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 — resolves credentials from the environment:19# ANTHROPIC_API_KEY, or ANTHROPIC_AUTH_TOKEN, or an `ant auth login` profile.20# Prefer this for local dev; don't hardcode a key.21client = anthropic.Anthropic()2223# Explicit API key (only when you must inject a specific key)24client = anthropic.Anthropic(api_key="your-api-key")25```2627---2829## Create an Environment3031```python32environment = client.beta.environments.create(33name="my-dev-env",34config={35"type": "cloud",36"networking": {"type": "unrestricted"},37},38)39print(environment.id) # env_...40```4142---4344## Create an Agent (required first step)4546> ⚠️ **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}`.4748### Minimal4950```python51# 1. Create the agent (reusable, versioned)52agent = client.beta.agents.create(53name="Coding Assistant",54model="claude-opus-4-8",55tools=[{"type": "agent_toolset_20260401", "default_config": {"enabled": True}}],56)5758# 2. Start a session59session = client.beta.sessions.create(60agent={"type": "agent", "id": agent.id, "version": agent.version},61environment_id=environment.id,62)63print(session.id, session.status)64```6566### With system prompt and custom tools6768```python69import os7071agent = client.beta.agents.create(72name="Code Reviewer",73model="claude-opus-4-8",74system="You are a senior code reviewer.",75tools=[76{"type": "agent_toolset_20260401"},77{78"type": "custom",79"name": "run_tests",80"description": "Run the test suite",81"input_schema": {82"type": "object",83"properties": {84"test_path": {"type": "string", "description": "Path to test file"}85},86"required": ["test_path"],87},88},89],90)9192session = client.beta.sessions.create(93agent={"type": "agent", "id": agent.id, "version": agent.version},94environment_id=environment.id,95title="Code review session",96resources=[97{98"type": "github_repository",99"url": "https://github.com/owner/repo",100"mount_path": "/workspace/repo",101"authorization_token": os.environ["GITHUB_TOKEN"],102"branch": "main",103}104],105)106```107108---109110## Send a User Message111112```python113client.beta.sessions.events.send(114session_id=session.id,115events=[116{117"type": "user.message",118"content": [{"type": "text", "text": "Review the auth module"}],119}120],121)122```123124> 💡 **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).125126---127128## Stream Events (SSE)129130```python131import json132133# Stream-first: open stream, then send while stream is live134with client.beta.sessions.events.stream(135session_id=session.id,136) as stream:137client.beta.sessions.events.send(138session_id=session.id,139events=[{"type": "user.message", "content": [{"type": "text", "text": "..."}]}],140)141for event in stream:142... # process events143144# Standalone stream iteration:145with client.beta.sessions.events.stream(146session_id=session.id,147) as stream:148for event in stream:149if event.type == "agent.message":150for block in event.content:151if block.type == "text":152print(block.text, end="", flush=True)153elif event.type == "agent.custom_tool_use":154# Custom tool invocation — session is now idle155print(f"\nCustom tool call: {event.name}")156print(f"Input: {json.dumps(event.input)}")157# Send result back (see below)158elif event.type == "session.status_idle":159print("\n--- Agent idle ---")160elif event.type == "session.status_terminated":161print("\n--- Session terminated ---")162break163```164165---166167## Provide Custom Tool Result168169```python170client.beta.sessions.events.send(171session_id=session.id,172events=[173{174"type": "user.custom_tool_result",175"custom_tool_use_id": "sevt_abc123",176"content": [{"type": "text", "text": "All 42 tests passed."}],177}178],179)180```181182---183184## Poll Events185186```python187events = client.beta.sessions.events.list(188session_id=session.id,189)190for event in events.data:191print(f"{event.type}: {event.id}")192```193194> ⚠️ **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).195196---197198## Full Streaming Loop with Custom Tools199200```python201import json202203204def run_custom_tool(tool_name: str, tool_input: dict) -> str:205"""Execute a custom tool and return the result."""206if tool_name == "run_tests":207# Your tool implementation here208return "All tests passed."209return f"Unknown tool: {tool_name}"210211212def run_session(client, session_id: str):213"""Stream events and handle custom tool calls."""214while True:215with client.beta.sessions.events.stream(216session_id=session_id,217) as stream:218tool_calls = []219for event in stream:220if event.type == "agent.message":221for block in event.content:222if block.type == "text":223print(block.text, end="", flush=True)224elif event.type == "agent.custom_tool_use":225tool_calls.append(event)226elif event.type == "session.status_idle":227break228elif event.type == "session.status_terminated":229return230231if not tool_calls:232break233234# Process custom tool calls235results = []236for call in tool_calls:237result = run_custom_tool(call.name, call.input)238results.append({239"type": "user.custom_tool_result",240"custom_tool_use_id": call.id,241"content": [{"type": "text", "text": result}],242})243244client.beta.sessions.events.send(245session_id=session_id,246events=results,247)248```249250---251252## Upload a File253254```python255with open("data.csv", "rb") as f:256file = client.beta.files.upload(257file=f,258)259260# Use in a session261session = client.beta.sessions.create(262agent={"type": "agent", "id": agent.id, "version": agent.version},263environment_id=environment.id,264resources=[{"type": "file", "file_id": file.id, "mount_path": "/workspace/data.csv"}],265)266```267268---269270## List and Download Session Files271272List files the agent wrote to `/mnt/session/outputs/` during a session, then download them.273274```python275# List files associated with a session276files = client.beta.files.list(277scope_id=session.id,278betas=["managed-agents-2026-04-01"],279)280for f in files.data:281print(f.filename, f.size_bytes)282# Download each file and save to disk283file_content = client.beta.files.download(f.id)284file_content.write_to_file(f.filename)285```286287> 💡 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.288289---290291## Session Management292293```python294# Get session details295session = client.beta.sessions.retrieve(session_id="sesn_011CZxAbc123Def456")296print(session.status, session.usage)297298# List sessions299sessions = client.beta.sessions.list()300301# Delete a session302client.beta.sessions.delete(session_id="sesn_011CZxAbc123Def456")303304# Archive a session305client.beta.sessions.archive(session_id="sesn_011CZxAbc123Def456")306```307308---309310## MCP Server Integration311312```python313# Agent declares MCP server (no auth here — auth goes in a vault)314agent = client.beta.agents.create(315name="MCP Agent",316model="claude-opus-4-8",317mcp_servers=[318{"type": "url", "name": "my-tools", "url": "https://my-mcp-server.example.com/sse"},319],320tools=[321{"type": "agent_toolset_20260401", "default_config": {"enabled": True}},322{"type": "mcp_toolset", "mcp_server_name": "my-tools"},323],324)325326# Session attaches vault(s) containing credentials for those MCP server URLs327session = client.beta.sessions.create(328agent=agent.id,329environment_id=environment.id,330vault_ids=[vault.id],331)332```333334See `shared/managed-agents-tools.md` §Vaults for creating vaults and adding credentials.335