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.
typescript/managed-agents/README.md
1# Managed Agents — TypeScript23> **Bindings not shown here:** This README covers the most common managed-agents flows for TypeScript. If you need a class, method, namespace, field, or behavior that isn't shown, WebFetch the TypeScript 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```bash10npm install @anthropic-ai/sdk11```1213## Client Initialization1415```typescript16import Anthropic from "@anthropic-ai/sdk";1718// Default (uses ANTHROPIC_API_KEY env var)19const client = new Anthropic();2021// Explicit API key22const client = new Anthropic({ apiKey: "your-api-key" });23```2425---2627## Create an Environment2829```typescript30const environment = await client.beta.environments.create(31{32name: "my-dev-env",33config: {34type: "cloud",35networking: { type: "unrestricted" },36},37},38);39console.log(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```typescript51// 1. Create the agent (reusable, versioned)52const agent = await client.beta.agents.create(53{54name: "Coding Assistant",55model: "claude-opus-4-7",56tools: [{ type: "agent_toolset_20260401", default_config: { enabled: true } }],57},58);5960// 2. Start a session61const session = await client.beta.sessions.create(62{63agent: { type: "agent", id: agent.id, version: agent.version },64environment_id: environment.id,65},66);67console.log(session.id, session.status);68```6970### With system prompt and custom tools7172```typescript73const agent = await client.beta.agents.create(74{75name: "Code Reviewer",76model: "claude-opus-4-7",77system: "You are a senior code reviewer.",78tools: [79{ type: "agent_toolset_20260401", default_config: { enabled: true } },80{81type: "custom",82name: "run_tests",83description: "Run the test suite",84input_schema: {85type: "object",86properties: {87test_path: { type: "string", description: "Path to test file" },88},89required: ["test_path"],90},91},92],93},94);9596const session = await client.beta.sessions.create(97{98agent: { type: "agent", id: agent.id, version: agent.version },99environment_id: environment.id,100title: "Code review session",101resources: [102{103type: "github_repository",104url: "https://github.com/owner/repo",105mount_path: "/workspace/repo",106authorization_token: process.env.GITHUB_TOKEN,107branch: "main",108},109],110},111);112```113114---115116## Send a User Message117118```typescript119await client.beta.sessions.events.send(120session.id,121{122events: [123{124type: "user.message",125content: [{ type: "text", text: "Review the auth module" }],126},127],128},129);130```131132> 💡 **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).133134---135136## Stream Events (SSE)137138```typescript139// Stream-first: open stream and send concurrently140const [events] = await Promise.all([141collectStream(session.id),142client.beta.sessions.events.send(143session.id,144{ events: [{ type: "user.message", content: [{ type: "text", text: "..." }] }] },145),146]);147148// Standalone stream iteration:149const stream = await client.beta.sessions.stream(150session.id,151);152153for await (const event of stream) {154switch (event.type) {155case "agent.message":156for (const block of event.content) {157if (block.type === "text") {158process.stdout.write(block.text);159}160}161break;162case "agent.custom_tool_use":163// Custom tool invocation — session is now idle164console.log(`\nCustom tool call: ${event.tool_name}`);165console.log(`Input: ${JSON.stringify(event.input)}`);166break;167case "session.status_idle":168console.log("\n--- Agent idle ---");169break;170case "session.status_terminated":171console.log("\n--- Session terminated ---");172break;173}174}175```176177---178179## Provide Custom Tool Result180181```typescript182await client.beta.sessions.events.send(183session.id,184{185events: [186{187type: "user.custom_tool_result",188custom_tool_use_id: "sevt_abc123",189content: [{ type: "text", text: "All 42 tests passed." }],190},191],192},193);194```195196---197198## Poll Events199200```typescript201const events = await client.beta.sessions.events.list(202session.id,203);204for (const event of events.data) {205console.log(`${event.type}: ${event.id}`);206}207```208209---210211## Full Streaming Loop with Custom Tools212213```typescript214function runCustomTool(toolName: string, toolInput: unknown): string {215if (toolName === "run_tests") {216// Your tool implementation here217return "All tests passed.";218}219return `Unknown tool: ${toolName}`;220}221222async function runSession(client: Anthropic, sessionId: string) {223while (true) {224const stream = await client.beta.sessions.stream(225sessionId,226);227228const toolCalls: Array<{ custom_tool_use_id: string; tool_name: string; input: unknown }> = [];229230for await (const event of stream) {231if (event.type === "agent.message") {232for (const block of event.content) {233if (block.type === "text") {234process.stdout.write(block.text);235}236}237} else if (event.type === "agent.custom_tool_use") {238toolCalls.push({239id: event.id,240tool_name: event.tool_name,241input: event.input,242});243} else if (event.type === "session.status_idle") {244break;245} else if (event.type === "session.status_terminated") {246return;247}248}249250if (toolCalls.length === 0) break;251252// Process custom tool calls253const results = toolCalls.map((call) => ({254type: "user.custom_tool_result" as const,255custom_tool_use_id: call.id,256content: [{ type: "text" as const, text: runCustomTool(call.tool_name, call.input) }],257}));258259await client.beta.sessions.events.send(260sessionId,261{ events: results },262);263}264}265```266267---268269## Upload a File270271```typescript272import fs from "fs";273274const file = await client.beta.files.upload({275file: fs.createReadStream("data.csv"),276});277278// Use in a session279const session = await client.beta.sessions.create(280{281agent: { type: "agent", id: agent.id, version: agent.version },282environment_id: environment.id,283resources: [{ type: "file", file_id: file.id, mount_path: "/workspace/data.csv" }],284},285);286```287288---289290## List and Download Session Files291292List files the agent wrote to `/mnt/session/outputs/` during a session, then download them.293294```typescript295import fs from "fs";296297// List files associated with a session298const files = await client.beta.files.list({299scope_id: session.id,300betas: ["managed-agents-2026-04-01"],301});302for (const f of files.data) {303console.log(f.filename, f.size_bytes);304305// Download and save to disk306const resp = await client.beta.files.download(f.id);307const buffer = Buffer.from(await resp.arrayBuffer());308fs.writeFileSync(f.filename, buffer);309}310```311312> 💡 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.313314---315316## Session Management317318```typescript319// Get session details320const session = await client.beta.sessions.retrieve("sesn_011CZxAbc123Def456");321console.log(session.status, session.usage);322323// List sessions324const sessions = await client.beta.sessions.list();325326// Delete a session327await client.beta.sessions.delete("sesn_011CZxAbc123Def456");328329// Archive a session330await client.beta.sessions.archive("sesn_011CZxAbc123Def456");331```332333---334335## MCP Server Integration336337```typescript338// Agent declares MCP server (no auth here — auth goes in a vault)339const agent = await client.beta.agents.create({340name: "MCP Agent",341model: "claude-opus-4-7",342mcp_servers: [343{ type: "url", name: "my-tools", url: "https://my-mcp-server.example.com/sse" },344],345tools: [346{ type: "agent_toolset_20260401", default_config: { enabled: true } },347{ type: "mcp_toolset", mcp_server_name: "my-tools" },348],349});350351// Session attaches vault(s) containing credentials for those MCP server URLs352const session = await client.beta.sessions.create({353agent: agent.id,354environment_id: environment.id,355vault_ids: [vault.id],356});357```358359See `shared/managed-agents-tools.md` §Vaults for creating vaults and adding credentials.360