从 Effect-TS 函数式架构到 Session 会话引擎,从 Agent 循环到工具注册系统,从插件化 Provider 到 SolidJS TUI——逐层拆解 opencode 这个最快增长的 AI 编码 Agent。
OpenCode 是一个全 TypeScript 的 AI 编码 Agent,采用 Effect-TS 函数式编程体系构建。与 Python 生态的同类项目不同,Effect-TS 提供了类型安全的 Effect 副作用管理、Schema 编解码、Layer 依赖注入和 Scope 资源生命周期管理,使得整个 Agent 的每个环节——从 LLM 调用到工具执行——都可以在编译期类型检查,并在运行时被精确追踪。
截至 v1.17,OpenCode 在 GitHub 上获得 55K+ Star,是目前增长最快的 CLI 编码 Agent 之一。其架构设计充分体现了函数式编程在大规模 AI Agent 系统中的工程实践价值:可测试性、可推理性、和可组合性。
OpenCode 五层架构:CLI/TUI → Session 引擎 → Agent Loop → Tool System → Provider Layer。核心技术栈:Effect-TS、Bun、SolidJS、AI SDK、Drizzle ORM。Monorepo 包:core / opencode / tui / cli / plugin / llm。
其中 core 包是整个系统的中枢,提供了 Agent 定义与管理、Session 持久化和执行引擎、Tool 注册与编排、Plugin 钩子系统、Catalog 模型目录等核心抽象。所有模块通过 Effect-TS 的 Layer 依赖注入机制组装,启动时通过 PluginBoot 引导加载 30 多个 内置 Provider 插件和配置插件。
State 模块(src/state.ts)提供了一种"可回放的 Transform 状态管理"模式:每个插件或配置项注册一个 scoped transform,在 Scope 生命周期内生效,关闭 Scope 时自动移除并重建状态。这种设计使得插件卸载、配置热更新、Agent 切换等场景不需要手动清理状态,Effect-TS 的 Scope 系统保证了资源泄漏零容忍。
Session 生命周期:用户输入 → Session 创建 → Agent Loop → Tool 执行 → 输出返回。协调器模式:RunCoordinator 管理单 Session 单线程,状态机 idle → draining → rerun。Agent 循环最大 25 步。
RunCoordinator(src/session/run-coordinator.ts)是 Session 执行的核心调度器。它为每个 Session ID 维护一个独立的执行通道,支持两种触发模式:run(显式排水,确保至少一次 Provider 调用)和 wake(被动唤醒,在已有排水链中合并重复请求)。当多个请求同时到达时,coalesce() 函数会合并需求:显式 run 始终优先,多个 wake 则保留最新的序列号。
底层执行由 SessionRunner 驱动,每次调用 runner.run() 时,它通过 SessionRunnerModel 解析出 @opencode-ai/llm 的 Model 对象,然后调用 llm.stream(request) 进行流式推理。推理结果中的 tool_call 会被 ToolRegistry 拦截:先持久化记录到 ToolOutputStore,再通过 settle() 执行具体工具,最后将所有工具结果汇总后回到 LLM 循环。
事件溯源同样贯穿 Session 的设计:SessionEvent 和 SessionInput 系统以事件流的形式记录每一次用户输入、模型输出、工具调用和结果。事件驱动的持久化设计使得 Session 可以随时重放、恢复、或迁移到不同的运行时。
Tool.make() 工厂 + 13 个内置工具:bash / read / write / edit / grep / glob / websearch / webfetch / lsp / shell / todo / task / plan。权限两层策略。
工具注册的核心在 ToolRegistry(src/tool/registry.ts),它维护着一个两层工具注册表:第一层是 ApplicationTools(编译期注册的内置工具),第二层是运行时通过 Tools.Service.register() 动态注册的工具。动态工具通过 WeakMap 跟踪所有已注册的 Tool 对象,每个工具名可以拥有多个版本的注册条目,形成栈结构,最新注册的版本优先。
每个工具定义(通过 Tool.make() 创建)包含三个核心要素:输入 Schema(Effect-TS Schema 编译期为 JSON Schema)、输出 Schema、以及 execute 执行函数。工具执行时,settle() 函数会先通过凭据校验(PermissionV2 两层策略),然后将调用分发到具体的 execute 函数,最终结果被 ToolOutputStore 持久化到 SQLite 数据库。
工具权限系统(PermissionV2.Ruleset)支持通配符匹配的 allow/deny 规则:每条规则包含 action(如 tool:bash)、resource(如 *)和 effect(allow/deny)。规则的禁用通过 whollyDisabled() 函数判断——只有最后一条匹配规则为 deny 且 resource 为通配符时,工具才被整体禁用。
加载器 4 阶段:resolve → check → load → apply。支持 10+ Provider:OpenAI、Anthropic、Google、GitHub Copilot、Groq、Mistral 等。MCP 集成:Stdio/HTTP/SSE。
实际上 OpenCode 内置了 33 个 Provider 插件(src/plugin/provider.ts),覆盖了几乎所有主流 LLM 服务:OpenAI、Anthropic、Google/Gemini、Google Vertex AI(含 Anthropic 通道)、GitHub Copilot、Azure、Amazon Bedrock、Mistral、Groq、Cohere、Perplexity、Together AI、DeepInfra、NVIDIA、Cerebras、xAI、Alibaba、Snowflake Cortex、SAP AI Core、Cloudflare Workers AI 等。每个 Provider 通过 PluginV2.define() 注册,在启动时通过 PluginBoot 批量注入到系统中。
插件系统基于 Hook 机制(src/plugin.ts):定义了三个核心 Hook 点——catalog.transform(修改模型目录)、aisdk.language(注入自定义 AI SDK Language Model)、aisdk.sdk(注入自定义 AI SDK)。Provider 插件通过监听这些 Hook 点来扩展系统能力,而不需要修改核心代码。例如 OpenAI 插件通过 aisdk.language Hook 注入 OpenAI 兼容的 LanguageModelV3 实现。
MCP(Model Context Protocol)集成通过 MCP 配置层(src/config/mcp.ts)支持三种传输方式:Stdio(本地进程通信)、HTTP/SSE(远程服务器推送事件)。这使得 OpenCode 能够无缝接入 VS Code 的 MCP 生态,复用社区已有的 MCP 工具服务器。
OpenCode 的 Agent 系统(src/agent.ts)通过 Effect-TS Schema 定义了完整的 Agent 信息模型:包含 ID(品牌化字符串)、model 引用、请求配置(headers/body)、system prompt、mode(subagent/primary/all)、step 上限(默认 25)、权限规则集等字段。Agent 信息通过 State.Interface 的 scoped transform 机制管理,支持热更新和插件扩展。
Agent 支持三种运行模式:primary(主 Agent,拥有完整工具集)、subagent(子 Agent,受限于父级权限)、all(同时担任两者)。每个 Agent 可以配置独立的颜色标识、是否隐藏、以及专属的权限规则子集。Agent 选择通过 resolve() 和 select() 函数完成,支持按 ID 或名称字符串查找。
Skill 系统(src/skill.ts)是 Agent 知识的扩充渠道,支持三种来源:directory(本地目录中的 Markdown 文件)、url(远程技能包)、embedded(内嵌在配置中的技能)。每个 Skill 包含 name、description、slash 标志和纯文本的 content,Agent 在推理时会根据权限规则加载对应的 Skill 内容作为 system context 的一部分。