# Agents API — Create, Configure, and Run Agents

REST reference for ACP agent profiles. Create, list, read, update, patch, delete, and run governed agents — with per-agent budget, tool, and delegation caps.

# Agents

An **agent profile** is the unit you govern: a model, a system prompt, the tools it may use, and hard caps on what one run may spend and do. These endpoints create, configure, and run them.

The Agent API is slug-free — ACP resolves your workspace from the key — so every path starts at `/api/v1/agents`.

```
https://api.agenticcontrolplane.com/api/v1/agents
```

All endpoints require a valid `gsk_` key ([Authentication](/docs/api/authentication)). Writes return `{ "ok": true, … }`; reads return the resource.

## The agent profile object

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `id` | string | — | Server-assigned. Stable identifier for the profile. |
| `name` | string | *required* | Human-readable name. Appears on every audit entry the agent produces. |
| `model` | string | *required* | The model the agent runs on, e.g. `claude-sonnet-4-6`. |
| `systemPrompt` | string | `"You are a helpful autonomous agent."` | The agent's instructions. |
| `description` | string | `""` | Optional notes. |
| `icon` | string | `""` | Optional icon identifier for the console. |
| `enabledTools` | string[] | `[]` | Tools the agent may call. Empty means none. Each call is still checked against workspace policy. |
| `scopes` | string[] | `[]` | Capability scopes granted to the agent's identity. |
| `maxToolCalls` | number | `50` | Hard cap on tool calls in a single run. |
| `maxBudgetCents` | number | `1000` | Hard spend cap per run, in cents. The run halts when reached. |
| `maxDurationMs` | number | `1800000` | Wall-clock cap per run (default 30 min). |
| `maxToolRounds` | number | `10` | Cap on orchestration rounds (model→tools→model cycles). |
| `delegatable` | boolean | `true` | Whether another agent may delegate to this one. |
| `canDelegate` | boolean | `false` | Whether this agent may delegate to others. |
| `maxDelegationDepth` | number | — | If set, caps how deep this agent's delegation chains may go. |

The caps are not advisory — they're enforced at runtime. A misconfigured prompt can't outspend `maxBudgetCents` or loop past `maxToolRounds`.

## List agents

```
GET /api/v1/agents
```

Returns every profile in the workspace, newest first.

```bash
curl -s "$ACP/api/v1/agents" \
  -H "Authorization: Bearer $ACP_KEY"
```

```json
{
  "ok": true,
  "profiles": [
    { "id": "a7Kf9_Qe2", "name": "Release Notes Writer", "model": "claude-sonnet-4-6", "maxBudgetCents": 50, "...": "..." }
  ]
}
```

## Get an agent

```
GET /api/v1/agents/{id}
```

```bash
curl -s "$ACP/api/v1/agents/a7Kf9_Qe2" \
  -H "Authorization: Bearer $ACP_KEY"
```

```json
{ "ok": true, "profile": { "id": "a7Kf9_Qe2", "name": "Release Notes Writer", "...": "..." } }
```

Returns `404` if no profile with that ID exists in this workspace.

## Create an agent

```
POST /api/v1/agents
```

`name` and `model` are required; everything else takes the defaults above.

```bash
curl -sX POST "$ACP/api/v1/agents" \
  -H "Authorization: Bearer $ACP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Campsite Scout",
    "model": "claude-haiku-4-5",
    "systemPrompt": "Watch for campsite cancellations and report them.",
    "enabledTools": ["http.get", "notifications.sendEmail"],
    "maxBudgetCents": 25,
    "maxToolCalls": 30,
    "maxDurationMs": 600000
  }'
```

```json
{ "ok": true, "id": "Rk3p_Lm8" }
```

## Update an agent

Two ways, depending on how strict you want to be.

### PUT — replace fields

```
PUT /api/v1/agents/{id}
```

Send any subset of the writable fields; each present field is written, absent fields are left untouched. Permissive — unknown fields are ignored.

```bash
curl -sX PUT "$ACP/api/v1/agents/Rk3p_Lm8" \
  -H "Authorization: Bearer $ACP_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "maxBudgetCents": 40 }'
```

### PATCH — validated update

```
PATCH /api/v1/agents/{id}
```

The strict path, and the one to prefer for automation. The body is validated at the boundary: **unknown fields are rejected**, `model` must be a recognized model, and numeric caps must fall within sane bounds. A bad request fails with `400` instead of silently writing garbage. `PATCH` is rate limited and audit-logged.

```bash
curl -sX PATCH "$ACP/api/v1/agents/Rk3p_Lm8" \
  -H "Authorization: Bearer $ACP_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "maxToolCalls": 50, "model": "claude-sonnet-4-6" }'
```

```json
{ "ok": true }
```

Use `PUT` for a quick interactive tweak; use `PATCH` when a script or pipeline is doing the writing and you want the guardrails.

## Delete an agent

```
DELETE /api/v1/agents/{id}
```

```bash
curl -sX DELETE "$ACP/api/v1/agents/Rk3p_Lm8" \
  -H "Authorization: Bearer $ACP_KEY"
```

```json
{ "ok": true }
```

Returns `404` if the profile doesn't exist.

## Run an agent

```
POST /api/v1/agents/{id}/run
```

Kicks off a governed run. Pass an `input`, optional `context`, and `stream` to get SSE events. Every tool call inside the run is checked against your workspace policy, and the whole run obeys the profile's caps.

```bash
curl -sX POST "$ACP/api/v1/agents/a7Kf9_Qe2/run" \
  -H "Authorization: Bearer $ACP_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "input": "Draft release notes for everything merged this week." }'
```

The request and response shape — `input`, `context` injection, streaming events, and run status — are documented in full on [Run triggers](/docs/agent-triggers).

## Common errors

| Status | When |
|--------|------|
| `400` | Missing `name` or `model` on create; an unknown field or out-of-bounds cap on `PATCH`. |
| `401` | Missing or invalid key. |
| `404` | No profile with that `id` in this workspace. |
| `429` | `PATCH` rate limit exceeded. Back off and retry. |

## Next

<div style="display:flex;gap:12px;flex-wrap:wrap;margin-top:8px;">
  <a href="/docs/api/policies" class="acp-btn acp-btn-primary" style="padding:12px 24px;">Govern it with Policies &rarr;</a>
  <a href="/docs/api/logs" class="acp-btn acp-btn-ghost" style="padding:12px 24px;">Read the Logs &rarr;</a>
</div>
