claude_agent_sdk/ 从一行研究 Agent 写到 Docker、Modal 和 Kubernetes,实际在追问:把 Claude Code 放进自己的程序以后,哪些原来由交互式产品承担的工作,现在必须由应用接管?

答案不只是工具循环。项目配置、权限、会话、审计、子任务和进程生命周期共同组成 Agent 的运行框架。模型负责选择下一步,这套框架决定它能看到什么、能做什么、做过的事如何留下,以及程序重启后还能不能继续。

SDK 开放的是一套现成的运行框架

最简单的研究示例只有一个 query():传入问题和 WebSearch,异步读取模型消息。这里的 Agent 是一次性的;下一次调用不会继承上一次调查。

换成 ClaudeSDKClient 后,同一个 client 内的后续 query 可以接着前文继续。再往后,SDK 又接入 CLAUDE.md、.claude/agents/、hooks、commands 和 output styles。此时 system prompt 已经不是唯一配置源,工作目录也不再只是文件路径。cwd 和 setting_sources 决定了一组项目级行为是否进入运行时。

Chief of Staff 示例里,只有设置 setting_sources=["project", "local"],项目中的 subagent、命令和本地 hooks 才会加载。换句话说,同一段 Python 代码在不同目录、不同 setting sources 下,运行的并不是同一个 Agent。

这种设计直接继承了 Claude Code 的项目模型。好处是既有的 CLAUDE.md、脚本和 Agent 定义可以原样复用;代价是行为分散在 API 参数和文件系统中。上线前只审查 agent.py 不够,还要审查工作目录里的配置文件,否则会漏掉实际生效的权限和自动动作。

Hook 把不应由模型判断的规则移出模型

SRE 示例比普通 MCP 接入更有参考价值。模型可以查询指标、读取日志、修改配置并重启服务,但修改前会经过 PreToolUse hook:连接池大小不在 5 到 100 之间时阻止写入;部署前再读取配置,数值异常则阻止命令执行。

这和在 system prompt 里写“不要设置危险值”不是同一层保证。提示词影响模型的选择,hook 检查已经形成的具体调用:

模型提出 edit_config_file(DB_POOL_SIZE=1)
→ PreToolUse 解析参数
→ 规则不通过,工具不执行
→ 错误返回模型,模型重新选择

Agent 的自主性因此被夹在两个确定性边界之间。工具实现限制可访问目录和命令前缀,hook 检查这一次修改的内容。前者约束能力范围,后者约束具体动作。

教程也展示了另一种 hook:在 Write、Edit 或 Bash 之后记录审计日志。它只能证明调用发生过,不能阻止损害。判断一个 hook 是否构成安全边界,首先要看它运行在工具之前还是之后,而不是看它是否叫“合规 hook”。

Subagent 的价值在上下文和权限分区

Chief of Staff 通过 Task 工具调用 .claude/agents/financial-analyst.md。这个文件同时声明角色说明、可用工具和领域提示词。主 Agent 不需要读取财务文件、运行计算脚本后再把所有结果塞回自己的上下文;它只需要向财务 Agent 下达任务并接收结论。

子 Agent 因此带来两种隔离。第一种是上下文隔离,大量局部材料留在子任务里。第二种是能力隔离,例如财务 Agent 只有 Read、Bash 和 WebSearch,不必继承主 Agent 的全部工具。

但这里的委派仍主要由提示词触发。角色描述告诉主 Agent 什么时候应该调用谁,运行时不会替你证明任务确实分给了正确角色。角色边界若很重要,就应继续用工具白名单和 hook 固化;不能只依赖“请把财务问题交给 financial-analyst”。

这也解释了为什么 subagent 不等于多写一段角色提示。独立上下文和独立工具集才是结构上的变化,角色语气只是附带效果。

Session 是可以分叉的执行历史

session_browser notebook 没有增加模型能力,却补上了 Agent 产品常被忽略的一层。SDK 把 transcript 写到本地,应用可以列出、读取、重命名、标记、恢复和删除 session。fork_session() 还能复制某个节点之前的历史,重新映射消息 ID,再用 resume= 从分支继续。

这比“保存聊天记录”多了一步。历史不再只是供人回看,而是可以重新成为模型的执行起点:

原 session:调查 → 方案 A → 实现
                    └→ fork → 方案 B → 实现

分叉适合高成本决策,因为重试无需覆盖原轨迹。不过这些 transcript 默认在本地磁盘。跨机器访问、用户归属、索引、并发和保留策略仍由应用负责。教程中的 tag 也只是单个字符串;更丰富的产品状态需要另外建库,不能把 transcript 文件当成完整业务数据库。

部署暴露了 Agent 的真实运行单位

最后一篇把同一个研究 Agent 部署为一次性容器、带 HTTP 服务的长驻容器,再扩展到 Modal 和 Kubernetes。这里最有用的判断是:Agent SDK 中的 Agent 更接近一个进程,而不是 Web 服务里的普通对象。

一旦要支持连续会话,部署层必须解决四件事:为任务启动容器,把同一 session 的后续请求路由回正确实例,回收空闲实例,把 transcript 持久化到实例之外。示例服务器还维护外部 session ID 到 SDK session ID 的映射,因为调用方使用的 ID 与 SDK 内部生成的 ID并不相同。

这已经是分布式系统问题。示例明确留下了一个竞态:同一外部 ID 的两个首次请求可能各自创建 SDK session,最后一次写入覆盖映射。单机演示可以接受,生产系统则需要在“读取映射—创建 session—写回映射”这一整段上加互斥或原子创建。

安全边界也会随部署变化。本地研究 Agent 能使用 Read;托管服务器故意只保留 WebSearch,因为没有上传入口时,容器里可读的反而是其他 session 的 transcript 和环境变量。来自网页的提示注入可能借 Read 把这些内容带出去。工具在本地有用,不代表放到共享服务器后仍然安全。

这组教程补的是模型之外的部分

研究、Chief of Staff、Observability、SRE 和漏洞检测只是不同业务外壳。更值得借鉴的是下面这组分工:

  • 模型决定下一步行动;
  • 工具白名单决定可用能力;
  • hook 对具体动作做确定性检查或记录;
  • subagent 隔离局部上下文和权限;
  • session 保存并分叉执行历史;
  • 容器和网关管理租户、生命周期与持久化。

其中任何一层缺失,模型仍可能在演示中完成任务,却很难成为可长期运行的应用。Agent SDK 的价值是复用 Claude Code 已经形成的运行框架;它没有替应用消除工程责任,而是把这些责任暴露得更清楚。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐