Agents
Agents are the AI systems that ask for approval. Each agent has instances, and each instance holds a credential it uses to call the API.
Tokens are returned once, when issued, and are never shown again.
Register an instance to get a credential directly, or create a provisioner token so each replica can create its own instance through the Agent Approval Protocol (AAP).
List agents
Returns the organization's agents. Each entry carries the agent's instance counts, when it was last seen, and how many requests it has made. Active agents come first, then disabled ones, then archived ones, each group sorted by name. Archived agents are left out unless status says otherwise.
An agent is live when one of its instances holds a credential that is neither expired nor revoked. last_seen_at is the newest authenticated call from any of its instances. Agents only call in when they have something to approve, so a quiet agent is not a broken one.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
status | query · enum | Which agents to return. One of live, archived, all |
limit | query · integer | How many agents to return. Defaults to 50. |
Response
Response codes
| Status | Body | Description |
|---|---|---|
200 | object | The agents |
400 | ErrorResponse |
|
403 | ErrorResponse | You cannot read agents |
Response body200
Example
curl -X GET "$WITHHUMAN_URL/api/v1/agents" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY"{
"agents": [
{
"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",
"instance_count": 0,
"live_instance_count": 0,
"last_seen_at": "2026-09-08T12:02:11Z",
"recent_request_count": 0,
"pending_request_count": 0,
"request_trend": [
0
]
}
]
}Create an agent
Creates an agent. An agent is a stable identity for one AI system, such as a support bot or a deploy assistant. Its slug is the identity: chosen here, never changed, never reused. Every agent owns one approval pipeline, created empty with the agent.
Creating an agent does not issue a credential. Register an instance, or create a provisioner token, to let it call the API.
Request
Request body
The agent's identity. Lowercase letters, digits, dots, underscores and hyphens, up to 63 characters. It cannot change and is never reused, so a slug an archived agent holds is refused.
A display name. Reviewers see it on every request the agent makes. It can be changed later and must be unique among the organization's live agents.
Response
Response codes
| Status | Body | Description |
|---|---|---|
201 | Agent | The new agent |
403 | ErrorResponse | You cannot create agents |
409 | ErrorResponse | The slug is taken by a live or archived agent ( |
429 | The organization is at its agent limit |
Response body201
The agent's identity, chosen once at creation. It never changes and is never reused, not even after the agent is archived.
The membership or organization-key actor that created the agent.
The display name. Reviewers see it on every request. Editable, and unique among the organization's live agents.
A disabled agent's instances cannot authenticate until it is enabled again. An archived agent is retired: nothing of it authenticates, nothing can be enrolled under it, and its status cannot change until it is restored.
One of active, disabled, archived
When the agent was archived. Present exactly when status is archived.
Example
curl -X POST "$WITHHUMAN_URL/api/v1/agents" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"slug": "support-bot",
"name": "Support bot"
}'{
"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"
}Retrieve an agent
Returns one agent with a page of instances, each instance's credentials, and its provisioner tokens. Secrets are never included. Instances are sorted by last seen, then creation time and id, newest first. Counts and connection state cover all instances, independent of the page and filters.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
slugrequired | path · string | The agent's slug: the identity chosen when it was created, never changed and never reused. |
instance_limit | query · integer | Number of instances in this page. |
instance_offset | query · integer | Number of matching instances to skip. |
instance_q | query · string | Case-insensitive literal substring of the instance name. |
instance_status | query · enum | Filter by whether an instance is enabled or disabled, independently of its credentials. One of active, disabled |
provisioner_limit | query · integer | Number of provisioner tokens in this page, sorted by issued time and id, newest first. |
provisioner_offset | query · integer | Number of matching provisioner tokens to skip. |
provisioner_q | query · string | Case-insensitive literal substring of the token identifier or displayed identifier suffix. Searches identifiers, never secrets. |
provisioner_status | query · enum | Token state, with revocation taking precedence over expiry. One of active, expired, revoked |
Response
Response codes
| Status | Body | Description |
|---|---|---|
200 | Agent | The agent |
400 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
403 | ErrorResponse | You cannot read agents |
404 | ErrorResponse | No such agent |
Response body200
The agent's identity, chosen once at creation. It never changes and is never reused, not even after the agent is archived.
The membership or organization-key actor that created the agent.
The display name. Reviewers see it on every request. Editable, and unique among the organization's live agents.
A disabled agent's instances cannot authenticate until it is enabled again. An archived agent is retired: nothing of it authenticates, nothing can be enrolled under it, and its status cannot change until it is restored.
One of active, disabled, archived
When the agent was archived. Present exactly when status is archived.
All provisioner tokens owned by this agent.
Tokens matching the current identifier and status filters before pagination.
All instances owned by this agent.
Active instances with at least one live credential across all pages.
Instances matching the current search and status filters before pagination.
All requests made by this agent.
One of human, api_key
The name of the human or organization key that created the agent.
The requested page of instances, sorted by last seen, creation time, and id, newest first.
The requested page of provisioner tokens, sorted by issued time and id, newest first. Secrets are never included.
Requests made in the last seven days.
Requests still waiting for a decision.
Example
curl -X GET "$WITHHUMAN_URL/api/v1/agents/{slug}" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY"{
"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",
"provisioner_count": 0,
"matching_provisioner_count": 0,
"instance_count": 0,
"live_instance_count": 0,
"matching_instance_count": 0,
"request_count": 0,
"created_by_actor_type": "human",
"created_by_display_name": "string",
"instances": [
{
"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",
"credentials": [
{
"id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"issued_at": "2026-09-08T12:02:11Z",
"expires_at": "2026-09-08T12:02:11Z",
"last_used_at": "2026-09-08T12:02:11Z",
"revoked_at": "2026-09-08T12:02:11Z"
}
],
"recent_request_count": 0,
"request_trend": [
0
]
}
],
"provisioners": [
{
"id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"agent_slug": "string",
"created_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"issued_at": "2026-09-08T12:02:11Z",
"expires_at": "2026-09-08T12:02:11Z",
"last_used_at": "2026-09-08T12:02:11Z",
"revoked_at": "2026-09-08T12:02:11Z"
}
],
"recent_request_count": 0,
"pending_request_count": 0
}Update an agent
Changes an agent's status or its display name, the two fields that can change after creation. The slug never changes. Who manages an agent is decided by the role assignments at the agent, not by a property of it.
Disabling an agent keeps its instances and credentials in place, but none of them can authenticate until the agent is enabled again. An archived agent is past both switches; restore it first.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
slugrequired | path · string | The agent's slug: the identity chosen when it was created, never changed and never reused. |
Request body
A new display name, unique among the organization's live agents. Audited as agent.renamed.
Response
Response codes
| Status | Body | Description |
|---|---|---|
200 | Agent | The updated agent |
400 | ErrorResponse | Neither status nor name was given, or the status is invalid |
403 | ErrorResponse | You cannot change agents |
404 | ErrorResponse | No such agent |
409 | ErrorResponse | The agent is archived ( |
Response body200
The agent's identity, chosen once at creation. It never changes and is never reused, not even after the agent is archived.
The membership or organization-key actor that created the agent.
The display name. Reviewers see it on every request. Editable, and unique among the organization's live agents.
A disabled agent's instances cannot authenticate until it is enabled again. An archived agent is retired: nothing of it authenticates, nothing can be enrolled under it, and its status cannot change until it is restored.
One of active, disabled, archived
When the agent was archived. Present exactly when status is archived.
Example
curl -X PATCH "$WITHHUMAN_URL/api/v1/agents/{slug}" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "active",
"name": "Support bot"
}'{
"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"
}Archive an agent
Archives the agent. Every live credential and provisioner token is revoked. Nothing is deleted: the agent is still listed with status=archived or all, it can still be retrieved with its instances and revoked credentials, and its requests and audit trail stay readable. But no instance or provisioner token can be created for it and its status cannot change. Its name is freed for a new agent; its slug is not, and never will be.
The agent's approval pipeline is archived with it: every revision is stamped and the active one deactivated. The archived revisions stay readable but cannot be activated. Restore the agent to bring the pipeline back.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
slugrequired | path · string | The agent's slug: the identity chosen when it was created, never changed and never reused. |
Response
Response codes
| Status | Body | Description |
|---|---|---|
204 | The agent is archived | |
401 | ErrorResponse | You are not signed in |
403 | ErrorResponse | You cannot change agents |
404 | ErrorResponse | No such agent |
409 | ErrorResponse | The agent is already archived ( |
Example
curl -X DELETE "$WITHHUMAN_URL/api/v1/agents/{slug}" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY"Restore an archived agent
Brings an archived agent back to active, together with its approval pipeline: every archived revision is unfrozen and the latest one becomes active again. Credentials and provisioner tokens revoked when the agent was archived stay revoked; register instances or connect them again to let it call the API. The name must still be free among the organization's live agents.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
slugrequired | path · string | The agent's slug: the identity chosen when it was created, never changed and never reused. |
Response
Response codes
| Status | Body | Description |
|---|---|---|
200 | Agent | The restored agent |
401 | ErrorResponse | You are not signed in |
403 | ErrorResponse | You cannot change agents |
404 | ErrorResponse | No such agent |
409 | ErrorResponse | The agent is not archived ( |
Response body200
The agent's identity, chosen once at creation. It never changes and is never reused, not even after the agent is archived.
The membership or organization-key actor that created the agent.
The display name. Reviewers see it on every request. Editable, and unique among the organization's live agents.
A disabled agent's instances cannot authenticate until it is enabled again. An archived agent is retired: nothing of it authenticates, nothing can be enrolled under it, and its status cannot change until it is restored.
One of active, disabled, archived
When the agent was archived. Present exactly when status is archived.
Example
curl -X POST "$WITHHUMAN_URL/api/v1/agents/{slug}/restore" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY"{
"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"
}Disable or enable an instance
Disables or re-enables one instance. A disabled instance keeps its credentials, but none of them can authenticate until it is enabled again. The agent and its other instances are not affected.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
idrequired | path · uuid | The instance's id. |
Request body
Response
Response codes
| Status | Body | Description |
|---|---|---|
200 | AgentInstance | The updated instance |
400 | ErrorResponse |
|
403 | ErrorResponse | You cannot change agents |
404 | ErrorResponse | No such instance |
409 | ErrorResponse | The instance's agent is archived ( |
Response body200
The slug of the agent this is an instance of.
Unique within the agent.
The JSON stored when the instance was created.
The last time this instance called the API.
Example
curl -X PATCH "$WITHHUMAN_URL/api/v1/agent_instances/{id}" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "active"
}'{
"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"
}Register an instance
Registers an instance of an agent and issues its credential. An instance is one running copy of the agent, such as a CI runner or a pod. The credential's token is returned once, in this response. Store it where the instance can read it. It cannot be retrieved again.
Use this when you set up an instance by hand. For a fleet that starts replicas itself, create a provisioner token instead and let each replica create its own instance through the Agent Approval Protocol (AAP).
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
slugrequired | path · string | The agent's slug: the identity chosen when it was created, never changed and never reused. |
Request body
A name for the instance, unique within the agent. Reviewers see it next to the agent's name.
Any JSON object to store with the instance, such as a region or pod name.
Response
Response codes
| Status | Body | Description |
|---|---|---|
201 | AgentInstanceCredential | The new instance and its credential. The token appears only in this response. |
403 | ErrorResponse | You cannot issue credentials |
404 | ErrorResponse | No such agent |
409 | ErrorResponse | The agent is archived ( |
Response body201
One running copy of an agent.
Example
curl -X POST "$WITHHUMAN_URL/api/v1/agents/{slug}/instances" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "ci-runner-07",
"metadata": {
"region": "eu-west"
}
}'{
"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"
}
}Create a provisioner token
Creates a provisioner token for an agent. A provisioner token lets a fleet or platform create instances of this agent on its own, each with a credential of its own, through the Agent Approval Protocol (AAP). It cannot create approval requests itself.
The token is returned once, in this response. It cannot be retrieved again.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
slugrequired | path · string | The agent's slug: the identity chosen when it was created, never changed and never reused. |
Response
Response codes
| Status | Body | Description |
|---|---|---|
201 | AgentProvisionerCredential | The provisioner and its token. The token appears only in this response. |
403 | ErrorResponse | You cannot issue credentials |
404 | ErrorResponse | No such agent |
409 | ErrorResponse | The agent is archived ( |
Response body201
A provisioner token as the agent page shows it. The token is never included.
Example
curl -X POST "$WITHHUMAN_URL/api/v1/agents/{slug}/provisioners" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY"{
"provisioner": {
"id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"organization_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"agent_slug": "string",
"created_by_actor_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"issued_at": "2026-09-08T12:02:11Z",
"expires_at": "2026-09-08T12:02:11Z",
"last_used_at": "2026-09-08T12:02:11Z",
"revoked_at": "2026-09-08T12:02:11Z"
},
"credential": {
"id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"token": "whc_live_3f6b9c1d0e7a4b2c",
"expires_at": "2026-09-08T12:02:11Z"
}
}Revoke a provisioner token
Revokes a provisioner token. It stops working immediately. The instances it already created, and their credentials, are not affected.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
idrequired | path · uuid | The provisioner's id. |
Response
Response codes
| Status | Body | Description |
|---|---|---|
204 | The token is revoked | |
403 | ErrorResponse | You cannot revoke credentials |
404 | ErrorResponse | No such provisioner |
Example
curl -X DELETE "$WITHHUMAN_URL/api/v1/agent-provisioners/{id}" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY"Revoke a credential
Revokes one instance credential. It stops working immediately. The instance stays registered, and the agent and its other instances are not affected.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
idrequired | path · uuid | The credential's id. |
Response
Response codes
| Status | Body | Description |
|---|---|---|
204 | The credential is revoked | |
403 | ErrorResponse | You cannot revoke credentials |
404 | ErrorResponse | No such credential |
Example
curl -X DELETE "$WITHHUMAN_URL/api/v1/agent-credentials/{id}" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY"Report the calling instance's tool catalogue
/api/v1/agent_instances/self/tool_catalogBearer tokenReplaces complete source snapshots in one discovery context. Failed sources retain their last successful definitions. The instance credential supplies organization and instance identity. No arguments or credentials belong in a report. This product endpoint is outside AAP. Maximum body size is 8 MiB.
Request
Request body
Stable opaque identifier for this local project or runtime context
Whether all configured sources in this context were enumerated
Response
Response codes
| Status | Body | Description |
|---|---|---|
204 | Catalogue report recorded | |
400 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
401 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
403 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
Example
curl -X PUT "$WITHHUMAN_URL/api/v1/agent_instances/self/tool_catalog" \
-H "Authorization: Bearer $WITHHUMAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"runtime": "string",
"discovery_context": "string",
"complete": true,
"sources": [
{
"source": "builtin",
"server": "string",
"complete": true,
"error": "string",
"tools": [
{
"name": "string",
"display_name": "string",
"description": "string",
"input_schema": {},
"annotations": {
"title": "string",
"read_only_hint": true,
"destructive_hint": true,
"idempotent_hint": true,
"open_world_hint": true
}
}
]
}
]
}'List known tool definitions
Returns definitions within the caller's agent scope. An edition's own tool source (the hosted gateway) is refreshed on read through a five-minute shared cache, with that edition's live grants applied. Failed refreshes retain the last successful definitions and mark their source stale. Catalogue information is advisory and never changes approval decisions.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
agent_slug | query · string | |
q | query · string | |
source | query · string | Only tools from this source: |
status | query · enum | One of available, unavailable, stale |
limit | query · integer | |
offset | query · integer | |
refresh | query · boolean | Bypass the edition's tool source discovery cache. Local tools require a CLI report. |
Response
Response codes
| Status | Body | Description |
|---|---|---|
200 | ToolCatalogPage | Known definitions and source discovery status |
400 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
401 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
403 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
Response body200
Example
curl -X GET "$WITHHUMAN_URL/api/v1/tool_catalog" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY"{
"tools": [
{
"name": "string",
"display_name": "string",
"description": "string",
"input_schema": {},
"annotations": {
"title": "string",
"read_only_hint": true,
"destructive_hint": true,
"idempotent_hint": true,
"open_world_hint": true
},
"id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"agent_slug": "string",
"agent_instance_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"instance_name": "string",
"discovery_context": "string",
"runtime": "string",
"source": "string",
"server": "string",
"available": true,
"stale": true,
"error": "string",
"schema_fingerprint": "string",
"last_seen_at": "2026-09-08T12:02:11Z",
"last_attempt_at": "2026-09-08T12:02:11Z"
}
],
"sources": [
{
"id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"agent_slug": "string",
"agent_instance_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"runtime": "string",
"discovery_context": "string",
"source": "string",
"server": "string",
"last_attempt_at": "2026-09-08T12:02:11Z",
"last_success_at": "2026-09-08T12:02:11Z",
"error": "string"
}
],
"total": 0,
"next_offset": 1
}Read a tool definition
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
idrequired | path · uuid | |
agent_slug | query · string |
Response
Response codes
| Status | Body | Description |
|---|---|---|
200 | ToolCatalogEntryDefinition | Definition and its discovery provenance |
401 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
403 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
404 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
Response body200
builtin, mcp, or a source an edition adds (the hosted gateway's gateway)
Example
curl -X GET "$WITHHUMAN_URL/api/v1/tool_catalog/{id}" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY"{
"name": "string",
"display_name": "string",
"description": "string",
"input_schema": {},
"annotations": {
"title": "string",
"read_only_hint": true,
"destructive_hint": true,
"idempotent_hint": true,
"open_world_hint": true
},
"id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"agent_slug": "string",
"agent_instance_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"instance_name": "string",
"discovery_context": "string",
"runtime": "string",
"source": "string",
"server": "string",
"available": true,
"stale": true,
"error": "string",
"schema_fingerprint": "string",
"last_seen_at": "2026-09-08T12:02:11Z",
"last_attempt_at": "2026-09-08T12:02:11Z"
}Read an agent's gateway tool accessHosted edition
Requires gateway.read and agent.read for the named agent. Unconfigured servers grant no access. All instances inherit these grants.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
slugrequired | path · string |
Response
Response codes
| Status | Body | Description |
|---|---|---|
200 | object | Saved grants, including no-access grants retained for revision checks |
401 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
403 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
404 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
501 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
Response body200
Example
curl -X GET "$WITHHUMAN_URL/api/v1/agents/{slug}/tool-access" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY"{
"grants": [
{
"server_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"server_slug": "string",
"mode": "none",
"tools": [
"string"
],
"revision": 1
}
]
}Replace an agent's access to a server's toolsHosted edition
Requires gateway.write and agent.read for the named agent. Grants exact tool names on this server, all current and future tools, or no tools. Supply the current revision, or zero for an unconfigured pair. A stale revision returns 412; an identical retry of the last write returns its committed result without another audit event. This version is the retry identity, so no Idempotency-Key is required. Archived agents and servers refuse edits. Inactive servers can be configured. The next MCP tool listing reflects changes; calls check live access before execution, including after approval. Already dispatched calls cannot be undone.
Request
Parameters
| Parameter | Type | Description |
|---|---|---|
slugrequired | path · string | |
server_slugrequired | path · string |
Request body
One of none, selected, all
Exact downstream tool names, meaningful only in selected mode. Empty for none or all; no wildcard matching.
Expected current version; zero for an unconfigured agent/server pair.
Response
Response codes
| Status | Body | Description |
|---|---|---|
200 | AgentToolAccess | Saved grant with its new revision |
400 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
401 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
403 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
404 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
409 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
412 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
501 | ErrorResponse | Error response. A 403 from a permission check carries ForbiddenDetails in error.details. |
Response body200
One of none, selected, all
Example
curl -X PUT "$WITHHUMAN_URL/api/v1/agents/{slug}/tool-access/{server_slug}" \
-H "Authorization: Bearer $WITHHUMAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "none",
"tools": [
"string"
],
"revision": 0
}'{
"server_id": "7ab8c8ec-7b2d-4fd6-9b52-752f9515eb71",
"server_slug": "string",
"mode": "none",
"tools": [
"string"
],
"revision": 1
}