Documentation
DocsAPI reference

Agent enrollment

Connect an agent from a developer machine. The agent asks for a code, a person approves it in the browser, and the agent exchanges the code for a credential. A withHuman extension, not part of the protocol.

Updated Sep 17, 2026

Enrollment is for an agent that runs on a developer machine, where nobody can hand it a credential in advance. The machine asks for a short code. A person approves that code in the browser, and the machine exchanges it for a credential of its own. No secret is ever copied by hand.

withhuman agent install <runtime> runs this flow for you. Use these endpoints to build the same flow into your own tool. Neither endpoint needs authentication.

This is a withHuman extension. It is not part of the Agent Approval Protocol, so other providers may not offer it.

How it works:

  1. Start an enrollment with the runtime and instance name. Optionally set requested_agent_name to require an existing parent agent. The response carries an enrollment_code for the machine, a user_code for the person, and a verification_uri.
  2. Show the person the verification URI and the user code. They sign in, enter the code, and select an existing agent or create one. This needs the agent.credential.issue permission, which owners and admins hold. Creating an agent also needs agent.write. Authorizing attaches the instance to the selected agent. A requested agent name fixes the target and never creates an agent automatically.
  3. In the meantime, exchange the enrollment code every few seconds. It returns 404 until the person has authorized the code. Then it returns the selected agent, the new instance and its credential. Store the credential's token; it is not shown again.

Both codes expire ten minutes after the enrollment starts. The response to the first call says exactly when. If that time passes, start over.

Start an enrollment

POST/auth/agent_enrollmentsNo auth

Starts an enrollment and returns two codes. The enrollment_code stays on the machine. The user_code is for a person to enter at the verification_uri. Both expire at expires_at, ten minutes after this call. The person selects an existing agent or creates one in the browser, then authorizes the instance. An optional requested agent name fixes the target within the organization they sign into.

Request

Request body

runtimestringrequired

The runtime being installed, independent of its parent agent.

Optional slug of an existing agent. The browser must authorize this target; it cannot create or substitute another agent.

instance_namestringrequired

A name for this instance, unique within the agent. The CLI defaults to the machine's hostname plus a unique suffix. Reviewers see it next to the agent's name.

Any JSON object to store with the instance, such as the hostname or operating system.

Response

Response codes

StatusBodyDescription
201EnrollmentCode

The codes and where to use them

400

A required field is missing or blank

Response body201

enrollment_codestringrequired

The secret the machine keeps. Send it to the exchange endpoint. Never show it to the person.

user_codestringrequired

The short code the person enters in the browser. Three letters, a hyphen, and four letters or digits. Case does not matter.

verification_uriurirequired

The page where the person enters the user code.

expires_atdate-timerequired

When both codes stop working. Start a new enrollment after this.

Example

POST /auth/agent_enrollments
curl -X POST "$WITHHUMAN_URL/auth/agent_enrollments" \
  -H "Content-Type: application/json" \
  -d '{
  "runtime": "claude-code",
  "requested_agent_slug": "codex",
  "instance_name": "eces-macbook",
  "instance_metadata": {
    "hostname": "eces-macbook",
    "os": "darwin"
  }
}'
201 response
{
  "enrollment_code": "whe_7c1f2a9e-4b3d-4f2e-9a1c-2d6e8b5f0a11_3f6b9c1d0e7a4b2c",
  "user_code": "K7M-3PQ2",
  "verification_uri": "https://app.withhuman.ai/connect/authorize",
  "expires_at": "2026-09-08T12:02:11Z"
}

Exchange an enrollment code

POST/auth/agent_enrollments/tokenNo auth

Exchanges an authorized enrollment code for the new instance and its credential. Call this every few seconds after starting an enrollment. It returns 404 until a person has authorized the user code. Once it succeeds, the code is used up and a second call returns 404 as well. The credential's token appears only in this response, so store it right away.

Request

Request body

enrollment_codestringrequired

The enrollment_code returned when the enrollment started.

Response

Response codes

StatusBodyDescription
200AgentEnrollmentCredential

The instance and its credential. The credential's token appears only in this response.

401

The enrollment code is not in the expected format

403

The agent or the instance has been disabled since it was authorized

404

The code has not been authorized yet, has expired, or has already been exchanged

Response body200

agentAgentrequired

An agent identity. The slug identifies it everywhere: URLs, role scopes, pipeline scopes, audit data and conditions. The name is a label for people.

One running copy of an agent.

Example

POST /auth/agent_enrollments/token
curl -X POST "$WITHHUMAN_URL/auth/agent_enrollments/token" \
  -H "Content-Type: application/json" \
  -d '{
  "enrollment_code": "whe_7c1f2a9e-4b3d-4f2e-9a1c-2d6e8b5f0a11_3f6b9c1d0e7a4b2c"
}'
200 response
{
  "agent": {
    "slug": "support-bot",
    "organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "created_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "name": "Support bot",
    "status": "active",
    "created_at": "2026-09-08T12:02:11Z",
    "updated_at": "2026-09-08T12:02:11Z",
    "archived_at": "2026-09-08T12:02:11Z"
  },
  "agent_instance": {
    "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "agent_slug": "string",
    "name": "ci-runner-07",
    "status": "active",
    "metadata": {
      "region": "eu-west"
    },
    "created_at": "2026-09-08T12:02:11Z",
    "last_seen_at": "2026-09-08T12:02:11Z"
  },
  "credential": {
    "id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
    "token": "whc_live_3f6b9c1d0e7a4b2c",
    "expires_at": "2026-09-08T12:02:11Z"
  }
}