🏛️ 整体架构

欢迎进入第四阶段!前三个阶段你学了理论(F)和框架(LangChain/LangGraph)。现在看一个真实开源的 AI 编码产品如何把这些概念落地。本章鸟瞰 OpenCode 的整体架构,特别是 Agent 循环的完整数据流——你会发现它和 F3 章的图一一对应

本章目标

  • 鸟瞰 OpenCode 的整体架构和核心模块
  • 理解 Agent 循环的完整数据流(从用户输入到返回)
  • 建立"模块职责映射":每个文件干什么
  • 对照 F3 章的循环图,验证理论如何落地
  • 认识 Effect 框架在 OpenCode 中的角色
📚 OpenCode 是什么

OpenCode 是一个开源的 AI 编码 Agent 产品(类似 Claude Code / Cursor),用 TypeScript + Bun 实现。它是"把前面学的所有 Agent 理论,打磨成可靠产品"的范例。本阶段重点呈现概念对照(看理论如何落地)和工程实践(看产品怎么做)。

技术栈:TypeScript + Effect

OpenCode 用 TypeScript(Bun 运行时),并深度使用 Effect 框架。理解 Effect 是看懂 OpenCode 的前提:

Effect 概念类比在 OpenCode 的作用
Effect.gen(function* () {...})async/await 的强化版所有副作用都用 Effect 表达
Context.Service / Layer依赖注入容器每个模块是一个 Service(Agent/Session/Tool...)
Stream异步迭代器LLM 事件流、流式输出
typed errors类型安全的异常工具错误、权限拒绝等
💡 Effect ≈ LangChain 的 Runnable + 更强

如果你觉得 Effect 眼熟——它和 LangChain 的 Runnable 思想相通:都是"可组合、可中断、可重试的工作单元"。OpenCode 用 Effect 而非 LangChain,是因为 TS 生态和它的需求(强类型副作用管理)。看完本章你会发现思想是一致的,只是语言不同

核心模块全景

模块路径职责对应 LangGraph 概念
Agentsrc/agent/agent.ts定义 Agent(提示+模型+权限)图的配置
Sessionsrc/session/session.ts会话数据持久层Checkpointer
SessionPromptsrc/session/prompt.tsAgent 循环(runLoop)图执行 / super-step
LLMsrc/session/llm.tsLLM 调用服务ChatModel
Processorsrc/session/processor.ts流事件处理stream 消费
Toolsrc/tool/工具定义与注册ToolNode / @tool
Permissionsrc/permission/权限控制interrupt(HITL)
Providersrc/provider/模型提供商抽象ChatOpenAI 等

Agent 循环完整数据流 ★

这是本章核心。OpenCode 的 Agent 循环数据流,和 F3 章的总参照图一一对应

用户输入 prompt.ts · prompt() 创建 user message → 调 loop() runLoop · while(true)(prompt.ts:1081)— 对应 F3 的 Agent 循环 读消息历史 MessageV2.filter 调 LLM handle.process() 处理事件流 processor.ts 有tc? 执行工具 SessionTools.resolve → tool.execute 结果写入 Session 事件落库 → 下轮读取 有 → 执行工具 最终回答(无 tc → break)
图 OC1.1 · ★ OpenCode Agent 循环数据流——和 F3 章总参照图一一对应

数据流对应的具体文件

把上面的数据流落到具体源码文件。这是后续章节的"地图":

数据流步骤源码文件精读章节
用户输入 → 创建消息session/prompt.ts:1052 prompt()OC2
★ 主循环 while(true)session/prompt.ts:1081 runLoop()OC2
读消息历史MessageV2.filterCompactedEffectOC2
组装 system promptsession/system.tsOC5
解析工具session/tools.ts:39 resolve()OC3
调 LLMsession/llm.ts LLM.Service.stream()OC2
处理流事件session/processor.ts:625 process()OC2
执行工具tool/tool.ts define + wrapOC3
权限检查permission + ctx.ask()OC4
结果持久化session/session.ts updatePartOC5
上下文压缩session/compaction.tsOC5

双运行时架构

OpenCode 的 LLM 调用有个独特设计——双运行时(源自 session/llm/AGENTS.md):

LLM.Service .stream() AI SDK 路径(默认) streamText + ai-sdk.ts Native 路径(opt-in) @opencode-ai/llm 直连 统一 LLMEvent 流 processor 不关心走哪条
图 OC1.2 · 双运行时:两条路径都产出统一的 LLMEvent,下游无感知
🧭 为什么双运行时

AI SDK(Vercel)是成熟的多厂商抽象,但有时直接调用厂商原生 SDK 更快/更可控。OpenCode 用门控机制flags.experimentalNativeLlm)逐请求选择:支持的模型走 native,否则 fallback 到 AI SDK。关键设计:两条路径都归一化成同一套 LLMEvent,所以 processor.ts 完全不用关心走了哪条——这是适配器模式的典范。

架构设计原则

从全景图能看出 OpenCode 的几个核心设计原则:

🔌

Service 解耦

每个模块是 Effect Service(Agent/Session/Tool...),通过 Context 注入。松耦合,可替换

📡

事件驱动

状态变更通过事件总线(EventV2Bridge)发布。事件溯源风格,可追溯。

🛡️

权限贯穿

权限检查在工具执行全链路,每次危险操作都可拦截(OC4)。

💧

全链路流式

从 LLM token 到工具状态,整个执行过程都流式,UI 实时反馈。

与框架概念的全面对照

理论/框架概念OpenCode 实现
Agent 循环(F3)runLoop while(true)
AgentAction/Finish 二态(LC7)hasToolCalls 判断 + continue/stop
StateGraph 图(LG1)隐式(命令式循环,无显式图)
Checkpointer 记忆(LG6)Session DB 持久化
interrupt HITL(LG6)Permission.ask
ToolNode / @tool(LG8/LC6)Tool.define + registry
stream messages(LG7)LLMEvent 流(text-delta...)
compaction 裁剪session/compaction.ts
create_react_agent(LG8)build agent(默认配置)

这张表是 OC6 概念对照表的预览。学完本阶段你会对每一行有深刻理解。

后续章节阅读指南

🎯 本阶段 6 章怎么学
  • OC2 runLoop(核心)—— 精读循环本体,对应 F3 章的循环图
  • OC3 工具系统 —— Tool.define 模式,对应 LC6/LG8
  • OC4 权限系统 —— HITL 的生产形态,对应 LG6
  • OC5 上下文工程 —— compaction/子 agent,对应记忆管理
  • OC6 概念对照表(核心)—— 总结性大对照表

小结

下一章 · 核心 ★

下一章 OC2 · runLoop 主循环——本阶段核心!逐段拆解 prompt.ts:1081 的 while(true) 循环,把 F3 章的 Agent 循环理论在生产代码里"对号入座"。你会看到一个真实产品如何实现那个图。