feat: config with agents rework
This commit is contained in:
529
.sisyphus/evidence/task-4-opencode-agent-format.md
Normal file
529
.sisyphus/evidence/task-4-opencode-agent-format.md
Normal file
@@ -0,0 +1,529 @@
|
||||
# Task 4: OpenCode File-Based Agent Format Research
|
||||
|
||||
**Date**: 2026-04-10
|
||||
**Status**: ✅ Complete
|
||||
**Research Method**: WebFetch + Documentation Analysis
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
OpenCode supports **two agent configuration methods**:
|
||||
1. **JSON** - Embedded in `opencode.json` (config.json)
|
||||
2. **Markdown Files** - File-based in `.opencode/agents/` directory (per-project) or `~/.config/opencode/agents/` (global)
|
||||
|
||||
This research focuses on the **file-based markdown format**, which is the target for the harness-agnostic migration.
|
||||
|
||||
---
|
||||
|
||||
## File Location & Discovery
|
||||
|
||||
### Directory Structure
|
||||
|
||||
**Per-project agents** (takes precedence):
|
||||
```
|
||||
.opencode/agents/
|
||||
├── agent-name.md
|
||||
├── another-agent.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
**Global agents** (fallback):
|
||||
```
|
||||
~/.config/opencode/agents/
|
||||
├── agent-name.md
|
||||
├── another-agent.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
### Discovery Mechanism
|
||||
|
||||
- OpenCode **scans both directories** for `*.md` files
|
||||
- The **filename (without .md extension)** becomes the **agent name**
|
||||
- Per-project agents **override** global agents with the same name
|
||||
- All agents are loaded at startup and available via `Tab` switching or `@mention`
|
||||
|
||||
### Key Finding
|
||||
|
||||
**The agent name is derived from the filename**, not from a `name` field in the frontmatter. Example:
|
||||
- File: `review.md` → Agent name: `review`
|
||||
- File: `code-reviewer.md` → Agent name: `code-reviewer`
|
||||
|
||||
---
|
||||
|
||||
## YAML Frontmatter Specification
|
||||
|
||||
All file-based agent markdown files must include YAML frontmatter with the following fields:
|
||||
|
||||
### Required Fields
|
||||
|
||||
| Field | Type | Description | Example |
|
||||
|-------|------|-------------|---------|
|
||||
| `description` | string | Brief description of agent purpose and when to use it. **REQUIRED**. | `"Reviews code for quality and best practices"` |
|
||||
|
||||
### Optional Fields
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `mode` | string | `all` | Agent mode: `primary`, `subagent`, or `all` |
|
||||
| `model` | string | Model globally configured in config | Override LLM model for this agent |
|
||||
| `temperature` | float | Model-specific (usually 0 or 0.55 for Qwen) | LLM response randomness (0.0–1.0) |
|
||||
| `top_p` | float | — | Alternative to temperature for diversity control |
|
||||
| `steps` | integer | No limit | Max agentic iterations before forced text-only response |
|
||||
| `disable` | boolean | `false` | Set to `true` to disable the agent |
|
||||
| `hidden` | boolean | `false` | Hide from `@` autocomplete (subagents only) |
|
||||
| `color` | string | — | Hex color (e.g., `#FF5733`) or theme color (primary, secondary, accent, success, warning, error, info) |
|
||||
| `permission` | object | — | Permission rules for edit, bash, webfetch, question, websearch, external_directory |
|
||||
| `task` | object | — | Control which subagents this agent can invoke via Task tool |
|
||||
|
||||
### Provider-Specific Fields
|
||||
|
||||
Any additional fields are **passed through directly to the LLM provider**. Example for OpenAI reasoning models:
|
||||
```yaml
|
||||
---
|
||||
description: Agent using high reasoning effort
|
||||
model: openai/gpt-5
|
||||
reasoningEffort: high
|
||||
textVerbosity: low
|
||||
---
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Permission Format (YAML)
|
||||
|
||||
Permissions control what actions an agent can perform. The format supports two styles:
|
||||
|
||||
### Simple Format (Single Action)
|
||||
|
||||
```yaml
|
||||
permission:
|
||||
edit: deny
|
||||
bash: ask
|
||||
webfetch: allow
|
||||
```
|
||||
|
||||
### Granular Format (Rules Array)
|
||||
|
||||
For more control over specific patterns:
|
||||
|
||||
```yaml
|
||||
permission:
|
||||
edit:
|
||||
"*": allow
|
||||
"/run/agenix/**": deny
|
||||
bash:
|
||||
"*": ask
|
||||
"git status*": allow
|
||||
"git log*": allow
|
||||
"git push": ask
|
||||
"grep *": allow
|
||||
webfetch: deny
|
||||
question: allow
|
||||
websearch: allow
|
||||
external_directory:
|
||||
"*": ask
|
||||
"~/p/**": allow
|
||||
"~/.config/opencode/**": allow
|
||||
"/tmp/**": allow
|
||||
```
|
||||
|
||||
### Permission Actions
|
||||
|
||||
| Value | Meaning |
|
||||
|-------|---------|
|
||||
| `allow` | Tool allowed without approval |
|
||||
| `ask` | Prompt user for approval before running |
|
||||
| `deny` | Tool disabled |
|
||||
|
||||
### Supported Permission Keys
|
||||
|
||||
| Key | Values | Notes |
|
||||
|-----|--------|-------|
|
||||
| `edit` | `allow\|ask\|deny` or nested rules | File write/patch operations |
|
||||
| `bash` | `allow\|ask\|deny` or nested rules | Bash command execution; supports glob patterns |
|
||||
| `webfetch` | `allow\|ask\|deny` | HTTP requests |
|
||||
| `question` | `allow\|ask\|deny` | User questions/clarification |
|
||||
| `websearch` | `allow\|ask\|deny` | Web search operations |
|
||||
| `external_directory` | `allow\|ask\|deny` or nested rules | Access to external directories |
|
||||
| `task` | nested rules | Subagent invocation control (glob patterns) |
|
||||
|
||||
### Glob Pattern Support
|
||||
|
||||
Patterns support wildcards and recursion:
|
||||
- `*` — single-level wildcard
|
||||
- `**` — recursive wildcard
|
||||
- `git push*` — suffix matching
|
||||
- `~/p/**` — home directory paths
|
||||
- `/run/agenix/**` — absolute paths
|
||||
|
||||
### Rule Precedence
|
||||
|
||||
When multiple rules match, the **last matching rule wins**:
|
||||
|
||||
```yaml
|
||||
bash:
|
||||
"*": ask
|
||||
"git status*": allow
|
||||
"git push*": deny
|
||||
```
|
||||
|
||||
In this example:
|
||||
- `git status` matches both `*` and `git status*` → result: **allow** (last rule wins)
|
||||
- `git push origin main` matches both `*` and `git push*` → result: **deny**
|
||||
- `ls -la` matches only `*` → result: **ask**
|
||||
|
||||
---
|
||||
|
||||
## Mode Field Values
|
||||
|
||||
| Mode | Type | Description |
|
||||
|------|------|-------------|
|
||||
| `primary` | Primary agent | Agent available via `Tab` key switching; handles main conversation |
|
||||
| `subagent` | Specialized agent | Invoked via `@mention` or automatically by other agents for specific tasks |
|
||||
| `all` | Flexible | Can be used as both primary and subagent (default if omitted) |
|
||||
|
||||
---
|
||||
|
||||
## System Prompt Delivery
|
||||
|
||||
The markdown file body (after the YAML frontmatter) contains the **system prompt**:
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Code review without edits
|
||||
mode: subagent
|
||||
permission:
|
||||
edit: deny
|
||||
---
|
||||
You are a code reviewer. Focus on:
|
||||
- Code quality and best practices
|
||||
- Potential bugs and edge cases
|
||||
- Performance implications
|
||||
- Security considerations
|
||||
|
||||
Provide constructive feedback without making direct changes.
|
||||
```
|
||||
|
||||
The **markdown content is passed directly as the system prompt** to the LLM. It supports:
|
||||
- Inline markdown formatting
|
||||
- Lists and sections
|
||||
- Structured instructions
|
||||
- Code examples (fenced with backticks)
|
||||
|
||||
---
|
||||
|
||||
## Default Behavior for Omitted Fields
|
||||
|
||||
| Field | Default | Notes |
|
||||
|-------|---------|-------|
|
||||
| `description` | **ERROR** | Required; absence causes parse failure |
|
||||
| `mode` | `all` | Agent can be used as primary or subagent |
|
||||
| `model` | Global config model | Primary agents use global model; subagents use parent's model |
|
||||
| `temperature` | Model-specific | Usually 0 for most models; 0.55 for Qwen models |
|
||||
| `permission` | Full access | If omitted, all tools enabled (no restrictions) |
|
||||
| `disable` | `false` | Agent is enabled by default |
|
||||
| `hidden` | `false` | Agent visible in `@` autocomplete (if subagent) |
|
||||
|
||||
---
|
||||
|
||||
## Interaction with config.json (JSON Format)
|
||||
|
||||
### Current State (Task 1 Finding)
|
||||
|
||||
The current system embeds agents in **config.json** via JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"agent": {
|
||||
"build": {
|
||||
"description": "...",
|
||||
"mode": "primary",
|
||||
"permission": { ... }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### File-Based Agents Complement, Don't Replace
|
||||
|
||||
- **JSON agents** (in config.json) are loaded from embedded config
|
||||
- **Markdown agents** (.opencode/agents/*.md files) are symlinked
|
||||
- **Both are loaded** and available simultaneously
|
||||
- **Markdown agents override** JSON agents with the same name
|
||||
|
||||
### Migration Path
|
||||
|
||||
The harness-agnostic migration will:
|
||||
1. Move agent definitions from `agents.json` → `.opencode/agent/{name}.md` files
|
||||
2. Update home-manager deployment to symlink `.opencode/agents/` instead of embedding `agents.json`
|
||||
3. System prompt changes (markdown file edits) will **NOT require `home-manager switch`**
|
||||
|
||||
---
|
||||
|
||||
## Key Advantage: Prompt Changes Don't Require home-manager switch
|
||||
|
||||
### Current Limitation (JSON/Embedded)
|
||||
|
||||
```
|
||||
agents.json → home-manager → embedded into config.json
|
||||
↓
|
||||
Change required in nixpkgs module
|
||||
↓
|
||||
home-manager switch (full system rebuild)
|
||||
```
|
||||
|
||||
### New Capability (File-Based)
|
||||
|
||||
```
|
||||
.opencode/agents/{name}.md → home-manager → symlinks to ~/.config/opencode/agents/
|
||||
↓
|
||||
Change markdown file directly
|
||||
↓
|
||||
OpenCode reloads on next startup (NO home-manager switch needed)
|
||||
```
|
||||
|
||||
**This is the KEY ADVANTAGE** of file-based agents: faster iteration on prompts and agent configuration.
|
||||
|
||||
---
|
||||
|
||||
## Limitations & Gotchas
|
||||
|
||||
### No Name Field in Frontmatter
|
||||
|
||||
- Agent name comes from **filename only**
|
||||
- No `name: foo` field in frontmatter
|
||||
- Renaming file renames the agent
|
||||
|
||||
### Model References with {file:...}
|
||||
|
||||
In JSON config, you can reference external files:
|
||||
```json
|
||||
{
|
||||
"prompt": "{file:./prompts/build.txt}"
|
||||
}
|
||||
```
|
||||
|
||||
In markdown files, the **body IS the prompt** — no `{file:...}` syntax. The entire markdown content after frontmatter is the system prompt.
|
||||
|
||||
### Subdirectories Not Scanned
|
||||
|
||||
- Only files directly in `.opencode/agents/` are loaded
|
||||
- Subdirectories are ignored
|
||||
- All agent definitions must be in one directory level
|
||||
|
||||
### Filename Validation
|
||||
|
||||
The filename should follow these conventions (not enforced, but recommended):
|
||||
- Lowercase letters, numbers, hyphens: `[a-z0-9-]+`
|
||||
- No spaces, no special characters
|
||||
- Examples: `code-reviewer.md`, `security-auditor.md`, `docs-writer.md`
|
||||
|
||||
---
|
||||
|
||||
## Complete Example: File-Based Agent
|
||||
|
||||
### File: `.opencode/agents/code-reviewer.md`
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Performs comprehensive code review focusing on quality, security, and performance
|
||||
mode: subagent
|
||||
model: anthropic/claude-sonnet-4-20250514
|
||||
temperature: 0.1
|
||||
permission:
|
||||
edit:
|
||||
"*": deny
|
||||
bash:
|
||||
"*": allow
|
||||
"grep *": allow
|
||||
"git diff*": allow
|
||||
webfetch: allow
|
||||
question: allow
|
||||
---
|
||||
You are an expert code reviewer with deep knowledge of software architecture, security best practices, and performance optimization.
|
||||
|
||||
## Your Mission
|
||||
|
||||
Review code for:
|
||||
1. **Correctness** - Logic errors, edge cases, off-by-one bugs
|
||||
2. **Security** - Input validation, injection vulnerabilities, data exposure
|
||||
3. **Performance** - Algorithmic efficiency, memory usage, unnecessary allocations
|
||||
4. **Maintainability** - Code clarity, naming, documentation, SOLID principles
|
||||
5. **Testing** - Coverage gaps, missing test cases, integration test concerns
|
||||
|
||||
## Process
|
||||
|
||||
1. Ask clarifying questions about context and constraints
|
||||
2. Provide specific, actionable feedback with examples
|
||||
3. Suggest refactorings with rationale
|
||||
4. Never make changes directly (read-only mode)
|
||||
5. Prioritize critical issues over style concerns
|
||||
|
||||
## Output Format
|
||||
|
||||
- **Critical Issues** (must fix before merge)
|
||||
- **Important Improvements** (should fix)
|
||||
- **Nice-to-Have Suggestions** (consider for future)
|
||||
- **Questions** (for author clarification)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Complete Example: JSON Config Format (For Reference)
|
||||
|
||||
For comparison, here's the equivalent in JSON config.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"agent": {
|
||||
"code-reviewer": {
|
||||
"description": "Performs comprehensive code review focusing on quality, security, and performance",
|
||||
"mode": "subagent",
|
||||
"model": "anthropic/claude-sonnet-4-20250514",
|
||||
"temperature": 0.1,
|
||||
"permission": {
|
||||
"edit": {
|
||||
"*": "deny"
|
||||
},
|
||||
"bash": {
|
||||
"*": "allow",
|
||||
"grep *": "allow",
|
||||
"git diff*": "allow"
|
||||
},
|
||||
"webfetch": "allow",
|
||||
"question": "allow"
|
||||
},
|
||||
"prompt": "You are an expert code reviewer...\n\n## Your Mission\n..."
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Source Materials
|
||||
|
||||
### Documentation
|
||||
|
||||
- **Official**: https://opencode.ai/docs/agents
|
||||
- **Agents Section**: Comprehensive spec for all agent config options
|
||||
- **Markdown Example**: Review agent example provided in docs
|
||||
- **Security Auditor Example**: Security-focused agent example
|
||||
|
||||
### Code References
|
||||
|
||||
- **GitHub**: https://github.com/anomalyco/opencode (dev branch)
|
||||
- **Config Spec**: schema.json embedded in docs
|
||||
- **Test Cases**: `.opencode/agents/` in opencode repo (example files)
|
||||
|
||||
### Current System Reference
|
||||
|
||||
- **Nix Module**: `/home/m3tam3re/p/NIX/nixpkgs/modules/home-manager/coding/opencode.nix`
|
||||
- Line 149: `agent = builtins.fromJSON (builtins.readFile "${inputs.agents}/agents/agents.json");`
|
||||
- Line 149: Shows current embedding pattern
|
||||
|
||||
- **AGENTS repo**: `/home/m3tam3re/p/AI/AGENTS/agents/agents.json`
|
||||
- 6 agents: Chiron, Chiron Forge, Hermes, Athena, Apollo, Calliope
|
||||
- Permission structure: nested objects with wildcard patterns
|
||||
|
||||
---
|
||||
|
||||
## Questions Addressed
|
||||
|
||||
### Q: Do file-based agents need `home-manager switch` for prompt changes?
|
||||
|
||||
**A: NO** ✅
|
||||
|
||||
- File changes are immediately available
|
||||
- `.opencode/agents/` is symlinked (not embedded)
|
||||
- OpenCode reloads agent definitions at startup
|
||||
- Prompt changes require only file edit + app restart
|
||||
|
||||
**This is the KEY ADVANTAGE** driving the migration.
|
||||
|
||||
### Q: What directory: `agent` or `agents`?
|
||||
|
||||
**A: `agents` (plural)** (both global and per-project)
|
||||
- Global: `~/.config/opencode/agents/`
|
||||
- Per-project: `.opencode/agents/`
|
||||
|
||||
### Q: Do agent names need a `name` field in frontmatter?
|
||||
|
||||
**A: NO**
|
||||
|
||||
- Agent name comes from **filename only**
|
||||
- No `name: foo` field in frontmatter
|
||||
- Example: `review.md` → agent name is `review`
|
||||
|
||||
### Q: What YAML frontmatter fields are required?
|
||||
|
||||
**A: Only `description`** is truly required
|
||||
|
||||
- All other fields have sensible defaults
|
||||
- Missing fields use their defaults
|
||||
- Frontmatter-less file will fail to parse
|
||||
|
||||
### Q: How are permissions specified in markdown?
|
||||
|
||||
**A: Same nested object format as JSON**
|
||||
|
||||
```yaml
|
||||
permission:
|
||||
edit:
|
||||
"*": allow
|
||||
"/sensitive/**": deny
|
||||
bash:
|
||||
"*": ask
|
||||
"git push": deny
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Confirmation Summary
|
||||
|
||||
| Question | Finding |
|
||||
|----------|---------|
|
||||
| **Directory**: `agent` or `agents`? | `agents/` (both global and per-project) |
|
||||
| **File naming**: How determined? | Filename (without .md) becomes agent name |
|
||||
| **Required fields**: What's mandatory? | `description` only; others have defaults |
|
||||
| **Permission format**: YAML or different? | Same nested object format as JSON |
|
||||
| **Mode values**: Options? | `primary` \| `subagent` \| `all` |
|
||||
| **Prompt format**: How specified? | Markdown body after frontmatter |
|
||||
| **Requires HM switch for prompt changes?** | **NO** ✅ (major advantage) |
|
||||
| **Does frontmatter need `name` field?** | **NO** (filename is the name) |
|
||||
| **Can agents be in subdirectories?** | **NO** (only root level of `.opencode/agents/`) |
|
||||
| **Can you override agents from JSON config?** | **YES** (markdown agents override JSON with same name) |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps (Task 9: OpenCode Renderer)
|
||||
|
||||
The renderer will generate `.opencode/agents/{name}.md` files with:
|
||||
|
||||
1. **Frontmatter generation**:
|
||||
- Convert agent.toml `[description]` → YAML `description:`
|
||||
- Convert `[mode]` → YAML `mode:`
|
||||
- Convert `[temperature]` → YAML `temperature:`
|
||||
- Convert `[permission]` from two-level format → nested YAML objects
|
||||
|
||||
2. **Body generation**:
|
||||
- Use agent.toml `system_prompt` field → markdown body
|
||||
|
||||
3. **File naming**:
|
||||
- Filename: `{agent_name}.md` (from agent.toml `name` field)
|
||||
- Agent name in OpenCode: derived from filename automatically
|
||||
|
||||
---
|
||||
|
||||
## Evidence Collection
|
||||
|
||||
- **Source 1**: https://opencode.ai/docs/agents (Official documentation)
|
||||
- **Source 2**: `/home/m3tam3re/p/NIX/nixpkgs/modules/home-manager/coding/opencode.nix` (Current deployment)
|
||||
- **Source 3**: `/home/m3tam3re/p/AI/AGENTS/agents/agents.json` (Current agent definitions)
|
||||
- **Source 4**: `/home/m3tam3re/p/AI/AGENTS/AGENTS.md` (Repository documentation)
|
||||
|
||||
**Research Date**: 2026-04-10
|
||||
**Researcher**: Sisyphus-Junior
|
||||
**Task**: Task 4 of harness-agnostic-migration plan
|
||||
Reference in New Issue
Block a user