zero Agent Loop 处理详细序列图

agent.Run 多轮循环:分区工具 → 压缩 → 流式收集 → 错误恢复 → 完成判定 / 工具执行(权限·沙箱·钩子)→ 自纠错·升级

Caller TUI / exec agent.Run 循环 loop.go Compactor+Guards compaction/guardrails Provider / LLM stream + collect executeToolCall 权限 / 裁决 Tools+Sandbox registry / hooks 入口 · agent.Run(ctx, prompt, provider, options) — 一次性初始化 Run(...) 初始化: • provider nil 校验;maxTurns 默认 12;permissionMode 默认 Auto • SeedMessagesWithImages(buildSystemPrompt, prompt, images) • newGuardState / newCompactionState;loaded{} 记录已加载 deferred 工具 • continueNudges / acceptanceRequested 计数器初始化 result := Result{Messages: copy(messages)} 主循环 · for turn := 0; turn < maxTurns; turn++ (紫框内为每轮重复) loop [turn] · result.Turns = turn+1 partitionTools(registry, mode, options, loaded) exposed(本轮可见工具集) maybeCompact(PROACTIVE:接近窗口则摘要旧历史) CompletionRequest{messages(copy), tools:exposed, reasoningEffort} OnContext(MeasureContext) 上报本轮上下文预算(可选) streamWithReconnect(request) — 断连退避重连 stream(token / reasoning / tool-call 片段) OnText / OnReasoning / OnToolCallStart / Delta / OnUsage CollectStreamWithOptions → collected{Text, ToolCalls, Reasoning, Usage, Error, FinishReason} 流错误恢复(recoverStreamError): • image 拒绝 → 友好错误,停止运行 • 上下文超限 → REACTIVE 压缩一次并重发本轮 • 空答文本的 stall 超时 → 退避重试(≤ maxStreamStallRetries) 已输出可见 prose 的 stall 不重试(避免重复答案文本) append assistant message(含 ToolCalls + Reasoning 思考块,供下轮 replay) alt [collected 的内容形态] ┌ 分支 0 · 工具调用被丢弃 / 空轮 DroppedToolCalls>0 → 追加 droppedToolCallNotice 并 continue;空轮 → guards.observeTurn 计数,runaway 上限则停止 纯空文本但未超上限 → 追加"继续或给最终答案"提示并 continue ├ 分支 A · 仅文本(len(ToolCalls)==0)→ 完成判定 guards.observeTurn / pendingPlanItems RequireCompletionSignal 门控(headless 开;TUI 关): 1. selfReportedIncompletion → Incomplete=true 立即返回 2. 续写线索 / 未完成 plan 项 → continueNudge 续推(bounded);耗尽后 cue 判 Incomplete 3. SelfCorrect 开 → 一次 task-grounded 验收核对(acceptanceRequested) 全通过 → result.FinalAnswer = collected.Text,return(跳出循环) 门控关闭时:有文本即视为最终答案,直接返回 └ 分支 B · 含工具调用 → 内层逐个 executeToolCall loop [for index, call := range collected.ToolCalls] OnToolCall(call) → 记录 + captureCheckpoint(安全 rewind) executeToolCall(ctx, registry, call, permissionMode, options) 前置校验(顺序): decodeToolArguments(解析失败即 error 结果) ToolAllowedByFilters(enabled/disabled) specDraft 未广告工具拒绝 PrePermissionRejecter 提前否决 ask_user / request_permissions → 专用拦截路径 权限裁决: unsafe→全允许;effectivePermission==Allow→允许 matchCommandPrefix 白名单命中 Sandbox.Evaluate 预检 → preflightDecision 需询问且有回调 → OnPermissionRequest(阻塞) 决策:Allow/Session/Prefix/Always/Deny/Cancel 授权 grant(network/fs/inline)+ cleanup defer dispatchBeforeTool(钩子可否决) registry.RunWithOptions(沙箱执行) Result{output,status,changedFiles,sandboxDecision} 沙箱受限重试 → 无沙箱重试;OnPermission(event);dispatchAfterTool 追加反馈 (ToolResult, abortErr) OnToolResult → 记录;append tool message;loaded[]∪LoadedTools 工具批次收尾(内层循环结束后): • abortErr / ctx.Done → appendAbortedToolResults 补齐后返回(保持 replay 合法) • stopReason 工具(如 finish)→ FinalAnswer + 返回;重复失败 guard → 停止 • SelfCorrect.AfterEdit(union changedFiles) → 反馈以 user 消息追加(批后,保 tool_result 连续) • ModelSwitcher(escalate_model 请求)→ 重建 provider,每轮至多一次 • dropped 通知 / failureHint / progressReminder / planReminder(一次性 nudge)→ continue 下一轮 ↻ 下一轮 循环耗尽 · 达到 maxTurns 上限(未在循环内 return) finalAnswerAfterMaxTurns(要求"不再调用工具的简短最终总结") answer / finishReason 有总结 → FinalAnswer=answer(截断则 Incomplete) 仍空 → FinalAnswer=maxTurnsAnswer,Incomplete=true 返回 · Result{FinalAnswer, Incomplete, IncompleteReason, StopReason, FinishReason, Turns, Messages, Usage} return (result, err) → 调用方(TUI agentResponseMsg / exec writer.final) defer runPermissions.cleanup():释放本轮授予的 turn 级网络/文件系统权限 图例 循环内部调用 provider 流式 / 循环回边 工具执行 权限 / 钩子裁决 回调 → 调用方 返回值 注:TUI 与 headless exec 复用同一 agent.Run;差异在于回调是否注册、RequireCompletionSignal 是否开启,以及权限交互 vs 自动裁决。

每轮骨架

  • partitionTools 按权限/过滤器/已加载暴露工具
  • maybeCompact 主动压缩逼近窗口的历史
  • streamWithReconnectCollectStream
  • • append assistant(含思考块,供下轮 replay)

流式与错误恢复

  • • 回调 OnText/OnReasoning/OnToolCall* 转调用方
  • • image 拒绝 → 友好错误停止
  • • 上下文超限 → REACTIVE 压缩重发本轮
  • • 空答 stall → 退避重试;已输出 prose 不重试

完成判定(分支 A)

  • RequireCompletionSignal:headless 开 / TUI 关
  • • 自报未完成 → Incomplete 立即返回
  • • 续写线索 / 未完成 plan → 续推 nudge(有上限)
  • • SelfCorrect 开 → 一次 task-grounded 验收

工具执行(分支 B)

  • • 逐个 executeToolCall;每次前 captureCheckpoint
  • • 解析→过滤→specDraft→PrePermissionRejecter
  • ask_user/request_permissions 专用拦截
  • registry.RunWithOptions 沙箱内执行

权限与钩子

  • • Allow/Session/Prefix/Always/Deny/Cancel 六类决策
  • • 授予 network/fs/inline 权限,turn 结束 cleanup
  • beforeTool 钩子可否决;afterTool 追加反馈
  • • 沙箱受限 → 无沙箱重试路径

批次收尾与升级

  • • abort/stopReason → 补齐 aborted 结果保 replay 合法
  • SelfCorrect.AfterEdit 对 union changedFiles 验证
  • ModelSwitcher 每轮至多一次模型升级
  • • 达 maxTurns → finalAnswerAfterMaxTurns 强制收尾