背景
PR #162 补齐了 docs/bytemind-architecture/* 的架构与接口契约,但当前 internal/agent 仍以 Runner 为中心、同步串行执行。
需要把 agent 从“可用实现”迭代到“契约一致、可扩展、可观测”的主编排层。
现状差距
agent 入口仍是同步 RunPrompt,缺少统一 TurnEvent 流。
agent 对 session/context/provider/tools/runtime/policy/storage 的边界未完全网关化,耦合偏高。
工具权限评估未形成 agent 层显式前置决策链,审计事件不完整(尤其是 permission/task 关键事件)。
runtime 任务能力仍是占位实现,子代理编排(尤其异步归并/worktree)无法落地。
prompt_too_long 仅有预算前压缩,缺少“触发后 reactive compact + retry”闭环。
目标
对齐 PR 架构设计 #162 中 agent 契约的最小可用版本(MVP)。
保持现有 CLI/TUI 行为不回退,采用“适配层 + 分阶段迁移”。
迭代计划
验收标准
go test ./internal/agent -v 与 go test ./internal/runtime -v 通过。
新增主闭环契约测试:事件顺序、终态一致性、异常分支可重现。
新旧入口兼容:CLI/TUI 的现有调用方式不需要改动即可运行。
工具权限决策与审计日志可关联到 session_id/task_id/trace_id。
子代理 MVP 仅支持同步模式,明确不包含后台归并/worktree。
非目标
本 issue 不一次性实现完整五层权限细分。
本 issue 不实现异步子代理归并与 worktree 隔离。
本 issue 不做 provider 大重构。
模块架构设计(Agent 详细版)
1. 目标与边界
agent 负责“单回合编排”与“跨模块协调”,不直接内嵌 context/policy/runtime/storage 的实现细节。
Engine 成为唯一回合执行入口;Runner 仅做兼容适配,不再承载主编排逻辑。
TurnEvent 是回合执行唯一对外事件契约;CLI/TUI/审计统一消费该事件流。
保持现有 RunPrompt/RunPromptWithInput 调用方式不变,先兼容后迁移。
2. 分层结构(建议落地到 internal/agent)
engine(编排层)
提供 HandleTurn(ctx, req) (<-chan TurnEvent, error)。
负责回合状态机、事件发射、错误收敛、重试策略。
gateway(边界层)
定义并注入 Session/Context/Model/Policy/Tool/Runtime/Storage 七类网关接口。
屏蔽底层模块差异,确保 engine 只依赖接口。
runner_adapter(兼容层)
Runner 内部调用 Engine,把 TurnEvent 转为现有输出与旧 Event。
在迁移完成前维持旧行为与测试用例稳定。
event_codec(事件层)
统一 TurnEvent schema、序列号分配、终态判定与校验。
3. 对外契约(MVP)
建议新增(或在 issue 内冻结)如下最小契约:
// 新入口(MVP)
type Engine interface {
HandleTurn (ctx context.Context , req TurnRequest ) (<- chan TurnEvent , error )
}
type TurnRequest struct {
SessionID core.SessionID
UserMessage llm.Message
Mode plan.AgentMode
Workspace string
Assets map [llm.AssetID ]llm.ImageAsset
TraceID core.TraceID // 空值时由 engine 生成
}
type TurnEvent struct {
EventID core.EventID
SessionID core.SessionID
TaskID core.TaskID
TraceID core.TraceID
TurnID string
Sequence uint64
Type string // start|delta|tool_use|tool_result|complete|error
Timestamp time.Time
Payload map [string ]any
ErrorCode string
Retryable bool
}
4. 七类 Gateway 职责与最小方法
SessionGateway
职责:加载/持久化 session,维护会话消息 append 原子性。
最小方法:Load(...)、Save(...)、AppendMessages(...)。
ContextGateway
职责:系统提示组装、上下文预算评估、compact 执行与回放保真。
最小方法:BuildTurnMessages(...)、EstimateTokens(...)、Compact(...)。
约束:继续遵守 prompt 组装顺序:default -> mode -> runtime block -> active skill -> AGENTS.md。
ModelGateway
职责:封装 Create/Stream 调用与模型能力裁剪(tool use、parts 兼容)。
最小方法:Chat(...)、ChatStream(...)。
PolicyGateway
职责:在工具执行前输出显式 allow/deny/ask 决策与理由。
最小方法:DecideTool(ctx, in) (Decision, error)。
约束:决策优先级固定为:
hard_deny > explicit_deny > risk_rule > explicit_allow > mode_default > fallback_ask。
ToolGateway
职责:执行工具、返回结构化结果,屏蔽 registry/executor 细节。
最小方法:Execute(ctx, call, execCtx)。
约束:不得绕过 PolicyGateway 直接执行。
RuntimeGateway
职责:任务/子代理编排入口(MVP 先同步)。
最小方法:Submit(...)、Wait(...)、Cancel(...)、Stream(...)。
约束:子代理先支持 Spawn + Wait;异步归并/worktree 隔离后续 issue。
StorageGateway
职责:审计与提示历史写入,保证 event->audit 映射一致。
最小方法:AppendAudit(...)、AppendPromptHistory(...)。
5. 回合状态机与事件顺序
回合状态机(engine 内部唯一真源):
initialized -> preparing -> model_calling -> (tool_authorizing -> tool_executing -> model_calling)* -> completing -> completed
异常路径:任意中间态可转 failed。
事件顺序约束(单个 TurnID 内严格单调):
start
delta(可 0..N)
tool_use(可 0..N)
tool_result(与 tool_use 成对,允许 error 结果)
complete 或 error(二选一终态)
补充约束:
每个事件必须带 session_id + trace_id + sequence。
若存在 runtime 任务,补 task_id 并透传到审计事件。
complete/error 发出后 channel 关闭。
6. 权限前置决策链(工具调用前)
对每个 tool call 执行以下流程:
归一化工具名与参数(空名直接 deny)。
PolicyGateway.DecideTool 返回 {decision, reason_code, risk_level}。
发射 permission_decision 审计事件。
allow 才进入 tool_use -> tool_result;deny/ask 直接回写结构化 tool_result(error)并继续回合。
说明:
ask 在 CLI/TUI 可映射交互确认;本 issue MVP 可先按配置降级为 deny 或 allow(需文档固定)。
决策结果必须可重放(相同输入得到同类决策)。
7. prompt_too_long 的 reactive compact + retry(一次)
触发点:ModelGateway.Chat/ChatStream 返回 context too long(含本地预算与 provider 错误)。
处理流程:
首次命中 prompt_too_long 时,发 error(code=prompt_too_long_pre_retry)内部标记,不对外终止。
调用 ContextGateway.Compact(reason=reactive_prompt_too_long, keep_latest_user=true)。
重新构建消息并重试模型调用一次。
若仍失败,发终态 error(code=prompt_too_long),结束回合。
一致性约束:
只允许一次 reactive retry,避免无限循环。
压缩后必须保留当前回合用户输入与必要 tool_use/tool_result 配对语义。
8. Runtime/子代理集成(MVP)
engine 不直接管理子代理线程,统一通过 RuntimeGateway 触发。
同步子代理路径:
Spawn 返回 task_id
发射 task_state_changed(pending/running) 审计事件
Wait 收敛结果并映射为 tool_result 或 error
父回合取消时调用 RuntimeGateway.Cancel(task_id),并发射 task_state_changed(killed)。
9. 审计模型与可回放要求
最小审计动作集合:
permission_decision
tool_execute_start
tool_execute_result
task_state_changed
turn_complete / turn_error
关联键要求:
必带:session_id, trace_id
有任务时必带:task_id
同回合内建议记录:turn_id, sequence
10. Runner 兼容适配设计
Runner.RunPrompt* 保留签名。
Runner 内部流程改为:
组装 TurnRequest
调用 Engine.HandleTurn
消费 TurnEvent 并映射旧 Event(run_started/assistant_delta/tool_call_started/...)
保持当前 stdout 输出行为与测试快照不变
迁移完成判定:
runner.go 仅剩参数组装与适配逻辑,不再承担核心状态机。
11. 并发与故障收敛策略
单回合事件流由一个主 goroutine 串行发射,保证序号严格递增。
工具执行可并发扩展,但 MVP 先保持串行(行为兼容优先)。
任一不可恢复错误统一落为 error 终态事件并关闭流,禁止悬挂 channel。
12. 与阶段计划的映射
Phase 0:冻结 PolicyGateway 优先级与 reason_code 字典。
Phase 1:落地 Engine + RunnerAdapter + Gateway 接口骨架。
Phase 2:打通 TurnEvent 主链路与 reactive compact + retry。
Phase 3:接入同步子代理 + 审计回放校验。
13. 测试矩阵(新增建议)
事件流契约
顺序:start -> delta* -> tool_use* -> tool_result* -> complete|error
终态唯一性与 channel close。
权限链路
覆盖 hard_deny/explicit_deny/risk_rule/explicit_allow/mode_default/fallback_ask 六级优先级。
deny/ask 不执行工具,且有 permission_decision 审计。
reactive compact
首次 prompt too long -> compact -> retry 成功。
二次失败 -> prompt_too_long 终态错误。
兼容层
旧 Runner 入口输出与关键 Event 序列不回归。
子代理 MVP
Spawn + Wait 正常闭环。
父回合取消能传播到 runtime 任务。
背景
PR #162 补齐了
docs/bytemind-architecture/*的架构与接口契约,但当前internal/agent仍以Runner为中心、同步串行执行。需要把 agent 从“可用实现”迭代到“契约一致、可扩展、可观测”的主编排层。
现状差距
agent入口仍是同步RunPrompt,缺少统一TurnEvent流。agent对session/context/provider/tools/runtime/policy/storage的边界未完全网关化,耦合偏高。runtime任务能力仍是占位实现,子代理编排(尤其异步归并/worktree)无法落地。prompt_too_long仅有预算前压缩,缺少“触发后 reactive compact + retry”闭环。目标
agent契约的最小可用版本(MVP)。迭代计划
hard_deny > explicit_deny > risk_rule > explicit_allow > mode_default > fallback_ask)并固化到 agent 依赖链。Engine.HandleTurn(ctx, req) (<-chan TurnEvent, error),Runner 作为兼容适配器调用新 Engine。SessionGateway/ContextGateway/ModelGateway/PolicyGateway/ToolGateway/RuntimeGateway/StorageGateway最小接口与默认实现。start/delta/tool_use/tool_result/complete/error事件流;工具调用前必须经过PolicyGateway。Spawn + Wait),异步归并与 worktree 隔离单独 issue。验收标准
go test ./internal/agent -v与go test ./internal/runtime -v通过。session_id/task_id/trace_id。非目标
模块架构设计(Agent 详细版)
1. 目标与边界
agent负责“单回合编排”与“跨模块协调”,不直接内嵌 context/policy/runtime/storage 的实现细节。Engine成为唯一回合执行入口;Runner仅做兼容适配,不再承载主编排逻辑。TurnEvent是回合执行唯一对外事件契约;CLI/TUI/审计统一消费该事件流。RunPrompt/RunPromptWithInput调用方式不变,先兼容后迁移。2. 分层结构(建议落地到
internal/agent)engine(编排层)HandleTurn(ctx, req) (<-chan TurnEvent, error)。gateway(边界层)Session/Context/Model/Policy/Tool/Runtime/Storage七类网关接口。runner_adapter(兼容层)Runner内部调用Engine,把TurnEvent转为现有输出与旧Event。event_codec(事件层)TurnEventschema、序列号分配、终态判定与校验。3. 对外契约(MVP)
建议新增(或在 issue 内冻结)如下最小契约:
4. 七类 Gateway 职责与最小方法
SessionGatewayLoad(...)、Save(...)、AppendMessages(...)。ContextGatewayBuildTurnMessages(...)、EstimateTokens(...)、Compact(...)。default -> mode -> runtime block -> active skill -> AGENTS.md。ModelGatewayCreate/Stream调用与模型能力裁剪(tool use、parts 兼容)。Chat(...)、ChatStream(...)。PolicyGatewayallow/deny/ask决策与理由。DecideTool(ctx, in) (Decision, error)。hard_deny > explicit_deny > risk_rule > explicit_allow > mode_default > fallback_ask。ToolGatewayExecute(ctx, call, execCtx)。PolicyGateway直接执行。RuntimeGatewaySubmit(...)、Wait(...)、Cancel(...)、Stream(...)。Spawn + Wait;异步归并/worktree 隔离后续 issue。StorageGatewayAppendAudit(...)、AppendPromptHistory(...)。5. 回合状态机与事件顺序
回合状态机(engine 内部唯一真源):
initialized -> preparing -> model_calling -> (tool_authorizing -> tool_executing -> model_calling)* -> completing -> completedfailed。事件顺序约束(单个
TurnID内严格单调):startdelta(可 0..N)tool_use(可 0..N)tool_result(与 tool_use 成对,允许 error 结果)complete或error(二选一终态)补充约束:
session_id + trace_id + sequence。task_id并透传到审计事件。complete/error发出后 channel 关闭。6. 权限前置决策链(工具调用前)
对每个 tool call 执行以下流程:
PolicyGateway.DecideTool返回{decision, reason_code, risk_level}。permission_decision审计事件。allow才进入tool_use -> tool_result;deny/ask直接回写结构化 tool_result(error)并继续回合。说明:
ask在 CLI/TUI 可映射交互确认;本 issue MVP 可先按配置降级为 deny 或 allow(需文档固定)。7.
prompt_too_long的 reactive compact + retry(一次)触发点:
ModelGateway.Chat/ChatStream返回 context too long(含本地预算与 provider 错误)。处理流程:
prompt_too_long时,发error(code=prompt_too_long_pre_retry)内部标记,不对外终止。ContextGateway.Compact(reason=reactive_prompt_too_long, keep_latest_user=true)。error(code=prompt_too_long),结束回合。一致性约束:
8. Runtime/子代理集成(MVP)
RuntimeGateway触发。Spawn返回task_idtask_state_changed(pending/running)审计事件Wait收敛结果并映射为tool_result或errorRuntimeGateway.Cancel(task_id),并发射task_state_changed(killed)。9. 审计模型与可回放要求
最小审计动作集合:
permission_decisiontool_execute_starttool_execute_resulttask_state_changedturn_complete/turn_error关联键要求:
session_id,trace_idtask_idturn_id,sequence10. Runner 兼容适配设计
Runner.RunPrompt*保留签名。TurnRequestEngine.HandleTurnTurnEvent并映射旧Event(run_started/assistant_delta/tool_call_started/...)迁移完成判定:
runner.go仅剩参数组装与适配逻辑,不再承担核心状态机。11. 并发与故障收敛策略
error终态事件并关闭流,禁止悬挂 channel。12. 与阶段计划的映射
Phase 0:冻结PolicyGateway优先级与 reason_code 字典。Phase 1:落地Engine + RunnerAdapter + Gateway 接口骨架。Phase 2:打通TurnEvent主链路与reactive compact + retry。Phase 3:接入同步子代理 + 审计回放校验。13. 测试矩阵(新增建议)
start -> delta* -> tool_use* -> tool_result* -> complete|errorhard_deny/explicit_deny/risk_rule/explicit_allow/mode_default/fallback_ask六级优先级。permission_decision审计。prompt_too_long终态错误。Runner入口输出与关键Event序列不回归。Spawn + Wait正常闭环。