分层架构总览
为什么 Agent 框架必须分层
一个 coding agent 看起来像“把用户消息发给模型,然后执行工具”,但真实系统很快会变复杂:
- 模型 provider 不同,streaming 和 tool call 格式不同。
- Session 需要恢复、压缩、回放、审计。
- Tools 可能来自本地、MCP、插件、远端 runner。
- 权限必须统一,否则 shell、patch、MCP、skill 会各自开后门。
- Client 形态很多:Web、CLI、IDE、ACP、移动端、channel。
- Memory 和 skills 会影响上下文,如果不可审计,会导致行为漂移。
如果不分层,项目会变成 provider、UI、tool、memory、协议互相交叉引用的泥球。
本项目采用一条主线:
构建一个 local-first、event-sourced 的 agent core,并用严格 adapter 隔离 models、tools、memory、skills、protocols 和 clients。
核心分层
Client / Protocol Layer Web, CLI, TUI, IDE, ACP, Mobile, Channels
Agent Host API Thin API around sessions, events, permissions, replay
Agent Core SessionEngine, turn state machine, orchestration
Context Layer Instructions, memory, skills metadata, MCP resources, compaction
Model Gateway Provider adapters, normalized stream events, tool call normalization
Tool Layer Tool registry, tool router, local tools, MCP tools, plugin tools
Permission Layer Policy, approval, risk classification, audit
Storage Layer Event log, indexes, artifacts, replay, snapshots
Observability / Quality Telemetry, golden transcripts, Web regression, architecture fitness一次 Turn 发生了什么
1. Client sends user prompt2. AgentHost creates or loads session3. SessionEngine starts a turn4. ContextBuilder builds model input5. ModelGateway streams normalized model events6. Model requests a tool call7. ToolRouter resolves the tool8. PermissionEngine decides allow / deny / ask9. ToolExecutor runs if allowed10. Tool result is appended to event log11. Model continues or finalizes12. Client renders events13. Session can be replayed from event log事实来源
系统运行时的事实来源不是 UI state,也不是 provider response,而是 append-only event log。
这意味着:
- Client 可以断线重连。
- Web 和 CLI 可以展示同一段 session。
- 测试可以重放 golden transcript。
- 审计可以追踪谁批准了哪个工具。
- 未来 remote execution 可以沿用同一套事件语义。
分层边界
Client 不能拥有 agent 逻辑
Client 只能:
- 发 prompt。
- 渲染 event stream。
- 展示 permission request。
- 展示 diff、timeline、context。
- 调用 session/replay API。
Client 不能:
- 构造 model prompt。
- 直接执行 tool。
- 直接写 event log。
- 直接改变 memory。
Core 不能知道 provider SDK
Core 只能看到 normalized events:
model.deltamodel.tool_call_requestedmodel.completedmodel.failed
Core 不能判断“这是 OpenAI 的字段还是 Anthropic 的字段”。
Tool 不能绕过 Permission
所有工具,无论来源是 local、MCP、plugin、skill、remote runner,都必须走:
ToolRouter -> PermissionEngine -> ToolExecutorMemory 必须可审计
Memory 影响长期行为,因此不能静默写入。MVP 阶段采用:
conversation evidence -> memory candidate -> user/reviewer approval -> durable memory架构成熟度阶段
Stage 1:Local Event Core
先实现本地 session、event log、fake model、Web timeline。
目标是证明:
- turn 可以运行。
- event 可以 replay。
- Web 可以观察系统。
Stage 2:Real Model + Safe Tools
加入 model provider、read/search/shell/patch、permission engine。
目标是证明:
- agent 能完成真实小任务。
- 工具行为可审计。
- 危险动作需要授权。
Stage 3:Context + Skills + MCP
加入 instruction hierarchy、memory candidates、skills、MCP。
目标是证明:
- 上下文可控。
- 能力可扩展。
- 外部工具不破坏安全边界。
Stage 4:Protocol + Remote
加入 ACP、remote-control、mobile、automation、plugin registry。
目标是证明:
- core 可以被多种 client 驱动。
- remote 和 local 在 event/replay 层语义一致。
设计检查问题
每当新增能力,问:
- 它属于哪一层?
- 它的输入输出是什么?
- 它是否需要新 event?
- 它是否会执行 tool?
- 它是否影响 memory/context?
- 它是否能 replay?
- Web 是否能观察?
- 它是否绕过了 adapter 边界?
答不清,就先写 ADR,不要直接实现。