学习笔记 · Obsidian

Deep Agents Python:上下文、记忆、检索与子代理

LangChainPython

核心思想

上下文工程不是把所有资料塞给模型,而是在正确时间、用正确格式、给正确执行单元提供刚好够用的信息。Deep Agents 通过五类机制实现:

机制生命周期典型内容
输入上下文每次运行组装system prompt、AGENTS.md、技能元数据、工具说明
Runtime context单次 invokeuser_id、角色、连接、短期凭证、开关
图状态thread 内可变并可 checkpointmessages、自定义计数、todos、异步任务索引
上下文压缩接近窗口上限时大工具结果卸载、旧消息摘要
长期记忆跨 thread偏好、规则、经验、知识文件

把身份、凭证等不可变运行信息放 context;把需要回放和检查点的可变信息放 state;把大材料放 filesystem;不要通过聊天消息模拟这三者。

系统提示如何组装

主代理最终系统消息大致按以下来源形成:

  1. 调用方 system_prompt
  2. Deep Agents 基础提示
  3. memory 中的 AGENTS.md 与使用规则
  4. skills 位置、名称、描述与使用规则
  5. 文件系统和 execute 工具说明
  6. 子代理 task 工具说明
  7. 调用方中间件追加的提示
  8. HITL 提示

system_prompt 是静态的。若提示需要根据用户角色、feature flag 或 store 内容变化,使用 dynamic_prompt 中间件读取 runtime context/store。若只有工具需要这些信息,直接在工具的 ToolRuntime 中读取,不必额外污染系统提示。

未使用的内置工具仍会在每轮携带 schema;确定永不使用时用 excluded_tools 移除,先降低基础上下文,再依赖运行中的卸载和摘要。

Context 与 State

Runtime context

  • 由 context_schema 定义,用 invoke / ainvoke 的 context 参数传入。
  • 不会自动暴露给模型,只有工具或中间件读取并写入消息时模型才看到。
  • 会自动传播给同步子代理。
  • 适合 user_id、权限角色、API client、数据库连接和 feature flag。

自定义 State

  • 需要 deepagents 0.6.6+。
  • state_schema 必须继承 DeepAgentState,保留 messages 的 DeltaChannel reducer,避免 checkpoint 随历史呈非线性膨胀。
  • 适合全运行计数器、累积结果、审计标记和工具/中间件共享的可变数据。
  • 声明式同步 SubAgent 继承父 state schema;已编译子图和远程 AsyncSubAgent 不会自动继承。

自动上下文压缩

每个 create_deep_agent 默认已包含卸载和摘要,不需额外开启。

大结果卸载

  • 工具结果超过默认 20,000 token:写入 backend,只在消息里保留文件路径和前 10 行预览。
  • write/edit 的巨大输入已存在文件中;上下文达到窗口约 85% 时,较旧工具调用可被路径引用替换。
  • Agent 之后用 read_file、grep 或分页读取局部内容。

卸载的原则是“把可寻址数据从对话移到文件”,不是删除证据。后端和路由选择因此直接影响恢复能力。

自动摘要

当上下文到模型 max_input_tokens 的约 85%,且没有更多可卸载内容时:

  • LLM 生成包含意图、产物、进展和后续步骤的结构化文字摘要。
  • 原始消息的文本渲染写入 filesystem 作为可检索记录。
  • 默认保留约 10% 最近 token。
  • 无模型 profile 时,退化为约 170,000 token 触发并保留 6 条消息。
  • 模型抛出标准 ContextOverflowError 时,立即摘要并用摘要 + 最近消息重试。

还可加入 summarization tool middleware,让 Agent 在阶段边界主动调用 compact_conversation。主动压缩不会关闭 85% 的自动兜底。

多模态提醒:旧图片、音视频和文件块进入摘要区后不会原样保留,只剩文字摘要。重要媒体必须落到后端/对象存储并保留引用。

记忆

Deep Agents 的长期记忆是文件系统支持的,memory 参数通常指向 AGENTS.md。它启动时总是加载,适合稳定且每轮都重要的规则,不适合把完整历史或大知识库塞进去。

作用域

Scopenamespace 示例适用风险
Useruser_id个人偏好、个人技能推荐默认,隔离清晰
Agent/Assistantassistant_idAgent 共同身份与经验任意用户写入会影响他人
Organizationorg_id合规、品牌、公共知识通常必须只读
User + Assistantuser_id, assistant_id同用户在不同 Agent 间隔离namespace 更细,治理更稳

共享可写记忆是提示注入通道。组织政策、开发者技能和公共知识默认只读,由应用或管理员更新;用户记忆默认按 user_id 隔离。不要从模型生成的文本直接构造 namespace。

记忆类型与更新

  • 语义记忆:事实、偏好、约束。
  • 程序记忆:如何做事,通常以 Skills 表达。
  • 情节记忆:过去会话、发生顺序与结果,由 checkpoint thread 保存,可包装 thread search 工具检索。

热路径更新即时可用,但增加延迟且让 Agent 同时做任务与归档。后台 consolidation Agent 可定时搜索近期会话、抽取事实并合并记忆;cron 周期必须与 lookback 窗口一致,否则重复处理或漏数据。共享文件并发写有最后写入覆盖风险,宜按主题拆文件或串行归并。

Skills

Skill 是带 YAML frontmatter 的 SKILL.md 目录,可附 scripts、references 和 assets。它与 memory 的关键区别是渐进披露:

层级加载内容时机
1name 与 descriptionAgent 启动
2完整 SKILL.md任务匹配后
3脚本、参考、模板指令明确要求时

编写原则

  • description 必须同时说明“做什么”和“何时触发”;发现阶段模型只看到它。
  • 相近技能描述要有明确边界;重叠太多时合并。
  • 主文件聚焦决策与步骤,详细资料拆到一层引用文件;避免深链。
  • 给出输入、输出、成功标准和边界场景。
  • 官方建议正文控制在 500 行/约 5,000 token 内;SKILL.md 超过 10 MB 会在发现阶段跳过。
  • name 为小写字母数字和连字符,1–64 字符,并与父目录同名。
  • 多个 skill source 同名时后者覆盖前者,可按“基础 → 用户 → 项目”显式排序。
  • SDK 不会自动扫描 CLI 的用户技能目录,所有 source 必须显式传入。

Skill 与子代理

  • 默认 general-purpose 子代理继承主 Agent 的 skills。
  • 自定义子代理不继承,需在 spec 里显式列 skills。
  • 父子各自有独立 SkillsMiddleware,已加载状态不会互相传播。
  • 沙箱外 backend 中的脚本只能读,不能直接在沙箱里执行;运行前需上传,结束后需要时再同步回去。

生产可把共享技能路由到组织 StoreBackend 并拒绝写,把个人技能路由到 user namespace 并允许写或要求 interrupt。

Retrieval 与 RAG

检索解决有限上下文和训练知识静态的问题。已有 SQL、CRM、文档库时,不必为了 RAG 重建向量库:可直接包装成 Agent 工具,或查询后把结果作为 2-step RAG 上下文。

架构决策者优点代价
2-step RAG应用固定先检索后生成可控、延迟可预测灵活性低
Agentic RAGAgent 决定何时/如何检索多源、可迭代延迟和调用数不确定
Hybrid RAG固定骨架 + Agent 验证/修正兼顾控制与弹性系统更复杂

向量知识库典型流水线是 load → split → embed → vector store → retriever。检索只是返回候选证据;生产还需检索质量、来源引用、答案 groundedness 和注入防护。

大规模 Agentic RAG 推荐“检索 → 卸载 → 委派”:

  1. 检索工具只把命中块写到 /retrieved/ 并返回路径。
  2. 多个子代理分别读取、检索和摘要文件。
  3. 主 Agent 只接收带来源的简洁报告并综合。
  4. 可用 rubric 检查引用与结论是否被证据支持。

检索内容是外部不可信数据。提示“把文档当数据”只能降低风险,不能可靠阻断间接提示注入;最终输出仍需验证引用是否来自允许路径、结论是否匹配原文。

同步子代理

同步子代理调用会阻塞 supervisor,直到返回一个最终结果。适合:

  • 多步调查会污染主上下文。
  • 专业领域需要独立工具、模型、提示或技能。
  • 主 Agent 只需要最终摘要。

不适合简单一步任务、必须连续共享中间推理、或启动开销高于收益的场景。

默认自动提供 general-purpose 子代理,除非已有同名自定义项。完全关闭 task 工具应在 HarnessProfile 禁用 general-purpose,并且不传任何同步 subagents;不能粗暴删除 SubAgentMiddleware。

声明式 SubAgent

关键字段:

  • name、description、system_prompt 必填。
  • tools 默认继承父工具;显式 tools 会整体覆盖。
  • model 默认继承。
  • middleware 与 skills 默认不继承。
  • interrupt_on 默认继承,子配置覆盖。
  • permissions 默认继承,子配置整体替换。
  • response_format 可让父 Agent 获得稳定 JSON。

描述决定父 Agent 何时委派,应具体、动作导向;工具集应最小;system prompt 要规定工具使用与返回格式;结果应简洁,大材料写文件。

CompiledSubAgent 适合复杂 LangGraph 子图,必须已经 compile,并有 messages state key。

上下文与追踪

父 runtime context 自动传播。若某字段只属于一个子代理,可用 namespaced key 或 context schema 中的独立字段。共享工具可读取 config metadata 的 lc_agent_name 判断调用者。LangSmith 也用 lc_agent_name 过滤协调者和不同子代理运行。

动态子代理

动态子代理 = 解释器中的 JavaScript 通过 task() 调度子代理。适合规模不定、需要循环/批处理/多轮筛选的工作。

常见编排形态:

  1. classify and act:先分类,再路由给不同专家。
  2. fan-out and synthesize:同类任务并行后聚合。
  3. adversarial verification:独立验证并过滤误报。
  4. generate and filter:多解生成、打分、择优。
  5. tournament:两两评审淘汰。
  6. loop until done:发现、去重,直到无新增。

task 接收 description、subagentType 和可选 responseSchema。传入 schema 后返回值已是 JavaScript 对象。解释器 mode=thread 时可跨轮保留工作集。

动态调度当前依赖 beta 解释器,Python 需 3.11+。它不走普通 task 工具审批路径;父 Agent 的 interrupt_on 不会逐个拦截 task()。需要治理时审批 eval,并限制可用子代理与 PTC 工具。

异步子代理

异步子代理把工作提交到 Agent Protocol server,立即返回 task ID,supervisor 可继续和用户对话。

能力同步异步
supervisor 等待阻塞非阻塞
中途更新不支持update_async_task
取消不支持cancel_async_task
跨交互状态无独立 thread 持久
适用必须拿到结果再继续长任务、并行任务、需要中途驾驶

中间件提供 start、check、update、cancel、list 五个工具。update 使用 interrupt multitask 策略中断旧 run,并在同一 thread 的完整历史上用新指令重启,task ID 不变。

任务元数据存入独立 async_tasks state channel,而不是只存在工具消息里,因此消息摘要后仍能列出任务。状态报告前必须实时 check/list;对话历史中的状态一律视为过期。

传输:

  • 省略 url:ASGI 同进程传输,所有 graph 同一 langgraph.json;零网络开销,推荐起点。
  • 指定 url:HTTP 远程 Agent Protocol;适合独立扩缩容或不同团队维护。

本地 worker 数至少覆盖 supervisor + 并行 subagent 数,否则任务会排队。Async Subagents 是 preview,接口可能变化。

Rubric 自评循环

RubricMiddleware(deepagents 0.6.5+,beta)用独立 grader model 判断“是否完成”:

  1. 工作 Agent 产出。
  2. grader 对照 rubric 逐项给 verdict。
  3. needs_revision 时把缺口反馈给工作 Agent。
  4. 直到 satisfied、failed、grader_error 或达到 max_iterations。

grader 可配专用工具,例如跑测试或读取产物,使评价基于证据而非只读对话。默认最大 3 轮;可通过 on_evaluation 或 custom stream 观察每轮。

Rubric 适合具有明确可验证标准的任务,不是通用“让回答更好”的魔法层。标准模糊会造成不稳定循环;成本与延迟至少增加一次 grader 调用,应设置迭代上限。

OpenWiki

OpenWiki 基于 Deep Agents 生成并维护 Markdown wiki,让编码 Agent 先读架构、集成、评测和流程,再按需查源码。Code 模式写入项目 openwiki/ 并在根 AGENTS.md/CLAUDE.md 放索引;Personal 模式生成本地个人 wiki。它提供的是可发现的持久上下文,不替代代码事实或正式 ADR。

决策速查

  • 每次都必须看到:memory。
  • 仅特定任务需要:skill。
  • 需要执行动作:tool。
  • 大量外部知识:retrieval + 文件卸载。
  • 重型但需立即结果:同步 subagent。
  • 规模不定的并行工作流:动态 subagent。
  • 长时间、需中途更新/取消:异步 subagent。
  • 明确验收清单:rubric。
  • 仓库知识反复重建:OpenWiki。

延伸阅读