runAgent 解析
定位
runAgent() 是子 agent 的真正运行入口。
文件:
src/tools/AgentTool/runAgent.ts
一句话:
runAgent()不是一个新引擎,而是“为子 agent 重新构造运行上下文,然后再次调用统一的query()主循环”。
核心职责
1. 生成子 agent 身份
- 生成
agentId - 设置 transcript sidechain
- 记录 metadata
- 注册 tracing / analytics context
2. 构造初始消息
- 普通 agent:用简单 prompt message
- fork agent:携带父上下文
forkContextMessages - 并过滤 incomplete tool calls,避免 API 协议错误
3. 构造 agent-specific context
userContextsystemContexttoolPermissionContextagent-specific appState viewagent-specific tool poolagent-specific abortController
4. 构造 system prompt
普通 agent:
- 使用 agent 自己的 system prompt
fork agent:
- 使用父 agent 已渲染好的 system prompt bytes
- 目标是 prompt cache byte-identical
5. 创建子上下文
核心调用:
createSubagentContext(...)
这一步决定:
- 哪些状态从父级继承
- 哪些隔离
- 哪些 callback 共享
- 哪些缓存复制
6. 最终重新进入 query()
真正执行发生在:
for await (const message of query({...}))这是理解整套 agent 体系最关键的一点:
- 主 agent 用
query() - 子 agent 也用
query()
重要设计点
子 agent 与主 agent 同构
这意味着:
- 主 / 子 agent 共用同一套 tool system
- 共用同一套 permission system
- 共用同一套 transcript / message 机制
上下文隔离是通过重新构造 ToolUseContext 实现的
而不是通过重写整个 runtime。
async agent 与 sync agent 的差别不在 runAgent 本身
runAgent() 负责“跑”。
是否:
- 前台跑
- 后台跑
- 变成 task
这些决策主要在 AgentTool.call() 和 task 层完成。
与其他模块关系
上游
AgentTool.call()调用它
下游
query()真正执行 looprecordSidechainTranscript()写 sidechain transcriptcreateSubagentContext()派生上下文initializeAgentMcpServers()附加 agent-specific MCP servers
当前理解
runAgent() 才是子 agent runtime 的门槛文件。
如果要真正看懂:
- 子 agent 如何继承父上下文
- 为何 fork child 能与父请求共享 prompt cache
- 子 agent 为什么仍然能安全跑同一套 query loop
那必须继续读:
createSubagentContextquery.tstoolOrchestration