跳转至

S04 subagent

2026年4月1日

s04 subagent

s04 subagent

改动

通过引入子代理(subagent)架构,优化长任务中“上下文污染”

功能 s02 tool_use s04 subagent
Agent 架构 单一agent Parent-Child:角色分工。
主 Agent 主要负责拆解任务、验收结果;
子 Agent 负责具体执行。
Context 全局单线:所有 bash 输出、文件读取日志全部堆积在主对话中,易导致大模型遗忘初始目标。 上下文隔离:子 Agent 启动时拥有完全干净的新上下文,完成后只将“精简总结”返回给主 Agent。
Tools 4 种基础工具(读、写、改、执行)。 基础工具 + task_dispatcher(任务分发器)。
System Prompt 单一设定:“你是一个写代码的 Agent,去执行任务。” SYSTEM 限制主 Agent 亲自动手,鼓励当甩手掌柜;
SUBAGENT_SYSTEM 设定子 Agent 专注闭环单项任务。
Execution Flow 单个 while 循环进行工具调用与反馈。 嵌套执行:主 Agent 遇到复杂任务 -> 召唤子 Agent -> 子 Agent 开启内部 N 次容错循环 -> 返回结果 -> 主 Agent 继续。
Langfuse 瀑布流追踪,所有思考和工具调用在同一层级。 引入 @observe(name="run_subagent"),形成树状层级追踪。主任务下清晰挂载独立的子任务 Span。

主子代理:思考与执行解耦

➡️工具链隔离:PARENT_TOOLSCHILD_TOOLS

如果一个 Agent 既要规划整个项目,又要去底层终端敲命令,还要去读写文件,上下文很快就会被繁杂的操作日志塞满,导致“忘了初心”。

CHILD_TOOLS:包含 bash, read_file, write_file, edit_file

PARENT_TOOLSCHILD_TOOLS + task_dispatcher

task_dispatcher

    {
        "name": "task_dispatcher",
        "description": "Spawn a subagent with fresh context. It shares the filesystem but not conversation history.",
        "input_schema": {
            "type": "object",
            "properties": {
                "prompt": { 
                    "type": "string",
                    "description": "Short description of the task"
                }
            },
            "required": ["prompt"]
        }
    }

➡️流式与非流式

  • 主代理:使用 client.messages.stream(...),打字机一样流式输出。
  • 子代理:使用 client.messages.create(...),非流式,无需把试错过程也流式打印在屏幕上。

子代理解放了上下文,非流式解放了屏幕。用户只需要知道‘下属去干活了’以及‘下属干完汇报的结果’。

子代理

Langfuse 层级追踪

➡️Trace, Generation 与 Span

Langfuse 的三个核心概念在 s04 中的映射关系:

  • Trace:一次完整的用户对话
  • Generation:大模型的每一次思考(耗 Token 的地方)
  • Span:执行某段代码逻辑(比如工具调用、子代理运行)的耗时与出入参数

➡️引入 @observe(name="run_subagent")

@observe(name="run_subagent")
def run_subagent(prompt: str) -> str:
    # ...

Langfuse 会自动捕获 run_subagent 函数的入参(主 Agent 给子 Agent 分配的 prompt)和返回值(子 Agent 最终的汇报总结)。它在后台形成了一个巨大的父 Span。

➡️嵌套的上下文管理器

run_subagent 内部,手动使用了with langfuse.start_as_current_observation(...)

由于它包裹在 run_subagent 执行期间,Langfuse 会自动将子 Agent 内部的每一次 LLM 调用(Generation)和具体的工具执行(Span)都挂载到 run_subagent 这个父节点之下。

langfuse 后台

类似:

▼ Trace: 用户要求写一个贪吃蛇游戏
  ▼ Generation: 主 Agent 思考 (决定派发任务)
  ▼ Span: Tool-call (task_dispatcher)
    ▼ Span: run_subagent ("去写一下蛇的移动逻辑")
      ▼ Generation: 子 Agent 思考 1
      ▼ Span: Tool-call (write_file)
      ▼ Generation: 子 Agent 思考 2 (发现写错了)
      ▼ Span: Tool-call (edit_file)
  ▼ Generation: 主 Agent 汇总汇报给用户

通过层级追踪进行 Agent 调试,便于有可以量化的指标

🔗具体代码

https://github.com/knight02-bit/agents-demo/blob/main/agents/s04_subagent.py

评论