模型: claude-opus-4-6 (anthropic/claude-opus-4-6)
生成日期: 2026-02-17
在上一章我们深入剖析了 Tool 系统——Agent 与外部世界交互的"手"。而本章,我们将聚焦于 Agent 本身——它是 OpenCode 赋予 LLM "性格"和"能力边界"的核心抽象。
如果说 Tool 定义了"Agent 能做什么",那么 Agent 就定义了"Agent 是谁"——它使用什么模型、拥有什么权限、遵循什么行为准则、最多执行多少步。理解 Agent 数据模型,是理解 OpenCode 整个多 Agent 编排体系的基础。
6.1.1 Agent.Info 的 Zod Schema 定义
Agent 的数据模型定义在 packages/opencode/src/agent/agent.ts 中,使用 Zod Schema 声明:
// agent/agent.ts
export namespace Agent {
export const Info = z
.object({
name: z.string(),
description: z.string().optional(),
mode: z.enum(["subagent", "primary", "all"]),
native: z.boolean().optional(),
hidden: z.boolean().optional(),
topP: z.number().optional(),
temperature: z.number().optional(),
color: z.string().optional(),
permission: PermissionNext.Ruleset,
model: z
.object({
modelID: z.string(),
providerID: z.string(),
})
.optional(),
variant: z.string().optional(),
prompt: z.string().optional(),
options: z.record(z.string(), z.any()),
steps: z.number().int().positive().optional(),
})
.meta({ ref: "Agent" })
export type Info = z.infer<typeof Info>
}
这段代码展示了 OpenCode 一贯的"Zod-first"设计风格——先定义数据 Schema,再从中推导出 TypeScript 类型。让我们逐一解析每个字段的含义和设计意图。
Agent 的唯一标识符,如 "build"、"explore"
Agent 的用途描述,用于 UI 展示和 LLM 选择参考
是否为 OpenCode 内置 Agent(区别于用户自定义 Agent)
是否在 UI 中隐藏(辅助型 Agent 如 title、summary 通常为 true)
name 是 Agent 在整个系统中的索引键。当用户通过 @agent-name 语法或 Task 工具委托子任务时,都是通过 name 来引用特定的 Agent。
mode 字段决定了 Agent 可以在什么场景下被使用:
primary:主 Agent,只能作为会话的顶层 Agent 使用。用户直接与其交互。例如 build Agent 和 plan Agent。
subagent:子 Agent,只能被其他 Agent 通过 Task 工具调用。不能直接作为会话的主 Agent。例如 explore Agent 和 general Agent。
all:两种模式皆可。适用于用户自定义的 Agent——它们既可以作为主 Agent 使用,也可以被其他 Agent 委托。
这种分类体现了一个重要的架构约束:不是所有 Agent 都应该被用户直接操控。辅助型 Agent(如 compaction、title、summary)被标记为 hidden 且其权限被严格限制,它们只为系统内部服务,不暴露给用户。
Agent 可以指定它使用的模型。如果未指定(optional),则使用系统的默认模型。model 字段由 providerID(如 "anthropic"、"openai")和 modelID(如 "claude-sonnet-4-20250514")两部分组成。
这种设计允许不同 Agent 使用不同的模型。例如在 oh-my-opencode 这样的插件中,主 Agent(Sisyphus)可能使用 Claude Opus 这样的高端模型进行复杂推理,而探索型 Agent(Explore)可能使用较便宜的模型来降低成本。
衍生解释:Temperature 和 Top-P
这两个参数控制 LLM 生成文本时的"随机性":
Temperature(温度):值越高(如 1.0),生成的文本越多样、越有创造性;值越低(如 0.1),生成的文本越确定、越保守。在 Agent 场景中,代码生成通常使用较低的 temperature 以确保输出的确定性。
Top-P(核采样):从概率最高的 token 中选取,使得累积概率不超过 P 值。Top-P = 0.9 意味着只从概率总和达到 90% 的候选 token 中采样。
这两个参数通常二选一使用。OpenCode 的 title Agent 将 temperature 设为 0.5,在确定性和多样性之间取得平衡——既不总生成一模一样的标题,也不生成过于离谱的标题。
variant 字段是模型变体的概念。某些模型提供不同的变体(如思考深度、响应风格等),variant 允许 Agent 指定其偏好的变体。
这是 Agent 最关键的字段之一。每个 Agent 都携带一组权限规则(Ruleset),定义它可以使用哪些工具、可以访问哪些文件路径。权限系统的详细设计将在第 9 章展开,这里只需理解:Agent 的权限规则直接决定了它的行为边界。
Agent 可以拥有自己专属的 System Prompt。当设置了 prompt 字段时,该 Prompt 将替代默认的 Provider Prompt(如 anthropic.txt),而非追加。这一设计让 Agent 可以拥有完全不同的"人格"。
例如,explore Agent 的 Prompt 是 prompt/explore.txt,将其定义为"文件搜索专家",与默认的 build Agent("全能编码助手")有着截然不同的行为特征。
steps 限制了 Agent 在一次交互中可以执行的最大迭代步数。在 Agentic Loop 中,每一次"工具调用 → 执行 → 返回结果 → 继续对话"算一步。当达到步数限制时,系统会注入一段强制性提示(max-steps.txt),要求 Agent 停止使用工具并以纯文本总结当前进展。
这是一种防护机制——防止 Agent 陷入无限循环或消耗过多资源。与 Doom Loop 检测(重复失败检测)不同,steps 是绝对上限,无论 Agent 是否在"有意义地"工作。
options 是一个开放式的键值对,用于传递 Provider 特定的选项。例如,某些 Provider 可能支持特殊的推理模式或安全设置,这些设置无法通过标准字段表达,就通过 options 传递。在 LLM 调用时,这些 options 会被层层合并:
color 字段用于 TUI 中的视觉区分。当用户切换不同 Agent 时,界面会使用对应的颜色标识当前活跃的 Agent。支持 HEX 颜色码(如 #FF5733)或主题颜色名(如 "primary"、"accent")。
6.1.2 Instance.state() 模式下的 Agent 初始化
Agent 的实例化使用了我们在第 3 章介绍过的 Instance.state() 模式:
这段代码的关键特征是:
延迟初始化:Instance.state() 接受一个异步工厂函数,只在第一次调用 state() 时执行。
项目隔离:每个项目实例拥有独立的 Agent 注册表,不同项目可以有不同的 Agent 配置。
缓存语义:初始化结果被缓存,后续调用直接返回缓存值,避免重复计算。
6.1.3 Agent 的公共 API
Agent 模块对外暴露三个核心函数:
defaultAgent() 的实现揭示了几个重要的约束:
默认 Agent 不能是 subagent 模式的 Agent。
默认 Agent 不能是 hidden 的 Agent。
如果用户没有指定 default_agent,系统会选择第一个非 subagent、非 hidden 的 Agent(通常是 build)。
这些约束确保了用户在启动 OpenCode 时,总有一个合适的主 Agent 可用。
6.1.4 Agent 与 Session 的关系
理解 Agent 数据模型,还需要理解它与 Session(会话)的关系。在 OpenCode 中:
一个 Session 只能绑定一个 Agent——在创建 Session 时指定。
子会话继承父会话的 Agent 配置——当 Task 工具创建子会话时,可以指定不同的 Agent。
Agent 决定了 Session 的行为特征——包括使用什么 System Prompt、拥有什么权限、使用什么模型。
这种"Agent-Session 绑定"的设计,使得多 Agent 协作成为可能:主 Session 使用 build Agent,而通过 Task 工具派生的子 Session 可以使用 explore、general 等子 Agent,每个子 Agent 都有自己独立的行为边界和能力范围。
本节建立了对 Agent 数据模型的全面理解。下一节,我们将聚焦于 OpenCode 最重要的内置 Agent——build,深入分析它的权限配置和行为设计。