6.5 自定义 Agent 配置

模型: claude-opus-4-6 (anthropic/claude-opus-4-6) 生成日期: 2026-02-17


OpenCode 的 Agent 系统不仅提供了内置 Agent,还支持用户通过多种方式创建和定制自己的 Agent。本节将详细分析三种自定义 Agent 的方式:通过 opencode.json 配置文件、通过 .opencode/agents/ 目录以及通过 Plugin 注入。

6.5.1 通过 opencode.jsonagent 字段定义

最直接的自定义方式是在项目的 opencode.json 配置文件中添加 agent 字段:

{
  "agent": {
    "code-reviewer": {
      "model": "anthropic/claude-sonnet-4-20250514",
      "description": "Code review specialist that checks for bugs and best practices",
      "prompt": "You are a meticulous code reviewer...",
      "mode": "subagent",
      "temperature": 0.2,
      "color": "#4CAF50",
      "steps": 20,
      "permission": {
        "*": "deny",
        "read": "allow",
        "grep": "allow",
        "glob": "allow"
      }
    }
  }
}

Config.Agent Schema

Agent 配置的 Zod Schema 定义在 config/config.ts 中:

这段 Schema 定义有几个巧妙的设计:

向后兼容处理

OpenCode 的权限系统经历了从 tools(简单的布尔开关)到 permission(细粒度的规则系统)的演进。为了不破坏现有用户的配置,Schema 在解析时自动将旧版 tools 格式转换为新版 permission 格式。

类似的兼容处理还包括 maxStepssteps 的字段重命名。

.catchall(z.any()) 与 options 提取

.catchall(z.any()) 允许配置中包含任何未定义的键,transform 将这些未知键自动收集到 options 字段中。这种设计使得用户可以通过配置文件传递 Provider 特定的参数,而无需 OpenCode 预先知道这些参数的存在:

其中 thinkingbudget_tokens 是 Anthropic 的 Provider 特定参数,它们会被自动收集到 options 中,最终通过 providerOptions 传递给 API。

Agent 合并逻辑

agent.tsstate() 函数中,用户配置与内置 Agent 的合并逻辑如下:

这段合并逻辑支持三种操作:

  1. 创建新 Agent:当 key 不在内置 Agent 中时,创建一个新 Agent(默认 mode: "all"native: false)。

  2. 修改内置 Agent:当 key 匹配内置 Agent 时,用配置值覆盖对应字段。只覆盖用户显式设置的字段(使用 ?? 运算符)。

  3. 禁用内置 Agentdisable: true 可以完全移除一个内置 Agent。

这种设计的灵活性体现在几个方面:

  • 用户可以只修改 build Agent 的模型,而不影响其他属性。

  • 用户可以给 explore Agent 添加额外的权限,而不覆盖其原有权限。

  • options 使用 mergeDeep 进行深度合并,而非简单覆盖。

6.5.2 通过 .opencode/agents/ 目录定义

对于更复杂的 Agent(特别是需要长篇 System Prompt 的 Agent),OpenCode 支持通过 Markdown 文件定义:

Markdown Agent 文件格式

文件由两部分组成:

  • YAML Front Matter--- 包裹的部分):Agent 的配置属性,对应 Config.Agent Schema 中的字段。

  • Markdown 正文:Agent 的 System Prompt 内容。

加载机制

加载过程有几个关键细节:

  1. 路径搜索:Glob 模式 {agent,agents}/**/*.md 同时搜索单数和复数形式的目录(agent/agents/),这种容错设计避免了用户因目录名拼写差异而遇到问题。

  2. 名称提取:Agent 的名称从文件路径中提取,而非从文件内容中获取。例如 .opencode/agents/security-auditor.md 的 Agent 名称为 security-auditor。支持嵌套目录——.opencode/agents/review/code.md 的名称为 review/code

  3. 容错解析ConfigMarkdown.parse() 使用 catch() 处理解析失败,通过事件总线发布错误通知而非直接抛出异常。这确保了一个 Agent 文件的语法错误不会阻止其他 Agent 的加载。

  4. Zod 校验:使用 Agent.safeParse() 进行安全校验。无效的配置会被报告但不会导致系统崩溃。

搜索路径

Agent 文件的搜索路径包括多个层级:

全局目录中定义的 Agent 在所有项目中可用,项目级目录中定义的 Agent 仅在当前项目中可用。如果同名 Agent 在两个层级都存在,根据配置合并策略(mergeConfigConcatArrays),项目级配置会覆盖全局配置。

6.5.3 通过 Plugin 注入 Agent 的机制

Plugin 是第三种注入 Agent 的方式。Plugin 通过 config 钩子可以动态地向配置中添加 Agent 定义:

Plugin 注入的 Agent 配置会与其他来源的配置一起合并。由于 Plugin 配置在合并链中的位置较高,Plugin 不仅可以添加新 Agent,还可以修改或增强已有的内置 Agent。

oh-my-opencode 的 Agent 注入

oh-my-opencode 作为 OpenCode 生态中最复杂的 Plugin,通过这种机制注入了 11 个 Agent(Sisyphus、Oracle、Explore、Librarian、Prometheus 等),每个 Agent 都有精心设计的 Prompt 和权限配置。这些 Agent 的详细分析将在第 15 章展开。

6.5.4 三种方式的对比

特性

opencode.json

.opencode/agents/*.md

Plugin

适用场景

简单配置、修改内置 Agent

复杂的自定义 Agent

跨项目复用、动态配置

Prompt 长度

适合短 Prompt

适合长 Prompt

适合程序化生成

分发方式

项目配置文件

项目目录

npm 包

动态性

静态

静态

可根据环境动态生成

版本控制

随项目配置管理

随项目文件管理

通过 npm 版本管理

选择建议

  • 修改内置 Agent 的行为(如更换模型、调整权限)→ opencode.json

  • 创建项目特有的专家 Agent(如安全审计、代码审查)→ .opencode/agents/

  • 开发可复用的 Agent 生态(如多 Agent 编排系统)→ Plugin

6.5.5 Agent 生命周期总结

综合前几节的分析,Agent 从定义到使用的完整生命周期如下:

这个生命周期清晰地展示了 Agent 如何从一个静态的配置定义,经过层层处理和合并,最终在运行时指导 LLM 的行为。


本章小结

本章完整地剖析了 OpenCode 的 Agent 系统:

  • 6.1 分析了 Agent 的数据模型(Agent.Info),理解了每个字段的含义和设计意图。

  • 6.2 深入了 7 个内置 Agent 的配置和权限设计,特别是 build(全能主 Agent)和 explore(只读搜索专家)的对比。

  • 6.3 分析了辅助型 Agent 的 Prompt 设计——标题生成、摘要生成、上下文压缩和代码库探索各有其精巧的 Prompt Engineering 技巧。

  • 6.4 揭示了 System Prompt 的分层架构——根据 LLM Provider 选择模板、Plugin 变换、缓存优化和参数注入的完整流程。

  • 6.5 展示了三种自定义 Agent 的方式及其适用场景。

Agent 系统的设计哲学可以概括为:通过声明式的配置定义 Agent 的"性格"和"能力",通过权限系统和 Prompt 双重机制确保安全边界,通过分层拼接和 Plugin 钩子实现最大的灵活性和可扩展性。

下一章,我们将进入 Provider 层——理解 OpenCode 如何统一对接 20+ 个 LLM Provider,实现"一次编写,多模型运行"的能力。

Last updated