Managed Agents — Onboarding Flow
Invoked via
/claude-api managed-agents-onboard? You're in the right place. Run the interview below — don't summarize it back to the user, ask the questions.
Use this when a user wants to set up a Managed Agent from scratch. Three steps: branch on know-vs-explore → configure the template → set up the session. End by emitting working code.
Read
shared/managed-agents-core.mdalongside this — it has full detail for each knob. This doc is the interview script, not the reference.
Claude Managed Agents is a hosted agent: Anthropic runs the agent loop on its orchestration layer and provisions a sandboxed container per session where the agent's tools execute. You supply the agent config and the environment config; the harness — event stream, sandbox orchestration, prompt caching, context compaction, and extended thinking — is handled for you.
What you supply:
- An agent config — tools, skills, model, system prompt. Reusable and versioned.
- An environment config — the sandbox your agent's tools execute in (networking, packages). Reusable across agents.
Each run of the agent is a session.
1. Know or explore?
Ask the user:
Do you already know the agent you want to build, or would you like to explore some common patterns first?
Explore path — show the patterns
Four shapes, same runtime code path (sessions.create() → sessions.events.send() → stream). Only the trigger and sink differ.
| Pattern | Trigger | Example | |
|---|---|---|---|
| Event-triggered | Webhook | GitHub PR push → CMA (GitHub tool) → Slack | # <------ MC maybe delete? |
| Scheduled | Cron | Daily brief: browser + GitHub + Jira → CMA → Slack | # <------ MC maybe delete? |
| Fire-and-forget PR | Human | Slack slash-command → CMA (GitHub tool) → PR passing CI | |
| Research + dashboard | Human | Topic → CMA (web search + frontend-design skill) → HTML dashboard |
Ask which shape fits, then continue with the Know path using it as the reference.
Know path — configure template
Three rounds. Batch the questions in each round; don't ask them one at a time.
Round A — Tools. Start here; it's the most concrete part. Three types; ask which the user wants (any combination):
| Type | What it is | How to guide |
|---|---|---|
Prebuilt Claude Agent tools (agent_toolset_20260401) | Ready-to-use: bash, read, write, edit, glob, grep, web_fetch, web_search. Enable all at once, or individually via enabled: true/false. | Recommend enabling the full toolset. List the 8 tools so the user knows what they're getting. Full detail: shared/managed-agents-tools.md → Agent Toolset. |
| MCP tools | Third-party integrations (GitHub, Linear, Asana, etc.) via mcp_toolset. Credentials live in a vault, not inline. | Ask which services. For each, walk through MCP server URL + vault credentials. Full detail: shared/managed-agents-tools.md → MCP Servers + Vaults. |
| Custom tools | The user's own app handles these tool calls — agent fires agent.custom_tool_use, the app sends a result message back. | Ask for each tool: name, description, input schema. The app code that handles the event is *their* code — don't generate it. Full detail: shared/managed-agents-tools.md → Custom Tools. |
Round B — Skills, files, and repos. What the agent has on hand when it starts.
*Skills* — two types; both work the same way — Claude auto-uses them when relevant. Max 20 per agent.
- [ ] Pre-built Agent Skills:
xlsx,docx,pptx,pdf. Reference by name. - [ ] Custom Skills: skills uploaded to the user's org via the Skills API. Reference by
skill_id+ optionalversion. If the skill doesn't exist yet, walk the user throughPOST /v1/skills+POST /v1/skills/{id}/versions(beta headerskills-2025-10-02). Full detail:shared/managed-agents-tools.md→ Skills + Skills API.
*GitHub repositories* — any repos the agent needs on-disk? For each:
- [ ] Repo URL (
https://github.com/org/repo) - [ ]
authorization_token(PAT or GitHub App token scoped to the repo) - [ ] Optional
mount_path(defaults to/workspace/<repo-name>) andcheckout(branch or SHA)
Emit as resources: [{type: "github_repository", url, authorization_token, ...}]. Full detail: shared/managed-agents-environments.md → GitHub Repositories.
‼️ PR creation needs the GitHub MCP server too.
github_repositorygives filesystem access only — to open PRs, also attach the GitHub MCP server in Round A and credential it via a vault. The workflow is: edit files in the mounted repo → push branch viabash→ create PR via the MCPcreate_pull_requesttool.
*Files* — any local files to seed the session with? For each:
- [ ] Upload via the Files API → persist
file_id - [ ] Choose a
mount_path— absolute, e.g./workspace/data.csv(parents auto-created; files mount read-only)
Emit as resources: [{type: "file", file_id, mount_path}]. Max 999 file resources. Agent working directory defaults to /workspace. Full detail: shared/managed-agents-environments.md → Files API.
Round C — Environment + identity:
- [ ] Networking: unrestricted internet from the container, or lock egress to specific hosts? (If locked, MCP server domains must be in
allowed_hostsor tools silently fail.) - [ ] Name?
- [ ] Job (one or two sentences — becomes the system prompt)?
- [ ] Model? (default
claude-opus-4-7)
2. Set up the session
Per-run. Points at the agent + environment, attaches credentials, kicks off.
Vault credentials (if the agent declared MCP servers):
- [ ] Existing vault, or create one? (
client.beta.vaults.create()+vaults.credentials.create())
Credentials are write-only, matched to MCP servers by URL, auto-refreshed. See shared/managed-agents-tools.md → Vaults.
Kickoff:
- [ ] First message to the agent?
Session creation blocks until all resources mount. Open the event stream before sending the kickoff. Stream is SSE; break on session.status_terminated, or on session.status_idle with a terminal stop_reason — i.e. anything except requires_action, which fires transiently while the session waits on a tool confirmation or custom-tool result (see shared/managed-agents-client-patterns.md Pattern 5). Usage lands on span.model_request_end. Agent-written artifacts end up in /mnt/session/outputs/ — download via files.list({scope_id: session.id, betas: ["managed-agents-2026-04-01"]}).
3. Emit the code
Go straight from the last interview answer to the code — no preamble about the setup-vs-runtime split, no "the critical thing to internalize…", no lecture about agents.create() being one-time. The two-block structure below already shows that; don't narrate it. Generate two clearly-separated blocks per language detected (Python/TS/cURL — see SKILL.md → Language Detection):
Block 1 — Setup (run once, store the IDs):
environments.create()→ persistenv_idagents.create()with everything from §Round A–C → persistagent_idandagent_version
Label: # ONE-TIME SETUP — run once, save the IDs to config/.env
Block 2 — Runtime (run on every invocation):
- Load
env_id+agent_idfrom config/env sessions.create(agent=AGENT_ID, environment_id=ENV_ID, resources=[...], vault_ids=[...])- Open stream,
events.send()the kickoff, loop untilsession.status_terminatedorsession.status_idle && stop_reason.type !== 'requires_action'(seeshared/managed-agents-client-patterns.mdPattern 5 for the full gate — do not break on baresession.status_idle)
⚠️ Never emit
agents.create()andsessions.create()in the same unguarded block. That teaches the user to create a new agent on every run — the #1 anti-pattern. If they need a single script, wrap agent creation inif not os.getenv("AGENT_ID"):.
Pull exact syntax from python/managed-agents/README.md, typescript/managed-agents/README.md, or curl/managed-agents.md. Don't invent field names.