Harness 即库:子智能体与会话存储 本节摘要:原始 LLM API 一次调用只给你一次往返;生产 Agent 需要的远不止——工具执行、MCP 服务器、生命周期钩子、子智能体派生、会话持久化、跨进程追踪传播。把这套「外壳(Harness)」从零写出来是巨大的工程量,而 Anthropic 的回答是:Claude Agent SDK 把 Claude Code 用的那套 Harness 当成一个可 import 的库发出来了——内置工具、子智能体(subagent)做上下文隔离与并行、生命周期钩子、W3C 追踪传播、会话存储,一个 import 全到位。
本节摘要:原始 LLM API 一次调用只给你一次往返;生产 Agent 需要的远不止——工具执行、MCP 服务器、生命周期钩子、子智能体派生、会话持久化、跨进程追踪传播。把这套「外壳(Harness)」从零写出来是巨大的工程量,而 Anthropic 的回答是:Claude Agent SDK 把 Claude Code 用的那套 Harness 当成一个可 import 的库发出来了——内置工具、子智能体(subagent)做上下文隔离与并行、生命周期钩子、W3C 追踪传播、会话存储,一个 import 全到位。本节先厘清 Client SDK(裸 Messages API,你自己拥有循环)与 Agent SDK(Harness 形状)的区别,再吃透子智能体的两大用途(并行化、上下文隔离——派生 20 个子智能体去找 20 个模块的测试文件,编排者的上下文窗口不被污染)、会话存储的五方法面(
append/load/list_sessions/delete/list_subkeys)与--session-mirror、六类生命周期钩子,以及云端托管的 Claude Managed Agents(长时异步、内置缓存与压缩,用控制权换托管基建)。读完本节,你应能用标准库实现一个带内置工具、子智能体派生、隔离上下文、生命周期钩子与会话存储的 Harness,并识别三种失败模式:子智能体过度派生、钩子蠕变、会话膨胀。
对应原课程:Phase 14 · Lesson 17 ·
claude-agent-sdk(原英文phases/14-agent-engineering/17-claude-agent-sdk/docs/en.md)。前置:第 01 节(Agent 循环)、第 10 节(技能库)。
阅读完本节,你应当能够:
append、load、list_sessions、delete、list_subkeys)及 --session-mirror 的作用。一个裸 LLM API 调用,给你的是一次往返:发提示、收响应。但生产 Agent 需要的是:
把这些从零写出来,是 Claude Code 这个产品本身大部分的工程量。Claude Agent SDK 的洞见是:这套 Harness 本身就是产品——把它作为库暴露出来,自定义 Agent 直接 import,不必重造轮子。
anthropic) —— 裸 Messages API。你自己拥有循环、工具、状态。适合:你已经有一套 Harness,只需一个稳定的 API 客户端。claude-agent-sdk) —— 内置工具执行、MCP 连接、钩子、子智能体派生、会话存储。Claude Code 的循环,作为库。适合:你想直接拿到生产级 Harness,把精力放在业务逻辑上。SDK 开箱带 10+ 工具:文件读写、shell、grep、glob、网页抓取等。自定义工具通过标准工具模式接口注册(第 06 节那套 name+description+JSON Schema)。这意味着一个最小 Agent 几乎零配置就能读写文件、跑命令。
Anthropic 文档记录了两大用途:
Python SDK 近期新增 list_subagents()、get_subagent_messages(),用于读取子智能体的对话轨迹——这对审计与调试至关重要。
与 TypeScript SDK 协议对齐的五方法面:
append(session_id, message) —— 追加一轮。load(session_id) —— 恢复对话。list_sessions() —— 枚举所有会话。delete(session_id) —— 删除,级联到子智能体会话。list_subkeys(session_id) —— 列出该会话下的子智能体键。--session-mirror(CLI 标志)在流转时把对话镜像到外部文件,用于调试——你能实时看到 Agent 在「想」什么。
可注册的生命周期钩子:
PreToolUse、PostToolUse —— 门控或审计工具调用(可拒绝、可记录)。SessionStart、SessionEnd —— 建立与拆除(如连数据库、清临时文件)。UserPromptSubmit —— 在模型看到用户输入前先动作(如敏感词过滤、注入检测)。PreCompact —— 在上下文压缩前跑(第 08 节的压缩门)。Stop —— Agent 退出时清理。Notification —— 旁路告警(如发 Slack)。钩子是横切关注点(cross-cutting concern)的落点——专业工作流(pro-workflow)与类似系统靠它加跨切行为,而不必改主循环。
调用方活跃的 OTel span,经 W3C trace context 头传播进 CLI 子进程。结果:整个多进程的追踪,在你的后端里显示为一条 trace。这是第 23 节(OTel 约定)与第 24 节(可观测性)能跨进程串起来的工程地基。
托管的替代方案(beta 头 managed-agents-2026-04-01):长时异步工作、内置提示缓存、内置压缩。用控制权换托管基建——你不再管 Harness 进程,Anthropic 替你管。适合跑几小时的研究型 Agent;不适合需要精确控制执行环境的工作。
⚠️ 三种失败模式:① 子智能体过度派生(Subagent over-spawn)——为 100 个小任务派 100 个子智能体,开销(派生、上下文拷贝、结果汇总)压过收益;应批处理(如每组 5 个)。② 钩子蠕变(Hook creep)——每个团队都加钩子,启动时间膨胀;每季度评审一次钩子清单。③ 会话膨胀(Session bloat)——会话累积、体积增长;用
list_sessions+ 过期策略定期清理。
原课程 code/main.py 用标准库实现了 SDK 的形状:
Tool、ToolRegistry,带内置 read_file、write_file、list_dir。Subagent——私有上下文、隔离运行、返回结果。SessionStore——append、load、list、delete、list_subkeys。Hooks——pre_tool_use、post_tool_use、session_start、session_end。class ToolRegistry: def __init__(self): self.tools = { "read_file": lambda path: open(path).read(), "write_file": lambda path, content: open(path, "w").write(content), "list_dir": lambda path: os.listdir(path), } def call(self, name, **kw): return self.tools[name](**kw)
class Subagent: def __init__(self, instructions, tools): self.context = [] # 私有上下文,与编排者隔离 self.instructions = instructions self.tools = tools def run(self, task): self.context.append({"role": "user", "content": task}) # 在自己的窗口里跑循环,结果摘要返回 result = llm_loop(self.instructions, self.context, self.tools) return result["summary"] # 编排者只收到摘要,过程留在子智能体里
class SessionStore: def __init__(self): self.db = {} def append(self, sid, msg): self.db.setdefault(sid, []).append(msg) def load(self, sid): return self.db.get(sid, []) def list_sessions(self): return list(self.db.keys()) def delete(self, sid): self.db.pop(sid, None) # 真实版级联子键 def list_subkeys(self, sid): return [k for k in self.db if k.startswith(f"{sid}.")] class Hooks: def pre_tool_use(self, name, args): ... # 门控/审计 def post_tool_use(self, name, res): ... def session_start(self, sid): ... def session_end(self, sid): ...
def spawn_parallel(subagent_factory, tasks): results = [subagent_factory().run(t) for t in tasks] # 真实版用线程/进程池 return aggregate(results) # 编排者上下文只增加聚合摘要,非 N 份原始过程
运行 python3 code/main.py 会展示:子智能体的上下文隔离(编排者上下文体积保持有界)、钩子执行、会话持久化。
💡 设计要点:子智能体的价值不在「并行」本身,而在上下文隔离——编排者收的是 N 份摘要而非 N 份冗长过程。这正是 MemGPT(第 07 节)「外部存储」思想在多智能体层的复现:把噪音推出主上下文,只在需要时把结论换页换进来。
| 框架/形态 | 何时选 | 关键取舍 |
|---|---|---|
| Claude Agent SDK | Claude 优先、想要 Claude Code 的 Harness 形状 | Harness 原生化,绑 Anthropic |
| Claude Managed Agents | 托管长时异步工作 | 用控制权换托管基建 |
| OpenAI Agents SDK(第 16 节) | OpenAI 优先 | handoff/guardrail 原生 |
| LangGraph + 自定义工具 | 想要图形状状态机 | 隔离/钩子/会话存储要自己接 |
Client SDK(anthropic) |
已有 Harness、只要 API 客户端 | 自己拥有循环与状态 |
原课程 outputs/skill-claude-agent-scaffold.md:脚手架一个 Claude Agent SDK 应用——子智能体、钩子、会话存储、MCP 服务器挂载、W3C 追踪传播。把 Mock LLM 换成真实 Messages API 调用即可投入生产,Harness 的组合逻辑无需改动。
PreToolUse 钩子,对 write_file 限流(每会话每分钟 5 次)。追踪其行为。list_subkeys 接到一个子智能体树渲染器。深度嵌套长什么样?claude-agent-sdk Python 包。工具注册有什么变化?append/load/list_sessions/delete(级联子键)/list_subkeys;--session-mirror 实时镜像对话用于调试。下一节,我们看 Agno 与 Mastra 这类生产 Agent 运行时——把会话、记忆、工具、评估、可观测性整合成一个可部署服务的运行时,对比 Harness 即库与运行时即服务两种形态。