主题
第三章 Opencode Agent 系统
← 返回目录 | 上一章:Opencode 核心架构 | 下一章:工具链与会话模型 →
3.1 Agent 定义模型
在 Opencode 中,Agent 是一个相当轻量的概念——本质上是一组配置的集合,而不是独立运行的进程:
typescript
// agent/agent.ts 中的 Agent 定义结构
interface AgentConfig {
agentID: string; // 唯一标识符
systemPrompt: string; // 系统提示词
tools: string[]; // 可用工具白名单
model: string; // 绑定的 LLM 模型
mode: "primary" | "subagent" | "all"; // 运行模式
visible: boolean; // 是否在 UI 中可见/可选
maxTokens?: number; // 最大输出 token 数
}运行模式(mode) 是 Agent 系统的关键概念:
| 模式 | 含义 | 模型选择 |
|---|---|---|
primary | 主 Agent,用户直接交互 | 使用 UI 中用户选择的模型 |
subagent | 子 Agent,由其他 Agent 调用 | 使用自身配置的模型(不受 UI 影响) |
all | 两种模式兼备 | 作为主 Agent 时用 UI 模型,被调用时用自身模型 |
3.2 七个内置 Agent
Opencode 原生定义了 7 个 Agent,分为三层:
用户可见层(可在 TUI 中切换):
| Agent | 用途 | 工具权限 | 特殊约束 |
|---|---|---|---|
| build | 默认主 Agent,全能型编程助手 | 全部工具 | 无 |
| plan | 只读规划 Agent,用于分析不修改代码 | 只读工具(Read/Glob/Grep/Bash/WebFetch/Task) | 不能编辑文件 |
子 Agent 层(只能被 Task 工具调用):
| Agent | 用途 | 工具权限 |
|---|---|---|
| general | 通用子任务执行者 | 全部工具 |
| explore | 代码库搜索专家 | 只读工具 + 搜索工具 |
隐藏层(系统内部使用,用户不可见):
| Agent | 用途 | 说明 |
|---|---|---|
| compaction | 上下文压缩 | 将过长对话摘要为简短总结 |
| title | 会话标题生成 | 自动为新会话生成标题 |
| summary | 内容摘要 | 用于文件/内容的摘要生成 |
3.3 Task 工具:Opencode 原生的子 Agent 调度
Opencode 的 Task 工具是其唯一的 Agent 间调度机制,实现非常直接:
父 Agent 调用 Task 工具
→ 创建新的子 Session
→ 在子 Session 中启动指定 Agent
→ 同步等待子 Agent 完成
→ 将结果返回给父 Agent关键限制:
- 纯同步:父 Agent 在子任务完成前完全阻塞,不能并行执行多个子任务
- 无后台能力:没有异步执行、没有任务队列、没有并发控制
- 单层调度:Task 可以嵌套(子 Agent 可以再调用 Task),但没有全局编排器
这些限制正是 OmO 存在的主要动因之一——它需要把这个同步单线程模型升级为异步多 Agent 并行编排系统。
3.4 Agent 与 LLM 的交互循环
一个 Agent 的完整执行循环(在 session/processor.ts 中实现):
用户消息 → 组装 System Prompt → 调用 LLM API(流式)
→ 解析响应流(文本/工具调用/推理)
→ 如果有工具调用:
→ 执行工具(可能触发权限检查)
→ 将工具结果追加到消息序列
→ 再次调用 LLM(让 Agent 看到工具结果)
→ 循环直到 Agent 不再调用工具
→ 返回最终文本响应这是标准的 ReAct (Reasoning + Acting) 循环。Opencode 在此基础上增加了:
- 流式输出:LLM 响应逐 token 推送到 TUI
- 权限管理:敏感工具(Bash、Edit、Write)需要用户确认
- 消息持久化:每一步都写入 SQLite,支持恢复
- Token 追踪:实时统计输入/输出 token 数和费用
3.5 Agent 模型选择策略
Opencode 的模型选择机制是其多 Provider 开放性的关键体现:
| Agent 模式 | 模型来源 | 用户控制度 |
|---|---|---|
primary | TUI 中用户选择的模型 | 完全可控 |
subagent | Agent 配置中硬编码的模型 | 不可控(由插件/配置决定) |
all | 取决于调用方式 | 视场景而定 |
这种设计意味着:用户切换模型只影响主 Agent(build/plan),子 Agent(explore/general 等)始终使用预配置的模型。这是一个务实的选择——子 Agent 的 Prompt 通常针对特定模型调优,随意切换可能导致质量下降。
与 OmO 和 Claude Code 的对比:
- OmO 将此机制进一步发展为经济学分配——不同角色的 Agent 使用不同价位的模型(Prometheus 用高端模型做规划,Explore 用廉价模型做搜索)
- Claude Code 走了完全不同的路径——只支持 Claude 系列模型,但通过 prompt caching、extended thinking 等 API 级优化获得单模型的极致性能
3.6 设计局限与 OmO 的改进动机
Opencode 的 Agent 系统是一个精简但够用的设计。它的主要局限在于:
- Task 工具纯同步:父 Agent 调用子 Agent 时完全阻塞,无法并行探索多个方向
- 无全局编排器:没有"元 Agent"来决定任务分配策略,一切依赖主 Agent 自行判断
- 角色不够细分:7 个 Agent 中只有 build 和 general 承担实际编码,缺少专门的审查、规划、调研角色
这些局限正是 OmO 存在的核心动因。OmO 通过插件系统将 7 个 Agent 扩展为 12 个,增加了 Prometheus(规划)、Oracle(咨询)、Momus(审查)等专职角色,并将同步 Task 升级为异步后台任务系统。详见第六章。