运行时 · 状态机 · 流程

运行时深度解析

从用户输入到代码修改落地,opencode 经历了 Plan → Build 双 Agent 编排、LLM API 调用、工具并行执行、System Prompt 动态构建等关键流程。本文用状态机图与流程图完整还原每个环节。

⚙️ 双 Agent 执行流程

一次完整的用户请求经历以下阶段。Plan Agent 先行分析,产出结构化方案后,Build Agent 按方案逐步执行,每步均可调用工具并将结果反馈给 LLM。

1
用户输入 (USER_INPUT)
TUI 接收用户消息,或通过 -p 标志传入 prompt。消息追加至当前 session 的消息列表,触发 Agent 编排流程。
2
Plan Agent — 分析阶段
Plan Agent 以只读工具集(read_file、grep、search_files、list_directory)扫描代码库,理解任务意图、识别影响范围、生成结构化实施步骤。输出包含:要修改的文件列表、每步操作说明、潜在风险点。
3
Build Agent — 执行阶段
Build Agent 接收 Plan Agent 输出,获得全工具访问权限(含写入、Shell 执行),按计划逐步执行。每步执行后验证结果(如运行类型检查、lint),根据反馈动态调整后续步骤。
4
LLM API 调用 (LLM_CALL)
当前 session 消息历史(含 system prompt、用户消息、工具结果)被序列化发送至选定的 LLM Provider。支持流式返回(SSE),TUI 实时渲染增量 token。
5
工具调用并行执行 (TOOL_CALLS)
LLM 响应中包含 tool_use 块时,opencode 提取所有工具调用并并行执行(Promise.all),最大化吞吐量。各工具结果以 tool_result 消息追加至上下文,触发下一轮 LLM 调用。
read_file
grep
list_directory
search_files
6
循环直至 DONE
LLM 调用 → 工具执行 → 结果追加 → 再次 LLM 调用,此循环持续直至 LLM 不再产生 tool_use,发出完成信号(stop_reason: end_turn)。
7
Session 持久化 (PERSIST)
完整对话历史(含工具调用、结果、最终响应)序列化写入磁盘。若开启 --share,同步推送至 opencode.ai console。
🔄 Agent 循环状态机

以下状态机图展示 Build Agent 单轮执行循环的完整状态转移。分支条件决定是否继续工具调用循环或终止。

USER_INPUT
用户消息 / -p prompt 注入
PLAN_AGENT_RUN
只读工具 · 分析意图 · 输出方案
BUILD_AGENT_RUN
接收 Plan 输出 · 全工具访问
LLM_CALL
Provider API · 流式返回 · Token 渲染
stop_reason == "tool_use" ?
YES
NO
TOOL_EXECUTE
并行执行所有工具
TOOL_RESULTS → LLM
结果追加 · 重新调用
↺ 回到 LLM_CALL
RESPONSE
最终回复渲染至 TUI
PERSIST_SESSION
写入磁盘 · 可选共享
📝 System Prompt 构建管道

每个 session 启动时,opencode 按固定顺序组装 system prompt。各层内容追加叠加,最终通过可选的 JS transform 钩子做全局变换。

① 基础指令 (Base Instructions)
内置 opencode 行为规范 · 工具使用格式 · 安全约束
+
② AGENTS.md (项目级,如存在)
项目根目录的 AGENTS.md 全文追加 · 技术约定 · 禁止操作
+
③ 匹配技能 (Auto-matched Skills)
语义匹配得分最高的 N 个 SKILL.md 内容 · 项目 > 全局 > 插件
↓ (可选)
④ experimental.chat.system.transform
JS eval · 入参: system (string), extraContext · 返回值替换最终 prompt
⑤ 最终 System Prompt → LLM
发送至 Provider API · 每轮对话保持不变直至 /compact 或 session 重启
Transform 钩子示例
// ~/.config/opencode/opencode.json { "experimental": { "chat": { "system": { "transform": "return system + '\\n\\n## 额外约束\\n今天是 ' + new Date().toLocaleDateString('zh-CN') + ',请用中文回复。'" } } } } // 更复杂的用法(多行字符串) { "transform": "const extra = process.env.TEAM_CONTEXT || ''; return system + extra" }
⚠️
transform 中的 JS 表达式在 opencode 进程中直接 eval 执行,拥有访问 process.env 的能力,请勿放入不可信内容。该特性标记为 experimental,API 可能变更。
🧩 Skill 注入流程

opencode 在每次 session 启动时执行一次技能扫描与注入。整个流程分为四个阶段,确保最相关的技能内容被自动纳入 system prompt。

📂
扫描技能库
按优先级遍历
项目 → 全局 → 插件
🔍
解析 Frontmatter
提取 name
& description
🧠
语义匹配
与项目上下文
计算相关性分
💉
注入 Prompt
TopK 技能内容
追加至 system
语义匹配依据的项目上下文
上下文信号示例影响技能
文件扩展名分布 .tsx, .css 文件占多数 前端/React 相关技能分数提升
package.json 依赖 react, tailwindcss UI 框架技能相关性更高
配置文件存在 prisma/schema.prisma 数据库/ORM 技能优先注入
AGENTS.md 关键词 "FastAPI", "TypeScript" 对应技术栈技能分数加权
当前任务 prompt "Fix the login form UI" 前端/认证相关技能优先
🗜️ Context 压缩机制 (/compact)

当对话历史过长,接近 LLM context 窗口上限时,/compact 命令将历史消息压缩为摘要,释放空间以继续长任务。

压缩前
~24 条消息 ~80K tokens

/compact
压缩后
1 摘要 + 最新消息 ~8K tokens
压缩行为细节
  • 摘要由 LLM 本身生成,保留关键决策、已做修改、待完成任务等核心信息
  • 摘要以单条 assistant 消息替换原始消息列表,保持 API 消息格式合法
  • 压缩前的完整历史仍持久化在磁盘,可通过 session 恢复查看
  • 也可配置为自动压缩(auto-compact),在 token 数达到阈值时自动触发,无需手动 /compact
🔗 Session 共享架构

opencode --share 将当前 session 实时发布至 opencode.ai,团队成员无需安装 opencode 即可通过浏览器查看完整操作过程。

🔒
共享 session 默认公开可访问(知链接即可看),请避免在包含敏感信息(API Key、密码、内部代码)的 session 中启用共享。autoshare: false 为默认安全设置。
🤖 非交互模式与 CI/CD 集成

使用 -p 标志时,opencode 进入非交互模式:执行完成后以退出码 0(成功)或非 0(失败)退出,适合在 CI 流水线中调用。

# GitHub Actions 示例 - name: AI Code Review env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: | opencode -p "Review the diff in this PR for security issues and code quality. Output a structured report with severity levels." # 退出码处理 opencode -p "Run tests and fix any failures" || echo "opencode task failed" # 组合使用:指定模型 + 非交互 + 禁用自动压缩 opencode --model anthropic/claude-opus-4 \ --no-auto-compact \ -p "Refactor src/api/ to use the repository pattern"
🔧 工具执行细节
工具Plan AgentBuild Agent执行方式
read_fileBun.file().text()
write_fileBun.write()
execute_commandBun.spawn() / $``
grepripgrep 子进程
search_filesglob 文件系统遍历
web_fetchfetch() API
git_*git CLI 子进程
lsp_*LSP stdio 协议
📡 流式响应处理

opencode 全程使用流式 API(SSE / streaming),实现 token 级别的实时渲染。TUI 使用 React 状态更新驱动增量显示,用户无需等待完整响应。

// 简化的流式处理伪代码 async function streamLLM(messages, onToken) { const stream = await provider.chat.stream({ messages }) for await (const chunk of stream) { if (chunk.type === 'text_delta') { onToken(chunk.text) // TUI React 状态更新 } if (chunk.type === 'tool_use') { toolCalls.push(chunk) } if (chunk.stop_reason === 'end_turn') break } // 并行执行所有收集到的工具调用 if (toolCalls.length > 0) { const results = await Promise.all(toolCalls.map(executeT)) return streamLLM([...messages, ...results], onToken) // 递归 } }
opencode · Anomaly / SST · github.com/sst/opencode 深度文档 · 2026-05-22