Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build LLM-powered apps with the Anthropic Claude API or SDK across Python, TypeScript, Java, Go, Ruby, C#, and PHP.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
python/managed-agents/README.md
1# Managed Agents — Python23> **Bindings not shown here:** This README covers the most common managed-agents flows for Python. If you need a class, method, namespace, field, or behavior that isn't shown, WebFetch the Python SDK repo **or the relevant docs page** from `shared/live-sources.md` rather than guess. Do not extrapolate from cURL shapes or another language's SDK.45> **Agents are persistent — create once, reference by ID.** Store the agent ID returned by `agents.create` and pass it to every subsequent `sessions.create`; do not call `agents.create` in the request path. The Anthropic CLI is one convenient way to create agents and environments from version-controlled YAML — its URL is in `shared/live-sources.md`. The examples below show in-code creation for completeness; in production the create call belongs in setup, not in the request path.67## Installation89```bash10pip install anthropic11```1213## Client Initialization1415```python16import anthropic1718# Default (uses ANTHROPIC_API_KEY env var)19client = anthropic.Anthropic()2021# Explicit API key22client = anthropic.Anthropic(api_key="your-api-key")23```2425---2627## Create an Environment2829```python30environment = client.beta.environments.create(31name="my-dev-env",32config={33"type": "cloud",34"networking": {"type": "unrestricted"},35},36)37print(environment.id) # env_...38```3940---4142## Create an Agent (required first step)4344> ⚠️ **There is no inline agent config.** `model`/`system`/`tools` live on the agent object, not the session. Always start with `agents.create()` — the session only takes `agent={"type": "agent", "id": agent.id}`.4546### Minimal4748```python49# 1. Create the agent (reusable, versioned)50agent = client.beta.agents.create(51name="Coding Assistant",52model="claude-opus-4-7",53tools=[{"type": "agent_toolset_20260401", "default_config": {"enabled": True}}],54)5556# 2. Start a session57session = client.beta.sessions.create(58agent={"type": "agent", "id": agent.id, "version": agent.version},59environment_id=environment.id,60)61print(session.id, session.status)62```6364### With system prompt and custom tools6566```python67import os6869agent = client.beta.agents.create(70name="Code Reviewer",71model="claude-opus-4-7",72system="You are a senior code reviewer.",73tools=[74{"type": "agent_toolset_20260401"},75{76"type": "custom",77"name": "run_tests",78"description": "Run the test suite",79"input_schema": {80"type": "object",81"properties": {82"test_path": {"type": "string", "description": "Path to test file"}83},84"required": ["test_path"],85},86},87],88)8990session = client.beta.sessions.create(91agent={"type": "agent", "id": agent.id, "version": agent.version},92environment_id=environment.id,93title="Code review session",94resources=[95{96"type": "github_repository",97"url": "https://github.com/owner/repo",98"mount_path": "/workspace/repo",99"authorization_token": os.environ["GITHUB_TOKEN"],100"branch": "main",101}102],103)104```105106---107108## Send a User Message109110```python111client.beta.sessions.events.send(112session_id=session.id,113events=[114{115"type": "user.message",116"content": [{"type": "text", "text": "Review the auth module"}],117}118],119)120```121122> 💡 **Stream-first:** Open the stream *before* (or concurrently with) sending the message. The stream only delivers events that occur after it opens — stream-after-send means early events arrive buffered in one batch. See [Steering Patterns](../../shared/managed-agents-events.md#steering-patterns).123124---125126## Stream Events (SSE)127128```python129import json130131# Stream-first: open stream, then send while stream is live132with client.beta.sessions.stream(133session_id=session.id,134) as stream:135client.beta.sessions.events.send(136session_id=session.id,137events=[{"type": "user.message", "content": [{"type": "text", "text": "..."}]}],138)139for event in stream:140... # process events141142# Standalone stream iteration:143with client.beta.sessions.stream(144session_id=session.id,145) as stream:146for event in stream:147if event.type == "agent.message":148for block in event.content:149if block.type == "text":150print(block.text, end="", flush=True)151elif event.type == "agent.custom_tool_use":152# Custom tool invocation — session is now idle153print(f"\nCustom tool call: {event.tool_name}")154print(f"Input: {json.dumps(event.input)}")155# Send result back (see below)156elif event.type == "session.status_idle":157print("\n--- Agent idle ---")158elif event.type == "session.status_terminated":159print("\n--- Session terminated ---")160break161```162163---164165## Provide Custom Tool Result166167```python168client.beta.sessions.events.send(169session_id=session.id,170events=[171{172"type": "user.custom_tool_result",173"custom_tool_use_id": "sevt_abc123",174"content": [{"type": "text", "text": "All 42 tests passed."}],175}176],177)178```179180---181182## Poll Events183184```python185events = client.beta.sessions.events.list(186session_id=session.id,187)188for event in events.data:189print(f"{event.type}: {event.id}")190```191192> ⚠️ **Prefer the SDK over raw `requests`/`httpx`.** If you hand-roll a poll loop, don't assume `timeout=(5, 60)` or `httpx.Timeout(120)` caps total call duration — both are **per-chunk** read timeouts (reset on every byte), so a trickling response can block forever. For a hard wall-clock deadline, track `time.monotonic()` at the loop level and bail explicitly, or wrap with `asyncio.wait_for()`. See [Receiving Events](../../shared/managed-agents-events.md#receiving-events).193194---195196## Full Streaming Loop with Custom Tools197198```python199import json200201202def run_custom_tool(tool_name: str, tool_input: dict) -> str:203"""Execute a custom tool and return the result."""204if tool_name == "run_tests":205# Your tool implementation here206return "All tests passed."207return f"Unknown tool: {tool_name}"208209210def run_session(client, session_id: str):211"""Stream events and handle custom tool calls."""212while True:213with client.beta.sessions.stream(214session_id=session_id,215) as stream:216tool_calls = []217for event in stream:218if event.type == "agent.message":219for block in event.content:220if block.type == "text":221print(block.text, end="", flush=True)222elif event.type == "agent.custom_tool_use":223tool_calls.append(event)224elif event.type == "session.status_idle":225break226elif event.type == "session.status_terminated":227return228229if not tool_calls:230break231232# Process custom tool calls233results = []234for call in tool_calls:235result = run_custom_tool(call.tool_name, call.input)236results.append({237"type": "user.custom_tool_result",238"custom_tool_use_id": call.id,239"content": [{"type": "text", "text": result}],240})241242client.beta.sessions.events.send(243session_id=session_id,244events=results,245)246```247248---249250## Upload a File251252```python253with open("data.csv", "rb") as f:254file = client.beta.files.upload(255file=f,256)257258# Use in a session259session = client.beta.sessions.create(260agent={"type": "agent", "id": agent.id, "version": agent.version},261environment_id=environment.id,262resources=[{"type": "file", "file_id": file.id, "mount_path": "/workspace/data.csv"}],263)264```265266---267268## List and Download Session Files269270List files the agent wrote to `/mnt/session/outputs/` during a session, then download them.271272```python273# List files associated with a session274files = client.beta.files.list(275scope_id=session.id,276betas=["managed-agents-2026-04-01"],277)278for f in files.data:279print(f.filename, f.size_bytes)280# Download each file and save to disk281file_content = client.beta.files.download(f.id)282file_content.write_to_file(f.filename)283```284285> 💡 There's a brief indexing lag (~1–3s) between `session.status_idle` and output files appearing in `files.list`. Retry once or twice if the list is empty.286287---288289## Session Management290291```python292# Get session details293session = client.beta.sessions.retrieve(session_id="sesn_011CZxAbc123Def456")294print(session.status, session.usage)295296# List sessions297sessions = client.beta.sessions.list()298299# Delete a session300client.beta.sessions.delete(session_id="sesn_011CZxAbc123Def456")301302# Archive a session303client.beta.sessions.archive(session_id="sesn_011CZxAbc123Def456")304```305306---307308## MCP Server Integration309310```python311# Agent declares MCP server (no auth here — auth goes in a vault)312agent = client.beta.agents.create(313name="MCP Agent",314model="claude-opus-4-7",315mcp_servers=[316{"type": "url", "name": "my-tools", "url": "https://my-mcp-server.example.com/sse"},317],318tools=[319{"type": "agent_toolset_20260401", "default_config": {"enabled": True}},320{"type": "mcp_toolset", "mcp_server_name": "my-tools"},321],322)323324# Session attaches vault(s) containing credentials for those MCP server URLs325session = client.beta.sessions.create(326agent=agent.id,327environment_id=environment.id,328vault_ids=[vault.id],329)330```331332See `shared/managed-agents-tools.md` §Vaults for creating vaults and adding credentials.333