您的位置:首页 > 手游攻略 > Agent Transfer:让AI将任务指派给更胜任的AI

Agent Transfer:让AI将任务指派给更胜任的AI

作者:互联网  时间: 2026-06-30 09:03:52  

读完这篇你会知道


一、为什么一个 Agent 不够

单 Agent 处理任何问题有一个根本限制:上下文会越来越长

Agent Transfer:让 AI 把任务交给更合适的 AI

当你要求同一个 Agent 既搜索资料、又写代码、又做数学计算,历史消息越积越多,模型要在所有历史里找线索,注意力被稀释。而且,同一个系统 Prompt 很难同时把三个角色都交代清楚——"你是搜索员,也是程序员,也是数学家"——通常意味着什么都不精。

多 Agent 的核心价值就在这里:每个 Agent 只看自己需要的上下文,专注自己的职责


二、方案一(推荐):把 Agent 包装成工具

Eino 源码注释里明确写着(agent_tool.go:69):

 复制代码// NewAgentTool creates a tool that wraps an agent for invocation.

用法:把一个子 Agent 包装成工具,父 Agent 通过普通的工具调用来"雇用"它。这是 ADK 官方唯一推荐的 Multi-Agent 模式

 复制代码// 创建子 Agent
researchAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
    Name:        "research_agent",
    Description: "the agent responsible to search the internet for info",
    Instruction: "You are a research agent...",
    Model:       m,
    ToolsConfig: adk.ToolsConfig{...},
})// 把子 Agent 变成一个工具
researchTool := adk.NewAgentTool(ctx, researchAgent)// 父 Agent 把这个"工具"加到自己的工具列表
parentAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
    Name:  "project_manager",
    Model: m,
    ToolsConfig: adk.ToolsConfig{
        ToolsNodeConfig: compose.ToolsNodeConfig{
            Tools: []tool.BaseTool{researchTool, codeTool, reviewTool},
        },
    },
})

从外部看,父 Agent 还是正常的 ReAct 循环,只是"工具"恰好是另一个 Agent。父 Agent 不关心子 Agent 内部怎么工作——它只是调用了一个名叫 research_agent 的工具,传入 {"request": "find 2024 US GDP"}, 等待返回结果。

关键特性:动作边界隔离

子 Agent 内部可能触发 Exit、Transfer、BreakLoop 等动作,但这些动作不会传到父 Agent(源码 agent_tool.go:90-93):

 复制代码// Action Scoping:
// - Interrupted: Propagated via CompositeInterrupt (interrupt/resume works across boundaries)
// - Exit, TransferToAgent, BreakLoop: Ignored outside the agent tool

白话:子 Agent 想"结束任务",对它自己来说任务确实结束了,但父 Agent 只看到"这个工具调用完成了,返回了结果"。子 Agent 不能意外终止父 Agent 的执行流。唯一的例外是 Interrupted(中断等待人工确认),这个会通过 CompositeInterrupt 传递出去,让整个系统都知道需要暂停等待用户。

Supervisor 预制模式

supervisor.New 是 AgentTool 之上的一个预制封装(源码在 adk/prebuilt/supervisor):

 复制代码// eino-examples/adk/multiagent/supervisor/agent.go:192
supervisorAgent, err := supervisor.New(ctx, &supervisor.Config{
    Supervisor: sv,                                    // 主控 Agent
    SubAgents:  []adk.Agent{searchAgent, mathAgent},  // 子 Agent 列表
})

supervisor.New 自动把每个子 Agent 包装成 AgentTool,注入到主控 Agent 的工具列表里。你只需要定义主控 Agent 的 Instruction("你是项目经理,有两个下属……"),其余的工具调用由 ReAct 循环自动处理。


三、方案二(不推荐):LLM 驱动的 Agent 切换

这是另一套机制——让模型自己决定"我要交给哪个 Agent"。

 复制代码// eino-examples/adk/intro/transfer/transfer.go:35
a, err := adk.SetSubAgents(ctx, routerAgent, []adk.Agent{chatAgent, weatherAgent})

SetSubAgents 做了两件事:

  1. 把子 Agent 的名字和描述告诉 Router Agent(注入到系统 Prompt)
  2. 给 Router Agent 加一个内置工具 transfer_to_agent(参数:agent_name

执行时,RouterAgent 的模型看到用户问题,自己判断该交给谁,然后调用 transfer_to_agent("WeatherAgent")——相当于给自己的下一步指路。

 复制代码用户:"北京今天天气?"
RouterAgent → 判断:这是天气相关 → 调用 transfer_to_agent(agent_name="WeatherAgent")
WeatherAgent → 调用 get_weather(city="Beijing") → 返回结果

这个模式看起来自然,但 Eino 官方在源码里明确标注(utils.go:92-95):

 复制代码// NOT RECOMMENDED: Agent transfer with full context sharing between agents has not
// proven to be more effective empirically. Consider using ChatModelAgent with AgentTool
// or DeepAgent instead for most multi-agent scenarios.

核心问题:全上下文共享。当 RouterAgent 的会话历史传给 WeatherAgent 时,WeatherAgent 要处理一堆它不需要的上下文(RouterAgent 的历史消息),既浪费 Token,又可能干扰判断。

上下文隔离机制

ADK 在实现 Transfer 时做了一个折中(deterministic_transfer.go:166)——创建 IsolatedSession

 复制代码isolatedSession := &runSession{
    Values:    parentSession.Values,   // 共享 session values(键值对)
    valuesMtx: parentSession.valuesMtx,
    // Events: 不继承(默认为空)
}

子 Agent 有独立的事件历史(不继承父 Agent 的全部消息),但共享 session.Values(通过 AddSessionValue/GetSessionValues 存取的键值对)。这样可以在两个 Agent 间传递少量结构化状态,同时避免把全部对话历史扔过去。


四、方案三(不推荐):确定性移交

有时候移交目标不需要 AI 判断,就是固定的。AgentWithDeterministicTransferTo 用于这个场景:

 复制代码// 执行完 agentA,固定移交给 agentB
wrappedA := adk.AgentWithDeterministicTransferTo(ctx, &adk.DeterministicTransferConfig{
    Agent:        agentA,
    ToAgentNames: []string{"agentB"},
})

执行完 agentA 的全部逻辑后,框架自动追加两条消息(assistant 说"我要移交给 agentB" + tool 确认消息),然后触发 TransferToAgent 动作,Session 流转到 agentB。

白话:这是硬编码的流水线——A 完事了一定交给 B,不经过任何 AI 决策。适合固定流程("报告总结完毕,一定发给审阅 Agent"),不适合根据内容动态路由。

同样标注了 NOT RECOMMENDED,原因相同:全上下文共享。


五、三种方案一张表

AgentTool(推荐)SetSubAgentsDeterministicTransfer
路由决策者父 Agent 的 LLM(工具调用)Router Agent 的 LLM代码硬编码
上下文共享隔离(只传 request 字符串)全部共享(IsolatedSession 折中)全部共享
子 Agent 动作边界Exit/Transfer 不传出全部传出全部传出
适合场景绝大多数场景特定路由式场景固定流水线
官方立场 推荐️ 不推荐️ 不推荐

六、完整示例:Supervisor 模式(AgentTool 推荐路径)

 复制代码// eino-examples/adk/multiagent/supervisor/agent.go(精简)
func buildSupervisor(ctx context.Context) (adk.Agent, error) {
    sv, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
        Name:  "supervisor",
        Instruction: `You are a supervisor managing two agents:
- a research agent: assign research-related tasks
- a math agent: assign math-related tasks
Do not do any work yourself.`,
        Model: m,
        Exit:  &adk.ExitTool{},   // 主控完成后用 exit 工具退出
    })    searchAgent, _ := buildSearchAgent(ctx)  // 有 search 工具的 Agent
    mathAgent, _ := buildMathAgent(ctx)      // 有 add/multiply/divide 工具的 Agent    // supervisor.New 内部自动 NewAgentTool 包装每个子 Agent
    return supervisor.New(ctx, &supervisor.Config{
        Supervisor: sv,
        SubAgents:  []adk.Agent{searchAgent, mathAgent},
    })
}

运行时发生的事:

 复制代码用户:"Find US and NY GDP in 2024. What % of US GDP was NY?"1. Supervisor 收到问题
2. Supervisor 决定:先搜索 → 调用 research_agent 工具,传入问题
3. research_agent 内部:搜索工具 → 返回 "US $29.18T, NY $2.297T"
4. Supervisor 收到搜索结果
5. Supervisor 决定:再计算 → 调用 math_agent 工具,传入数字
6. math_agent 内部:divide(2.297, 29.18) → 0.0787
7. Supervisor 汇总结果,调用 exit 工具,结束

主控 Agent 从未自己搜索或计算,只做"任务分配 + 汇总"。每个子 Agent 只看自己的 request,不知道其他 Agent 的存在。


七、对话历史怎么处理:一个实际问题

当子 Agent(AgentTool 模式)完成任务后,父 Agent 的对话历史里只有:

  • Tool 调用请求:{"tool": "research_agent", "input": {"request": "..."}}
  • Tool 返回结果:{"result": "US GDP was $29.18T..."}

子 Agent 内部的全部过程(搜索了哪些网页、中间想了什么)不进入父 Agent 的上下文。这是 AgentTool 的设计意图:结果传递,过程隔离

如果父 Agent 需要子 Agent 的中间事件(比如流式展示子 Agent 的思考过程),可以开启 EmitInternalEvents

 复制代码adk.ToolsConfig{
    EmitInternalEvents: true,  // 子 Agent 的事件实时推送给 Runner 的消费者
    ...
}

注意:这些内部事件只推给外部消费者(UI 显示),不记录在父 Agent 的 runSession 里——父 Agent 的历史依然只有工具调用和结果,不会因此膨胀。


小结

AgentTool 是唯一被官方推荐的 Multi-Agent 模式,原因很简单:上下文隔离,边界清晰。父 Agent 通过 ReAct 工具调用驱动子 Agent,子 Agent 只看到自己的输入,不背负无关历史。supervisor.New 是在 AgentTool 之上的预制封装,适合"主控 + 多专家"的常见结构。SetSubAgentsDeterministicTransfer 虽然存在且功能可用,但源码里的 NOT RECOMMENDED 注释来自团队实测——在绝大多数场景下,AgentTool 效果更好,不要忽视这个提示。

下篇继续。


代码来源:cloudwego/eino · cloudwego/eino-examples

相关资讯

最新游戏

更多

Copyright©2010-2019. All rights reserved | 波波三国游戏官网|[email protected]

备案编号:湘ICP备2022015115号-4