Github开源生信云平台 DEMO
是的,“同一轮发出多个 agent 工具调用”就是 executeTools 的 calls 里有多个 Name == "agent" 的元素。三种说法其实是三个不同层次的描述,下面拆开看。
executeTools
calls
Name == "agent"
provider.Response.ToolCalls
native.Run
executeTools(ctx, executor, response.ToolCalls, rt)
Name == AgentToolName
agent
prompts
agentTool.Execute
len(tasks) > 1
runBatch
response.ToolCalls 直接就是 executeTools 的 calls,所以前两者是同一件事的两种叫法:协议层叫“多个 tool_use”,执行层叫“calls 有多个”。
response.ToolCalls
模型一条 assistant 消息里输出两个调用:
{ "role": "assistant", "content": "我并行派两个子 Agent 去查。", "tool_calls": [ { "id": "call_1", "name": "agent", "arguments": "{\"prompt\":\"查 internal/agent 下的工具注册\"}" }, { "id": "call_2", "name": "agent", "arguments": "{\"prompt\":\"查 internal/handler 下调用 AgentService 的位置\"}" } ] }
进入 native.Run:
response.ToolCalls = [call_1, call_2] ↓ executeTools(calls=[call_1, call_2]) ↓ 两个 goroutine 并发(上限 maxConcurrentAgentCalls=4) results = [ {ToolCallID:"call_1", Content:"..."}, {ToolCallID:"call_2", Content:"..."}, ] ↓ history 追加 1 条 tool 消息(含 2 个 ToolResult) ↓ 父模型下一轮看到 2 份独立结果,自己写汇总
事件时间线:2 个 tool_call 事件 + 2 个 tool_result 事件。
tool_call
tool_result
模型只发一个 tool_use:
{ "role": "assistant", "tool_calls": [ { "id": "call_1", "name": "agent", "arguments": "{\"prompts\":[{\"name\":\"tools\",\"prompt\":\"查 internal/agent 下的工具注册\"},{\"name\":\"handlers\",\"prompt\":\"查 internal/handler 下调用 AgentService 的位置\"}]}" } ] }
进入执行层:
response.ToolCalls = [call_1] ← calls 只有 1 个 ↓ executeTools(calls=[call_1]) ← 不会走并发分支(只有 1 个 agent call) ↓ agentTool.Execute → runBatch(2 tasks) ← 并发发生在这里 ↓ results = [{ToolCallID:"call_1", Content:"## tools\n...\n## handlers\n..."}] ↓ 父模型下一轮看到 1 份已拼接好的结果
事件时间线:1 个 tool_call 事件 + 1 个 tool_result 事件。
executeTools.calls
maxConcurrentAgentCalls=4
agentTool.runBatch
MaxAgentConcurrency=8
ToolResult
## name
IsError
[error]
executeTools 的 calls 里不只是 agent 调用。例如模型一轮发出:
calls = [bash, agent, agent, view]
实际行为是:
bash
view
[bash, agent, agent, view]
tool_call_id
agentTool
如果目标是“最贴近主流工具、最省维护”,用多个 tool_use 即可;prompts 批量模式是减少工具块数量、让 UI 更安静的可选糖。