SDK:Agent 托管部署

将 Agent 部署为在线服务

🌐 查看英文原文 | 源码 Notebook


托管你的 Agent

你在 notebook 00 中构建了一个研究 Agent。它在你的笔记本电脑上运行。现在其他人需要使用它:一个队友、一个 cron 任务、一个 Web 应用、一个客户。这意味着它必须在你的终端以外的某个地方运行,保持运行,在重启后保持对话活跃,并且不泄露你的 API 密钥。

本 notebook 采用完全相同的 Agent,并通过三个层级进行部署:

层级 运行位置 何时使用
1. Docker 你的机器 / 单个 VM 开发循环、内部工具、单租户
2. Modal 托管 serverless 你想要一个 URL 和 scale-to-zero,而无需管理基础设施
3. Kubernetes 你自己的集群 多租户、受监管环境、完全控制

Agent 代码、容器镜像和 HTTP 接口在所有三个层级中是相同的。只有容器周围的操作机制发生变化。一旦 Agent 被容器化并位于稳定接口之后,选择主机就是一个部署决策而不是重写。

端到端运行本 notebook 的成本: 大约 1-2 美元的 Anthropic API 调用费用加上几分钱的 Modal 计算费用。每个层级都有清理步骤。

所有部署代码位于本 notebook 旁边的 hosting/ 中。

开始之前:你应该使用 Agent SDK 吗?

如果你正在构建面向客户的聊天产品,请先查看 Claude Managed Agents。你可以获得开箱即用的托管、会话和 UI,并且可以跳过本 notebook 的大部分内容。

当你需要编程控制时,Agent SDK 是正确的选择:批量和作业型 Agent、内部工具、嵌入你自己后端的 Agent,或你必须拥有基础设施的受监管环境。如果这适用于你,请继续阅读。

心智模型

三个名词需要分清:

  • 进程是一个加载了 SDK 的运行中的 Python 解释器。它与 Anthropic API 通信。
  • 会话是一个对话:SDK 写入磁盘的 prompt 历史、工具调用和结果,以便你稍后 resume= 它。
  • 容器是一个打包的进程加上其文件系统:你的 Agent 代码、SDK、Node 和会话存放的地方。

与进程内 SDK(OpenAI Agents SDK、Google ADK)不同,在后者的”Agent”是你在 Web 服务器中实例化的对象,而 Claude Agent SDK Agent 就是一个进程。这使得隔离变得简单(一个容器 = 一个爆炸半径),但意味着托管是一个分布式系统问题,而不是 pip install 问题。

每个部署,无论在哪个层级,都必须完成相同的四项工作:

┌────────────────────────────────────────────────────────────────────┐
│  caller ──► gateway ──► [ spawn | route ] ──► agent container ──► API
│                 │                                     │
│                 └── auth (not the agent's job)        └── /data  (persist)
│                                                                      │
│  orchestrator ──────────────── lifecycle ────────────────────────────┘
└────────────────────────────────────────────────────────────────────┘
  1. 当工作到达时生成容器
  2. 将每个请求路由到拥有该会话的容器
  3. 生命周期:杀死空闲容器,重启崩溃的容器
  4. 持久化会话记录,使重启不会丢失对话

层级 1 手动完成所有四项。层级 2 将生成+生命周期委托给 Modal。层级 3 将所有四项委托给 Kubernetes 加一个小型网关。Agent 容器永远不会改变。

我们正在部署的 Agent

我们正在复用来自 notebook 00 的 research_agent/agent.py,即带有 WebSearch 和 Read 的单行研究 Agent。如果你还没有做 notebook 00,请先做它;本 notebook 假设 Agent 已经可以工作。

hosting/ 唯一添加的是一个轻量 HTTP 服务器和一个 Dockerfile。系统提示直接来自 research_agent.agent;我们导入它而不是复制它。一个故意的区别:托管服务器将工具列表缩小到仅 WebSearch。服务器上没有上传路径,因此 Read 能触及的唯一文件是其他会话的记录和容器自身的环境,而 prompt 注入的 Web 结果可能引导 Agent 泄露它们。server.py 中的注释详细说明了理由。

from research_agent.agent import DEFAULT_MODEL, RESEARCH_SYSTEM_PROMPT

print(f"model: {DEFAULT_MODEL}")
print(RESEARCH_SYSTEM_PROMPT)
model: claude-opus-4-6
You are a research agent specialized in AI.

When providing research findings:
- Always include source URLs as citations
- Format citations as markdown links: [Source Title](URL)
- Group sources in a "Sources:" section at the end of your response

设置

创建包含你的 API 密钥的 hosting/.env。此文件被 gitignore。

%%bash
test -f hosting/.env || cp hosting/.env.example hosting/.env
echo 'Edit hosting/.env and set ANTHROPIC_API_KEY, then re-run this cell.'
grep -q '^ANTHROPIC_API_KEY=sk-ant-' hosting/.env \
  && ! grep -q 'your-key-here' hosting/.env \
  && echo '✅ key looks set'
Edit hosting/.env and set ANTHROPIC_API_KEY, then re-run this cell.
✅ key looks set

层级 1a — 临时:一个 prompt,一个容器,完成

最简单的部署:一个容器在一个环境变量的 prompt 上运行 Agent 一次,打印结果并退出。没有服务器、没有会话、没有状态。

模型说明: 托管层默认使用 claude-sonnet-4-6,以便你在学习本 notebook 时测试请求保持低成本。在 hosting/.env 中设置 MODEL=claude-opus-4-6 以完全匹配 notebook 00 的配置。

这对于很多实际工作来说已经足够了:发票处理、夜间报告生成、批量翻译、一次性分析。如果你的 Agent 的工作是”接收输入、产生输出、停止”,你不需要超过本部分的内容。

Dockerfile 打包了 Agent、SDK 和 SDK 底层驱动的 Claude Code CLI。构建上下文是 claude_agent_sdk/(此目录),而不是 hosting/,因为镜像还需要 research_agent/ 和 utils/:

%%bash
docker build -f hosting/Dockerfile -t research-agent . | tail -n 3
#0 building with "orbstack" instance using docker driver

#1 [internal] load build definition from D
ockerfile
#1 transferring dockerfile: 2.30kB done
#1 DONE 0.0s

#2 resolve image config for docker-i
mage://docker.io/docker/dockerfile:1
#2 DONE 0.6s

#3 docker-image://docker.io/docker/dockerfile:1@sha256:87999aa3d42bdc6bea60565083ee17e86d1f3339802f
543c0d03998580f9cb89
#3 CACHED

#4 [internal] load metadata for docker.io/library/python:3.11-slim
#4 DONE 0.5s

#5 [1/9] FROM docker.io/library/python:3.11-slim@sha256:a3ab0b966bc4e91546a033e22093cb840908979487a
9fc0e6e38295747e49ac0
#5 DONE 0.0s

#6 [internal] load build context
#6 transferring context: 814.53
kB 0.0s done
#6 DONE 0.0s

#7 [3/9] WORKDIR /app
#7 CACHED

#8 [6/9] COPY research_agent/ ./research
_agent/
#8 CACHED

#9 [7/9] COPY utils/ ./utils/
#9 CACHED

#10 [2/9] RUN apt-get update  && apt-get
 install -y --no-install-recommends curl ca-certificates  && curl -fsSL https://deb.nodesource.com/s
etup_20.x | bash -  && apt-get install -y --no-install-recommends nodejs  && npm install -g @anthrop
ic-ai/claude-code@2.1.140  && apt-get purge -y curl  && apt-get autoremove -y  && rm -rf /var/lib/ap
t/lists/*
#10 CACHED

#11 [4/9] COPY hosting/requirements.txt ./hosting/requirements.txt
#11 CACHED

#12 [5/9] RUN pip install --no-cache-dir -r hosting/requirements.txt
#12 CACHED

#13 [8/9] COPY hos
ting/server.py hosting/run_once.py hosting/entrypoint.sh ./hosting/
#13 CACHED

#14 [9/9] RUN chmod
+x hosting/entrypoint.sh  && touch hosting/__init__.py
#14 CACHED

#15 exporting to image
#15 export
ing layers done
#15 writing image sha256:b77b20f557cef5e4b9ef01212f3ba3a0895ee97ff8e31f79d9e1dc0cfb7
414f5 done
#15 naming to docker.io/library/research-agent done
#15 DONE 0.0s
%%bash
docker run --rm --env-file hosting/.env \
  -e PROMPT='What is the Claude Agent SDK, in one paragraph?' \
  research-agent
🤖 Thinking...
🤖 Using: ToolSearch()
✓ Tool completed
🤖 Thinking...
🤖 Using: WebSearch()
✓ Tool completed
🤖 Using: WebSearch()
✓ Tool completed
🤖 Thinking...
The **Claude Agent SDK** is a developer toolkit from Anthropic — available in Python and TypeScrip
t — that gives developers access to the same tools, agent loop, and context management that power
Claude Code, enabling them to build fully autonomous AI agents that can read files, run terminal com
mands, search the web, edit code, and interact with external APIs without requiring developers to ma
nually implement a tool execution loop. Unlike the standard Claude API (where the developer must han
dle tool-use loops themselves), the Agent SDK lets Claude manage the agentic loop autonomously, maki
ng it straightforward to build sophisticated agents such as finance assistants, personal assistants,
 customer support bots, and deep research agents that can operate with minimal human intervention.
---

**Sources:**
- [Agent SDK Overview – Claude Code Docs](https://code.claude.com/docs/en/agent-
sdk/overview)
- [Building Agents with the Claude Agent SDK – Anthropic Engineering](https://www.an
thropic.com/engineering/building-agents-with-the-claude-agent-sdk)
- [Agent SDK Overview – Anthrop
ic API Docs](https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-overview)
- [claude-agent-sdk-py
thon – GitHub](https://github.com/anthropics/claude-agent-sdk-python)
- [claude-agent-sdk-typescri
pt – GitHub](https://github.com/anthropics/claude-agent-sdk-typescript)

就是这样。entrypoint.sh 没有看到 serve 参数,因此 run_once.py 使用 $PROMPT 调用 research_agent.agent.send_query() 并退出 0。

这足够的情况: 每次调用都独立的作业型任务。从 cron、队列工作器、CI 步骤或任何其他你会运行 CLI 的地方运行它。


层级 1b — 混合:添加服务器使对话可以继续

临时模式无法保持对话;每次 docker run 都启动一个新会话。对于聊天型 Agent,你需要一个长期运行的进程来接受后续消息并每次恢复正确的会话。

hosting/server.py 是一个约 100 行的 FastAPI 应用,恰好做这些事。该接口是每个层级都遵守的契约:

GET  /health                            → 200 {"status": "ok"}
POST /sessions/{session_id}/messages    → 200 text/event-stream of SDK messages

server.py 中有两点值得注意:

  • 服务器没有认证。 文档字符串大声说明了这一点。认证是网关的工作(层级 3 展示了它的位置)。服务器验证 session_id 格式并信任调用者。
  • 它维护一个从你的 session_id 到 SDK 内部 ID 的小映射。 SDK 生成自己的 session ID;你无法选择。服务器从第一轮的 ResultMessage 中获知 SDK 的 ID,并在后续中将其传递给 resume=。该映射与记录一起持久化在 /data 下。

使用 docker-compose 启动它,它还将 ./sessions 挂载到 /data,使记录在重启后存活:

%%bash
cd hosting/docker && docker compose up --build -d
sleep 3
curl -s http://localhost:8000/health
 Image research-agent Building
#1 [internal] load local bake definitions
#1 reading from stdin 579B done
#1 DONE 0.0s

#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 2.30kB done
#2 DONE 0.0s

#3 resolve image config for docker-image://docker.io/docker/dockerfile:1
#3 DONE 0.2s

#4 docker-image://docker.io/docker/dockerfile:1@sha256:87999aa3d42bdc6bea60565083ee17e86d1f3339802f
543c0d03998580f9cb89
#4 CACHED

#5 [internal] load metadata for docker.io/library/python:3.11-slim
#5 DONE 0.2s

#6 [1/9] FROM docker.io/library/python:3.11-slim@sha256:a3ab0b966bc4e91546a033e22093cb840908979487a
9fc0e6e38295747e49ac0
#6 DONE 0.0s

#7 [internal] load build context
#7 transferring context: 494B d
one
#7 DONE 0.0s

#8 [2/9] RUN apt-get update  && apt-get install -y --no-install-recommends curl ca
-certificates  && curl -fsSL https://deb.nodesource.com/setup_20.x | bash -  && apt-get install -y -
-no-install-recommends nodejs  && npm install -g @anthropic-ai/claude-code@2.1.140  && apt-get purge
 -y curl  && apt-get autoremove -y  && rm -rf /var/lib/apt/lists/*
#8 CACHED

#9 [3/9] WORKDIR /app
#9 CACHED

#10 [4/9] COPY hosting/requirements.txt ./hosting/requirements.txt
#10 CACHED

#11 [7/9]
COPY utils/ ./utils/
#11 CACHED

#12 [5/9] RUN pip install --no-cache-dir -r hosting/requirements.tx
t
#12 CACHED

#13 [6/9] COPY research_agent/ ./research_agent/
#13 CACHED

#14 [8/9] COPY hosting/se
rver.py hosting/run_once.py hosting/entrypoint.sh ./hosting/
#14 CACHED

#15 [9/9] RUN chmod +x host
ing/entrypoint.sh  && touch hosting/__init__.py
#15 CACHED
#16 exporting to image
#16 exporting layers done
#16 writing image sha256:feb4e050b95b69f43fa027a2b5
a8c87974fba11cd890ba7c669db4aaa459fca0 done
#16 naming to docker.io/library/research-agent done
#16
DONE 0.0s

#17 resolving provenance for metadata file
#17 DONE 0.0s
 Image research-agent Built
 Network docker_default Creating
 Network docker_default Created
 Container docker-research-agent-1 Creating
 Container docker-research-agent-1 Created
 Container docker-research-agent-1 Starting
 Container docker-research-agent-1 Started
{"status":"ok"}

发送一个 prompt 并流式传输响应(-N 禁用 curl 的缓冲,使你能看到到达的事件):

%%bash
curl -N -s -X POST http://localhost:8000/sessions/demo-1/messages \
  -H 'Content-Type: application/json' \
  -d '{"prompt":"What are the three most interesting AI agent trends right now?"}'
event: message
data: {"subtype": "init", "data": {"type": "system", "subtype": "init", "cwd": "/app", "session_id": "77597263-a169-4236-b3d4-8ec14f90fd2b", "tools": ["Task", "TaskOutput", "Bash", "Glob", "Grep", "ExitPlanMode", "Read", "Edit", "Write", "N … [truncated]

event: message
data: {"content": [{"id": "toolu_01LpCYD1mQgNAmiDYq55RHyC", "name": "WebSearch", "input": {"query": "AI agent trends 2026"}}], "model": "claude-sonnet-4-6", "parent_tool_use_id": null, "error": null, "usage": {"input_tokens": 685, "cache_cr … [truncated]

[... 6 events omitted — thinking blocks, tool loading, and web-search result payloads ...]

event: message
data: {"content": [{"text": "Great question! Based on the latest research and reports, here are the **three most interesting AI agent trends** right now in 2026:\n\n---\n\n## \ud83e\udd1d 1. Multi-Agent Systems & Orchestration\nThe era of the single, all-purpose AI agent is giving way to **coordinat … [truncated]

event: message
data: {"subtype": "success", "duration_ms": 20980, "duration_api_ms": 20812, "is_error": false, "num_turns": 3, "session_id": "77597263-a169-4236-b3d4-8ec14f90fd2b", "stop_reason": "end_turn", "total_cost_usd": 0.0502906, "usage": {"input_t … [truncated]

event: done
data:

现在向相同的 session_id 发送后续消息。Agent 记得第一轮,因为服务器恢复了会话:

%%bash
curl -N -s -X POST http://localhost:8000/sessions/demo-1/messages \
  -H 'Content-Type: application/json' \
  -d '{"prompt":"Tell me more about the second one."}'
event: message
data: {"subtype": "init", "data": {"type": "system", "subtype": "init", "cwd": "/app", "session_id": "77597263-a169-4236-b3d4-8ec14f90fd2b", "tools": ["Task", "TaskOutput", "Bash", "Glob", "Grep", "ExitPlanMode", "Read", "Edit", "Write", "N … [truncated]

event: message
data: {"content": [{"id": "toolu_01YU5m6b66Kh6GcSN1Kbv7zq", "name": "WebSearch", "input": {"query": "context engineering AI agents 2026 techniques best practices"}}], "model": "claude-sonnet-4-6", "parent_tool_use_id": null, "error": null, … [truncated]

[... 5 events omitted — thinking blocks, tool loading, and web-search result payloads ...]

event: message
data: {"content": [{"text": "## \ud83e\uddf1 Deep Dive: Context Engineering\n\nContext engineering has quickly become **the defining AI skill of 2026**. Here's a thorough breakdown:\n\n---\n\n### What Is It, Exactly?\n\nContext engineering is the discipline of **designing what information an AI mode … [truncated]

event: message
data: {"subtype": "success", "duration_ms": 26895, "duration_api_ms": 26791, "is_error": false, "num_turns": 3, "session_id": "77597263-a169-4236-b3d4-8ec14f90fd2b", "stop_reason": "end_turn", "total_cost_usd": 0.08444499999999999, "usage": … [truncated]

event: done
data:

重启容器并发送另一个后续消息。卷挂载保留了 /data,因此对话得以保存:

%%bash
cd hosting/docker && docker compose restart && sleep 3
curl -N -s -X POST http://localhost:8000/sessions/demo-1/messages \
  -H 'Content-Type: application/json' \
  -d '{"prompt":"Summarize what we have discussed so far."}'
 Container docker-research-agent-1 Restarting
 Container docker-research-agent-1 Started
event: message
data: {"subtype": "init", "data": {"type": "system", "subtype": "init", "cwd": "/app
", "session_id": "77597263-a169-4236-b3d4-8ec14f90fd2b", "tools": ["Task", "TaskOutput", "Bash", "Gl
ob", "Grep", "ExitPlanMode", "Read", "Edit", "Write", "NotebookEdit", "WebFetch", "TodoWrite", "WebS
earch", "TaskStop", "AskUserQuestion", "Skill", "EnterPlanMode", "EnterWorktree", "ExitWorktree", "C
ronCreate", "CronDelete", "CronList", "RemoteTrigger", "ToolSearch"], "mcp_servers": [], "model": "c
laude-sonnet-4-6", "permissionMode": "default", "slash_commands": ["update-config", "debug", "simpli
fy", "batch", "loop", "schedule", "claude-api", "compact", "context", "cost", "heapdump", "init", "p
r-comments", "release-notes", "review", "security-review", "insights"], "apiKeySource": "ANTHROPIC_A
PI_KEY", "claude_code_version": "2.1.81", "output_style": "default", "agents": ["general-purpose", "
statusline-setup", "Explore", "Plan"], "skills": ["update-config", "debug", "simplify", "batch", "lo
op", "schedule", "claude-api"], "plugins": [], "uuid": "753db5ec-c432-4634-abb4-048eda1e6acd", "fast
_mode_state": "off"}, "type": "SystemMessage"}
event: message
data: {"content": [{"thinking": "The user wants a summary of our conversation so far
. No tools needed for this.", "signature": "EtYBCmcIDRgCIkBg3e+9ruTNyro9yQA8kMewU6BzRzlQR/MAvKWUy2kk
CH0rl6bddOJ1gJBmcF4L3GPf/pgLkImzUqg1JV4RfUNgKAEyEWNsYXVkZS1zb25uZXQtNC02OABCCHRoaW5raW5nEgxfs2ACXCyv
Me8OUvQaDA4MA9sG7f/fI1we2yIwQvNMoFyTGl2/Ps+arqqgLoLYtySrkCOrgNmwcZFIbzQOFWiSJIcsqA7inm8T8n90Kh0wlw1t
FbJw0suOLM6okhU+eNc0gCr59ENLuBeZhBgC"}], "model": "claude-sonnet-4-6", "parent_tool_use_id": null, "
error": null, "usage": {"input_tokens": 7108, "cache_creation_input_tokens": 0, "cache_read_input_to
kens": 0, "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, "outpu
t_tokens": 0, "service_tier": "standard", "inference_geo": "global"}, "type": "AssistantMessage"}
event: message
data: {"content": [{"text": "Sure! Here's a summary of our conversation so far:\n\n-
--\n\n### \ud83d\uddc2\ufe0f Conversation Summary\n\n**1. Top 3 AI Agent Trends (May 2026)**\nYou as
ked about the most interesting AI agent trends right now. Based on web research, the three highlight
ed were:\n\n- \ud83e\udd1d **Multi-Agent Systems & Orchestration** \u2014 Specialized agents working
 in coordinated teams, replacing single all-purpose agents. Gartner reported a 1,445% surge in multi
-agent system inquiries.\n- \ud83e\uddf1 **Context Engineering** \u2014 Designing the full informati
on architecture around an agent (memory, retrieval, data sources, token budgets) to ensure reliable,
 high-quality outputs at scale.\n- \ud83d\udee1\ufe0f **Governance & Deterministic Guardrails** \u20
14 Shifting from viewing governance as a compliance burden to an enabler, combining dynamic AI with
human oversight to safely deploy agents in high-stakes scenarios.\n\n---\n\n**2. Deep Dive into Cont
ext Engineering**\nYou asked for more detail on the second trend. Key takeaways included:\n\n- **Con
text Engineering \u2260 Prompt Engineering** \u2014 It's a broader discipline covering the entire in
formation lifecycle of an agent.\n- **Core techniques** include RAG, memory management, context comp
ression, context offloading, state persistence, and tool output structuring.\n- **Why it matters for
 agents** \u2014 Unlike chatbots, agents accumulate context over many steps, making careful informat
ion design critical to avoid context rot and token blowouts.\n- **RAG alone isn't enough** \u2014 77
% of IT leaders agree RAG is insufficient for production AI on its own.\n- Proper context engineerin
g can improve agent task completion rates dramatically (e.g., **83% \u2192 96%**).\n\n---\n\nWould y
ou like to explore any of these topics further?"}], "model": "claude-sonnet-4-6", "parent_tool_use_i
d": null, "error": null, "usage": {"input_tokens": 7108, "cache_creation_input_tokens": 0, "cache_re
ad_input_tokens": 0, "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens":
 0}, "output_tokens": 0, "service_tier": "standard", "inference_geo": "global"}, "type": "AssistantM
essage"}
event: message
data: {"subtype": "success", "duration_ms": 8163, "duration_api_ms": 8025, "is_error
": false, "num_turns": 1, "session_id": "77597263-a169-4236-b3d4-8ec14f90fd2b", "stop_reason": "end_
turn", "total_cost_usd": 0.028029, "usage": {"input_tokens": 7108, "cache_creation_input_tokens": 0,
 "cache_read_input_tokens": 0, "output_tokens": 447, "server_tool_use": {"web_search_requests": 0, "
web_fetch_requests": 0}, "service_tier": "standard", "cache_creation": {"ephemeral_1h_input_tokens":
 0, "ephemeral_5m_input_tokens": 0}, "inference_geo": "", "iterations": [{"input_tokens": 7108, "out
put_tokens": 447, "cache_read_input_tokens": 0, "cache_creation_input_tokens": 0, "cache_creation":
{"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, "type": "message"}], "speed": "sta
ndard"}, "result": "Sure! Here's a summary of our conversation so far:\n\n---\n\n### \ud83d\uddc2\uf
e0f Conversation Summary\n\n**1. Top 3 AI Agent Trends (May 2026)**\nYou asked about the most intere
sting AI agent trends right now. Based on web research, the three highlighted were:\n\n- \ud83e\udd1
d **Multi-Agent Systems & Orchestration** \u2014 Specialized agents working in coordinated teams, re
placing single all-purpose agents. Gartner reported a 1,445% surge in multi-agent system inquiries.\
n- \ud83e\uddf1 **Context Engineering** \u2014 Designing the full information architecture around an
 agent (memory, retrieval, data sources, token budgets) to ensure reliable, high-quality outputs at
scale.\n- \ud83d\udee1\ufe0f **Governance & Deterministic Guardrails** \u2014 Shifting from viewing
governance as a compliance burden to an enabler, combining dynamic AI with human oversight to safely
 deploy agents in high-stakes scenarios.\n\n---\n\n**2. Deep Dive into Context Engineering**\nYou as
ked for more detail on the second trend. Key takeaways included:\n\n- **Context Engineering \u2260 P
rompt Engineering** \u2014 It's a broader discipline covering the entire information lifecycle of an
 agent.\n- **Core techniques** include RAG, memory management, context compression, context offloadi
ng, state persistence, and tool output structuring.\n- **Why it matters for agents** \u2014 Unlike c
hatbots, agents accumulate context over many steps, making careful information design critical to av
oid context rot and token blowouts.\n- **RAG alone isn't enough** \u2014 77% of IT leaders agree RAG
 is insufficient for production AI on its own.\n- Proper context engineering can improve agent task
completion rates dramatically (e.g., **83% \u2192 96%**).\n\n---\n\nWould you like to explore any of
 these topics further?", "structured_output": null, "type": "ResultMessage"}
event: done
data:
%%bash
# Teardown tier 1
cd hosting/docker && docker compose down
 Container docker-research-agent-1 Stopping
 Container docker-research-agent-1 Stopped 
 Container docker-research-agent-1 Removing
 Container docker-research-agent-1 Removed
 Network docker_default Removing
 Network docker_default Removed

层级 2 — Modal:相同的镜像,现在它是一个 URL

层级 1 在你的机器上运行。层级 2 通过 modal.Sandbox 在 Modal 上运行相同的 Dockerfile,为你提供公共 HTTPS URL、scale-to-zero,无需管理服务器。

该 URL 是公开的:任何拥有它的人都可以花费你的 API 预算。层级 1 和 3 假设前面有一个认证网关;层级 2 没有网关,因此 modal_app.py 生成一个按部署的 bearer token 并将其作为 AGENT_AUTH_TOKEN 传递。server.py 仅在该环境变量设置时强制执行 token,因此其他层级不受影响。

hosting/modal/modal_app.py 很短,因为 Agent 的任何内容都没有改变:

app = modal.App.lookup("research-agent-hosting", create_if_missing=True)
image = modal.Image.from_dockerfile("hosting/Dockerfile", context_dir=".")
auth_token = secrets.token_urlsafe(32)
sandbox = modal.Sandbox.create(
    "serve",  # appended to the image's ENTRYPOINT, like compose's `command:`
    app=app,
    image=image,
    secrets=[
        modal.Secret.from_name("anthropic"),
        modal.Secret.from_dict({"AGENT_AUTH_TOKEN": auth_token}),
    ],
    volumes={"/data": sessions_volume},
    encrypted_ports=[8000],
)
print(sandbox.tunnels()[8000].url)

持久化使用挂载在 /data 的 modal.Volume,与层级 1 相同的 CLAUDE_CONFIG_DIR 技巧。(如果你的工作负载有许多并发写入的沙盒并且遇到 Volume 提交语义问题,请换用 SessionStore;这也是层级 3 和生产部署使用的。)

一次性设置,在你的终端中(modal setup 会打开浏览器,因此不能从 notebook 单元格运行):

pip install modal
modal setup

然后创建 Modal 将注入为 ANTHROPIC_API_KEY 的密钥:

%%bash
modal secret create anthropic ANTHROPIC_API_KEY="$(grep ANTHROPIC_API_KEY hosting/.env | cut -d= -f2)"
Created a new secret 'anthropic' with the key 'ANTHROPIC_API_KEY'

Use it in your Modal app:
                                                                                

@app.[38;2;248;248;242;48;
2;39;40;34mfunction(secret
s=[[38;2;248;248;242;4
8;2;39;40;34mmodal.Secret[
0m.from_name[38;2;248;248;
242;48;2;39;40;34m("anthro
pic")[38;2;248;248;24
2;48;2;39;40;34m])                    
def [38;2;166;226;46;48;2
;39;40;34msome_function()
[0m:
                 
    os[
0m.getenv[38;2;248;248;242
;48;2;39;40;34m("ANTHROPIC
_API_KEY")[48;2;39;40
;34m                                              

                                                   
%%bash
python hosting/modal/modal_app.py | tee /tmp/modal_deploy.out
MODAL_URL=$(awk '/^url:/ {print $2}' /tmp/modal_deploy.out)
MODAL_TOKEN=$(awk '/^token:/ {print $2}' /tmp/modal_deploy.out)
{ echo "MODAL_URL=$MODAL_URL"; echo "MODAL_TOKEN=$MODAL_TOKEN"; } > /tmp/modal_url.env
sandbox: sb-7R7zQ7TtX0h9eKZ8qslvwo
url:     https://ta-01ks91e217n9fymaxjtdc9k5bh-8000-kn9n102ljd7y4
majwav00kwg0.w.modal.host
token:   sb-…redacted…

⚠️  The URL is p
ublic. The token is the only thing gating it — don't share both.

Try it:
  curl -N -X POST https:
//ta-01ks91e217n9fymaxjtdc9k5bh-8000-kn9n102ljd7y4majwav00kwg0.w.modal.host/sessions/demo-1/messages
 \
    -H 'Authorization: Bearer sb-…redacted…' \
    -H 'Content-Type
: application/json' \
    -d '{"prompt":"What are the latest AI agent trends?"}'
%%bash
source /tmp/modal_url.env
curl -N -s -X POST "$MODAL_URL/sessions/demo-1/messages" \
  -H "Authorization: Bearer $MODAL_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"prompt":"Give me a one-sentence summary of the Claude Agent SDK."}'
event: message
data: {"subtype": "init", "data": {"type": "system", "subtype": "init", "cwd": "/app", "session_id": "1566ffe4-2b20-4a68-82ff-283984b64451", "tools": ["Task", "TaskOutput", "Bash", "Glob", "Grep", "ExitPlanMode", "Read", "Edit", "Write", "N … [truncated]

event: message
data: {"content": [{"id": "toolu_01PPS8yzMBzMnRhG2Hnpk5VL", "name": "WebSearch", "input": {"query": "Claude Agent SDK Anthropic 2026"}}], "model": "claude-sonnet-4-6", "parent_tool_use_id": null, "error": null, "usage": {"input_tokens": 120 … [truncated]

[... 5 events omitted — thinking blocks, tool loading, and web-search result payloads ...]

event: message
data: {"content": [{"text": "The **Claude Agent SDK** is Anthropic's framework that gives developers programmatic access to the same tools, agent loop, and context management that power Claude Code \u2014 enabling the creation of AI agents that can autonomously read files, run commands, search the w … [truncated]

event: message
data: {"subtype": "success", "duration_ms": 12879, "duration_api_ms": 12871, "is_error": false, "num_turns": 3, "session_id": "1566ffe4-2b20-4a68-82ff-283984b64451", "stop_reason": "end_turn", "total_cost_usd": 0.045893199999999995, "usage" … [truncated]

event: done
data:

相同的接口、相同的镜像、不同的主机。当没有调用时,Modal 将沙盒缩放到零,你无需付费。

清理,这样你就不会为空闲资源付费:

%%bash
python hosting/modal/teardown.py
terminating sandbox sb-7R7zQ7TtX0h9eKZ8qslvwo
deleted volume research-agent-sessions

层级 3 — Kubernetes:当你需要拥有基础设施时

层级 3 用于多租户生产、受监管环境或任何你需要完全控制网络、隔离和成本的地方。Agent 镜像和接口仍然相同;新的是它周围的机制:

  • 前面的网关,认证调用者并只转发他们拥有的 session_id。这是 server.py 省略的认证最终发生的地方。
  • 每个会话一个 Pod 的路由(网关 → Redis → pod),使每个对话有自己的爆炸半径。
  • 待机池的预热 pod,使新会话不必支付冷启动延迟。
  • 出口锁定(NetworkPolicy + 白名单代理),使 prompt 注入的 Agent 只能到达 api.anthropic.com 而不能到达其他任何地方。

完整的清单、网关和分步架构说明位于 hosting/kubernetes/ 中。它可以在本地 kind 集群上端到端运行,无需云账户:

cd hosting/kubernetes
ANTHROPIC_API_KEY=sk-ant-... ./kind-quickstart.sh

The quickstart prints bearer tokens for two demo tenants (alice and bob). The gateway scopes every session to the tenant that created it: the same curl -N POST /sessions/{id}/messages as tiers 1 and 2, now aimed at the gateway on :8080 with an Authorization: Bearer <alice-token> header, works for alice, while the same request with bob’s token gets a 403. The README’s Deploying to your own cluster section covers the registry/ingress changes for a real cluster.

Kubernetes 层级基于 Joe Shamon 和 Ben Lehrburger 的内部工作构建。


使其达到生产就绪

两个生产关注点,每个只需几行代码即可连接。下面的单元格展示了代码;托管文档涵盖了完整的生产清单(认证、优雅关闭、空闲超时调优、自动扩缩容、成本控制)。

可观测性

SDK 为每轮和每个工具调用发射 OpenTelemetry span。用两个环境变量将其指向你的 collector,无需更改 server.py 的代码(文档):

# In docker-compose.yml / modal_app.py / your k8s Deployment:
#   OTEL_EXPORTER_OTLP_ENDPOINT=http://your-collector:4317
#   OTEL_SERVICE_NAME=research-agent

存活检测

GET /health 已经在 server.py 中。将你的编排器的存活探针指向它(compose healthcheck:、Modal 健康检查、k8s livenessProbe)。

超越卷的持久化

对于单主机和 Modal,/data 卷挂载是可以的。对于多主机生产,使用 SessionStore 适配器将记录镜像到共享存储(S3、Postgres、Redis)。注意 SessionStore 是一个镜像;本地磁盘写入总是首先发生,镜像失败会发出 mirror_error 而不会中断 Agent。

线格式

server.py 流式传输原始 SDK 消息类型。这对 cookbook 来说可以;对于真正的 API,你需要定义一个稳定的线格式,这样 SDK 版本升级就不会破坏客户端。


选择你的层级

层级 它给你什么 何时选择 何时升级
1. Docker 你控制的机器上的容器。Compose 重启它,绑定挂载保留 /data。你运营一个 Docker 主机。 开发循环、内部工具、单租户应用、cron/批量作业。你可以手动重启它,网络外部没有人调用它。 该机器外部的人需要 URL,或”手动重启”不再可接受。
2. Modal 相同镜像位于公共 HTTPS URL 之后,具有 scale-to-zero 和远程构建。你无需运营任何东西。 你今天想要一个可调用的端点,流量大部分时间突发或为零,按部署的 bearer token 足够认证。 你需要真正的多租户隔离、网络级出口控制,或你的平台团队要求工作负载在他们的集群上。
3. Kubernetes 每个会话一个 Pod 的隔离,具有租户范围会话的认证网关、出口锁定和预热待机池。你运营集群、网关和 Redis。 多租户生产、受监管环境,或你已经运行 Kubernetes 并希望 Agent 遵循与其他所有东西相同的运营模型。 这是本 notebook 阶梯的顶部;从这里开始,你调优自动扩缩容、多区域路由和持久会话存储,而不是迁移。

托管指南的部署模式直接映射到这些层级。临时会话(模式 1:一个 prompt,一个进程,退出)是层级 1a:没有服务器,从 cron 或任何主机上的队列工作器运行容器。长期运行和混合会话(模式 2 和 3,其中进程跨轮次保持或重新水化对话状态)是 server.py 使用 resume= 加 /data 卷实现的;层级 1b、2 和 3 都服务于这种形状,区别仅在于谁保持该进程活跃以及调用者如何到达它。单容器(模式 4,多个会话多路复用到一个容器中)正是层级 1b 和 2 所做的;层级 3 存在于当这不再可接受且每个会话需要自己的爆炸半径时。


附录 — 移植到其他提供商

相同的 hosting/Dockerfile,不同的部署命令。这些中的每一个都暴露端口 8000 并给你一个 URL;在 /data 挂载一些东西以实现持久化。

Fly Machines

fly launch --dockerfile hosting/Dockerfile --no-deploy  # run from claude_agent_sdk/
fly volumes create data --size 1
fly deploy

E2B

from e2b import Sandbox
sbx = Sandbox(template="research-agent")  # template built from hosting/Dockerfile
sbx.commands.run("./hosting/entrypoint.sh serve", background=True)
url = sbx.get_host(8000)

Daytona

from daytona import Daytona, CreateSandboxFromImageParams
sbx = Daytona().create(CreateSandboxFromImageParams(image="research-agent"))
sbx.process.exec("./hosting/entrypoint.sh serve")

Cloudflare Containers

// wrangler.toml points at hosting/Dockerfile
export class Agent extends Container { defaultPort = 8000 }

Vercel Sandbox

import { Sandbox } from "@vercel/sandbox";
const sbx = await Sandbox.create({ image: "research-agent", ports: [8000] });
await sbx.runCommand({ cmd: "./hosting/entrypoint.sh", args: ["serve"], detached: true });

Tip

中文读者提示:本章节的代码和输出为英文原文。如需理解具体实现细节,可参考上方中文导读和代码注释。如有疑问,欢迎在 GitHub Issues 讨论。