* Update claude-api skill with Managed Agents guidance * Replace OPUS_ID placeholder with concrete model string in claude-api skill * Replace remaining model placeholders with concrete model names and IDs
12 KiB
Managed Agents — Core Concepts
Architecture
Managed Agents is built around four core concepts:
| Concept | Endpoint | What it is |
|---|---|---|
| Agent | /v1/agents |
A persisted, versioned object defining the agent's capabilities and persona: model, system prompt, tools, MCP servers, skills. Must be created before starting a session. See the Agents section below. |
| Session | /v1/sessions |
A stateful interaction with an agent. References a pre-created agent by ID + an environment + initial instructions. Produces an event stream. |
| Environment | /v1/environments |
A template defining the configuration for container provisioning. |
| Container | N/A | An isolated compute instance where the agent's tools execute (bash, file ops, code). The agent loop does not run here — it runs on Anthropic's orchestration layer and acts on the container via tool calls. |
┌─────────────────────────────────────┐
│ Anthropic orchestration layer │
Agent (config) ───────▶│ (agent loop: Claude + tool calls) │
└──────────────┬──────────────────────┘
│ tool calls
▼
Environment (template) ──▶ Container (tool execution workspace)
│
Session ─┤
├── Resources (files, repos — mounted at startup)
├── Vault IDs (MCP credential references)
└── Conversation (event stream in/out)
Agent creation is a prerequisite. Sessions reference a pre-created agent by ID —
model/system/toolslive on the agent object, never on the session. Every flow starts withPOST /v1/agents.
Session Lifecycle
rescheduling → running ↔ idle → terminated
| Status | Description |
|---|---|
idle |
Agent has finished the current task, and is awaiting input. It's either waiting for input to continue working via a user.message or blocked awaiting a user.custom_tool_result or user.tool_confirmation. The stop_reason attached contains more information about why the Agent has stopped working. |
running |
Session has starting running, and the Agent is actively doing work. |
rescheduling |
Session is (re)scheduling after a retryable error has occurred, ready to be picked up by the orchestration system. |
terminated |
Session has terminated, entering an irreversible and unusable state. |
- Events can be sent when the session is
runningoridle. Messages are queued and processed in order. - The agent transitions
idle → runningwhen it receives a new event, then back toidlewhen done. - Errors surface as
session.errorevents in the stream, not as a status value.
Built-in session features
- Context compaction — if you approach max context, the API automatically condenses session history to keep the interaction going
- Prompt caching — historical repeated tokens are cached, reducing processing time and cost
- Extended thinking — on by default, returned as
agent.thinkingevents
Session operations
| Operation | Notes |
|---|---|
| List / fetch | Paginated list or single resource by ID |
| Update | Only title is updatable |
| Archive | Session becomes read-only. Not reversible. |
| Delete | Permanently deletes session, event history, container, and checkpoints. |
Sessions
A session is a running agent instance inside an environment.
Session Object
Key fields returned by the API:
| Field | Type | Description |
|---|---|---|
type |
string | Always "session" |
id |
string | Unique session ID |
title |
string | Human-readable title |
status |
string | idle, running, rescheduling, terminated |
created_at |
string | ISO 8601 timestamp |
updated_at |
string | ISO 8601 timestamp |
archived_at |
string | ISO 8601 timestamp (nullable) |
environment_id |
string | Environment ID |
agent |
object | Agent configuration |
resources |
array | Attached files and repos |
metadata |
object | User-provided key-value pairs (max 8 keys) |
usage |
object | Token usage statistics |
Creating a session
A session is meaningless without an agent. Sessions reference a pre-created agent by ID. Create the agent first via agents.create(), then reference it:
// 1. Create the agent (reusable, versioned)
const agent = await client.beta.agents.create(
{
name: "Coding Assistant",
model: "claude-opus-4-6",
system: "You are a helpful coding agent.",
tools: [{ type: "agent_toolset_20260401"}],
},
);
// 2. Start a session that references it
const session = await client.beta.sessions.create(
{
agent: agent.id, // string shorthand → latest version. Or: { type: "agent", id: agent.id, version: agent.version }
environment_id: environmentId,
title: "Hello World Session",
},
);
Session creation parameters:
| Field | Type | Required | Description |
|---|---|---|---|
agent |
string or object | Yes | String shorthand "agent_abc123" (latest version) or {type: "agent", id, version} |
environment_id |
string | Yes | Environment ID |
title |
string | No | Human-readable name (appears in logs/dashboards) |
resources |
array | No | Files or GitHub repos, mounted to the container at startup |
vault_ids |
array | No | Vault IDs (vlt_*) — MCP credentials with auto-refresh. See shared/managed-agents-tools.md → Vaults. |
metadata |
object | No | User-provided key-value pairs |
Agent configuration fields (passed to agents.create(), not sessions.create()):
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Human-readable name (1-256 chars) |
model |
string or object | Yes | Claude model ID (bare string, or {id, speed} object). All Claude 4.5+ models supported. |
system |
string | No | System prompt — defines the agent's behavior (up to 100K chars) |
tools |
array | No | Encompasses three kinds: (1) pre-built Claude Agent tools (agent_toolset_20260401), (2) MCP tools (mcp_toolset), and (3) custom client-side tools. Max 128. |
mcp_servers |
array | No | MCP server connections — standardized third-party capabilities (e.g. GitHub, Asana). Max 20, unique names. See shared/managed-agents-tools.md → MCP Servers. |
skills |
array | No | Customized "best-practices" context with progressive disclosure. Max 64. See shared/managed-agents-tools.md → Skills. |
description |
string | No | Description of the agent (up to 2048 chars) |
metadata |
object | No | Arbitrary key-value pairs (max 16, keys ≤64 chars, values ≤512 chars) |
Agents
This is where every Managed Agents flow begins. The agent object is a persisted, versioned configuration — you create it once, then reference it by ID every time you start a session. No agent → no session.
Agent Object
The API is flat — model, system, tools etc. are top-level fields, not wrapped in an agent:{} sub-object.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Human-readable name |
model |
string | Yes | Claude model ID |
system |
string | No | System prompt |
tools |
array | No | Agent toolset / MCP toolset / custom tools |
mcp_servers |
array | No | MCP server connections |
skills |
array | No | Skill references (max 64) |
description |
string | No | Description of the agent |
metadata |
object | No | Arbitrary key-value pairs |
Lifecycle: create once, run many, update in place
The agent is a persistent resource, not a per-run parameter. The intended pattern:
┌─ setup (once) ─────────┐ ┌─ runtime (every invocation) ─┐
│ agents.create() │ │ sessions.create( │
│ → store agent_id │ ──→ │ agent={type:..., id: ID} │
│ in config/env/db │ │ ) │
└────────────────────────┘ └──────────────────────────────┘
Anti-pattern: calling agents.create() at the top of every script run. This accumulates orphaned agent objects, pays create latency on every invocation, and defeats the versioning model. If you see agents.create() in a function that's called per-request or per-cron-tick, that's wrong — hoist it to one-time setup and persist the ID.
Versioning
Each POST /v1/agents/{id} (update) creates a new immutable version (numeric timestamp, e.g. 1772585501101368014). The agent's history is append-only — you can't edit a past version.
Why version:
- Reproducibility — pin a session to a known-good config:
{type: "agent", id, version: 3} - Safe iteration — update the agent without breaking sessions already running on the old version
- Rollback — if a new system prompt regresses, pin new sessions back to the prior version while you debug
version is optional. Omit it (or use the string shorthand agent="agent_abc123") to get the latest version at session-creation time. Pass it explicitly ({type: "agent", id, version: N}) to pin for reproducibility.
Getting the version to pin: agents.create() and agents.update() both return version in the response. Store it alongside agent_id. To fetch the current latest for an existing agent: GET /v1/agents/{id} → .version.
When to update vs create new: Update (POST /v1/agents/{id}) when it's conceptually the same agent with tweaked behavior (better prompt, extra tool). Create a new agent when it's a different persona/purpose. Rule of thumb: if you'd give it the same name, update.
Agent Endpoints
| Operation | Method | Path |
|---|---|---|
| Create | POST |
/v1/agents |
| List | GET |
/v1/agents |
| Get | GET |
/v1/agents/{id} |
| Update | POST |
/v1/agents/{id} |
| Archive | POST |
/v1/agents/{id}/archive |
Using an Agent in a Session
Reference the agent by string ID (latest version) or by object with an explicit version:
# String shorthand — uses the agent's latest version
session = client.beta.sessions.create(
agent=agent.id,
environment_id=environment_id,
)
# Or pin to a specific version (int)
session = client.beta.sessions.create(
agent={"type": "agent", "id": agent.id, "version": agent.version},
environment_id=environment_id,
)