# Core Concept: Agent Metadata System **Purpose**: Understanding the centralized metadata system for OpenAgents Control **Priority**: CRITICAL - Load this before working with agent metadata --- ## What Is the Agent Metadata System? The agent metadata system separates **OpenCode-compliant agent configuration** from **OpenAgents Control registry metadata**. This solves the problem of OpenCode validation errors when agents contain fields that aren't part of the OpenCode agent schema. **Key Principle**: Agent frontmatter contains ONLY valid OpenCode fields. All other metadata lives in a centralized file. --- ## The Problem We Solved ### Before (Validation Errors) Agent frontmatter contained fields that OpenCode doesn't recognize: ```yaml --- id: opencoder # ❌ Not valid OpenCode field name: OpenCoder # ❌ Not valid OpenCode field category: core # ❌ Not valid OpenCode field type: core # ❌ Not valid OpenCode field version: 1.0.0 # ❌ Not valid OpenCode field author: opencode # ❌ Not valid OpenCode field tags: [development, coding] # ❌ Not valid OpenCode field dependencies: [] # ❌ Not valid OpenCode field description: "..." # ✅ Valid OpenCode field mode: primary # ✅ Valid OpenCode field temperature: 0.1 # ✅ Valid OpenCode field tools: {...} # ✅ Valid OpenCode field permission: {...} # ✅ Valid OpenCode field --- ``` **Result**: OpenCode validation errors: ``` Extra inputs are not permitted, field: 'id', value: 'opencoder' Extra inputs are not permitted, field: 'category', value: 'core' Extra inputs are not permitted, field: 'type', value: 'core' ... (9 validation errors) ``` ### After (Clean Separation) **Agent frontmatter** (`.opencode/agent/core/opencoder.md`): ```yaml --- # Metadata stored in: .opencode/config/agent-metadata.json description: "Orchestration agent for complex coding, architecture, and multi-file refactoring" mode: primary temperature: 0.1 tools: {...} permission: {...} --- ``` **Centralized metadata** (`.opencode/config/agent-metadata.json`): ```json { "agents": { "opencoder": { "id": "opencoder", "name": "OpenCoder", "category": "core", "type": "agent", "version": "1.0.0", "author": "opencode", "tags": ["development", "coding", "implementation"], "dependencies": [ "subagent:documentation", "subagent:coder-agent", "context:core/standards/code" ] } } } ``` **Result**: ✅ No validation errors, clean separation of concerns --- ## Valid OpenCode Agent Fields Based on [OpenCode documentation](https://opencode.ai/docs/agents/), these are the ONLY valid frontmatter fields: ### Required Fields - `description` - When to use this agent (required) - `mode` - Agent type: `primary`, `subagent`, or `all` (defaults to `all`) ### Optional Fields - `model` - Model override (e.g., `anthropic/claude-sonnet-4-20250514`) - `temperature` - Response randomness (0.0-1.0) - `maxSteps` - Max agentic iterations - `disable` - Set to `true` to disable agent - `prompt` - Custom prompt file path (e.g., `{file:./prompts/build.txt}`) - `hidden` - Hide from @ autocomplete (subagents only) - `tools` - Tool access configuration - `permission` - Permission rules for tools (v1.1.1+, replaces deprecated `permissions`) ### Example Valid Frontmatter ```yaml --- description: "Code review agent with security focus" mode: subagent model: anthropic/claude-sonnet-4-20250514 temperature: 0.1 tools: read: true grep: true glob: true write: false edit: false permission: # v1.1.1+ (singular, not plural) bash: "*": ask "git *": allow edit: deny --- ``` --- ## Centralized Metadata File **Location**: `.opencode/config/agent-metadata.json` ### Schema ```json { "$schema": "https://opencode.ai/schemas/agent-metadata.json", "schema_version": "1.0.0", "description": "Centralized metadata for OpenAgents Control agents", "agents": { "agent-id": { "id": "agent-id", "name": "Agent Name", "category": "core|development|content|data|product|learning|meta", "type": "agent|subagent", "version": "1.0.0", "author": "opencode", "tags": ["tag1", "tag2"], "dependencies": [ "subagent:subagent-id", "context:path/to/context" ] } }, "defaults": { "agent": { "version": "1.0.0", "author": "opencode", "type": "agent", "tags": [] }, "subagent": { "version": "1.0.0", "author": "opencode", "type": "subagent", "tags": [] } } } ``` ### Metadata Fields | Field | Required | Description | Example | |-------|----------|-------------|---------| | `id` | Yes | Unique identifier (kebab-case) | `"opencoder"` | | `name` | Yes | Display name | `"OpenCoder"` | | `category` | Yes | Agent category | `"core"` | | `type` | Yes | Component type | `"agent"` or `"subagent"` | | `version` | Yes | Version number | `"1.0.0"` | | `author` | Yes | Author identifier | `"opencode"` | | `tags` | No | Discovery tags | `["development", "coding"]` | | `dependencies` | No | Component dependencies | `["subagent:tester"]` | --- ## How It Works ### 1. Agent Creation When creating a new agent: **Step 1**: Create agent file with ONLY valid OpenCode fields ```bash # Create agent file touch .opencode/agent/category/my-agent.md ``` ```yaml --- description: "My agent description" mode: subagent temperature: 0.2 tools: read: true write: true --- # Agent prompt content here ``` **Step 2**: Add metadata to `.opencode/config/agent-metadata.json` ```json { "agents": { "my-agent": { "id": "my-agent", "name": "My Agent", "category": "development", "type": "subagent", "version": "1.0.0", "author": "opencode", "tags": ["custom", "helper"], "dependencies": ["context:core/standards/code"] } } } ``` **Step 3**: Run auto-detect to update registry ```bash ./scripts/registry/auto-detect-components.sh --auto-add ``` The auto-detect script: 1. Reads frontmatter from agent file (description, mode, etc.) 2. Reads metadata from `agent-metadata.json` (id, name, tags, dependencies) 3. Merges both into registry.json entry ### 2. Auto-Detect Integration The auto-detect script (`scripts/registry/auto-detect-components.sh`) has been enhanced to: 1. **Extract frontmatter** - Read description from agent file 2. **Lookup metadata** - Check `agent-metadata.json` for agent ID 3. **Merge data** - Combine frontmatter + metadata 4. **Update registry** - Write complete entry to registry.json **Code snippet** (from auto-detect script): ```bash # Check if agent-metadata.json exists and merge metadata from it local metadata_file="$REPO_ROOT/.opencode/config/agent-metadata.json" if [ -f "$metadata_file" ] && command -v jq &> /dev/null; then # Try to find metadata for this agent ID local metadata_entry metadata_entry=$(jq -r ".agents[\"$id\"] // empty" "$metadata_file" 2>/dev/null) if [ -n "$metadata_entry" ] && [ "$metadata_entry" != "null" ]; then # Merge name, tags, dependencies from metadata # ... fi fi ``` ### 3. Registry Output The registry.json entry contains merged data: ```json { "id": "opencoder", "name": "OpenCoder", "type": "agent", "path": ".opencode/agent/core/opencoder.md", "description": "Orchestration agent for complex coding...", "category": "core", "tags": ["development", "coding", "implementation"], "dependencies": [ "subagent:documentation", "subagent:coder-agent", "context:core/standards/code" ] } ``` --- ## Workflow ### Adding a New Agent ```bash # 1. Create agent file (OpenCode-compliant frontmatter only) vim .opencode/agent/category/my-agent.md # 2. Add metadata entry vim .opencode/config/agent-metadata.json # 3. Update registry ./scripts/registry/auto-detect-components.sh --auto-add # 4. Validate ./scripts/registry/validate-registry.sh ``` ### Updating Agent Metadata **To update OpenCode configuration** (tools, permissions, temperature): ```bash # Edit agent file frontmatter vim .opencode/agent/category/my-agent.md ``` **To update registry metadata** (tags, dependencies, version): ```bash # Edit metadata file vim .opencode/config/agent-metadata.json # Re-run auto-detect ./scripts/registry/auto-detect-components.sh --auto-add ``` ### Updating Dependencies **Add a dependency**: ```json { "agents": { "my-agent": { "dependencies": [ "subagent:tester", "context:core/standards/code", "subagent:new-dependency" // ← Add here ] } } } ``` Then run: ```bash ./scripts/registry/auto-detect-components.sh --auto-add ./scripts/registry/validate-registry.sh ``` --- ## Benefits ### ✅ OpenCode Compliance - Agent frontmatter contains ONLY valid OpenCode fields - No validation errors from OpenCode - Agents work correctly with OpenCode CLI ### ✅ Registry Compatibility - Registry still has all metadata (id, name, category, tags, dependencies) - Auto-detect script merges frontmatter + metadata - Backward compatible with existing tools ### ✅ Single Source of Truth - Metadata centralized in one file - Easy to update dependencies across multiple agents - Clear separation: OpenCode config vs. registry metadata ### ✅ Maintainability - Update dependencies in one place - Consistent metadata across all agents - Easy to add new metadata fields ### ✅ Validation - OpenCode validates frontmatter (no extra fields) - Registry validator checks dependencies exist - Clear error messages when metadata is missing --- ## Migration Guide ### Migrating from permissions (plural) to permission (singular) **OpenCode v1.1.1+ Change**: The field name changed from `permissions:` (plural) to `permission:` (singular). **Before** (deprecated): ```yaml permissions: bash: "*": "deny" ``` **After** (v1.1.1+): ```yaml permission: bash: "*": "deny" ``` **Migration Steps**: 1. Find all agents using `permissions:` (plural) ```bash grep -r "^permissions:" .opencode/agent/ ``` 2. Replace with `permission:` (singular) in each file 3. Verify no validation errors: ```bash opencode agent validate ``` ### Migrating Existing Agents **Step 1**: Identify agents with extra fields ```bash # Find agents with invalid OpenCode fields grep -r "^id:\|^name:\|^category:\|^type:\|^version:\|^author:\|^tags:\|^dependencies:" .opencode/agent/ ``` **Step 2**: Extract metadata to `agent-metadata.json` For each agent: 1. Copy `id`, `name`, `category`, `type`, `version`, `author`, `tags`, `dependencies` to metadata file 2. Remove these fields from agent frontmatter 3. Keep ONLY valid OpenCode fields in frontmatter **Step 3**: Update registry ```bash # Remove old entries jq 'del(.components.agents[] | select(.id == "agent-id"))' registry.json > tmp.json && mv tmp.json registry.json # Re-add with new metadata ./scripts/registry/auto-detect-components.sh --auto-add ``` **Step 4**: Validate ```bash ./scripts/registry/validate-registry.sh ``` --- ## Best Practices ### Agent Frontmatter ✅ **DO**: - Keep frontmatter minimal (only OpenCode fields) - Add comment pointing to metadata file - Use consistent formatting ❌ **DON'T**: - Add custom fields to frontmatter - Duplicate metadata in both places - Skip the metadata file ### Metadata File ✅ **DO**: - Keep metadata file in version control - Update metadata when adding/removing dependencies - Use consistent naming (kebab-case for IDs) - Document why dependencies exist ❌ **DON'T**: - Forget to update metadata when creating agents - Leave orphaned entries (agents that don't exist) - Skip validation after updates ### Dependencies ✅ **DO**: - Declare ALL dependencies (subagents, contexts) - Use correct format: `type:id` - Validate dependencies exist in registry ❌ **DON'T**: - Reference components without declaring dependency - Use invalid dependency formats - Forget to update when dependencies change --- ## Troubleshooting ### OpenCode Validation Errors **Problem**: `Extra inputs are not permitted, field: 'id'` **Solution**: Remove invalid fields from agent frontmatter, add to metadata file ```bash # 1. Edit agent file - remove id, name, category, type, version, author, tags, dependencies vim .opencode/agent/category/agent.md # 2. Add to metadata file vim .opencode/config/agent-metadata.json # 3. Update registry ./scripts/registry/auto-detect-components.sh --auto-add ``` ### Missing Metadata **Problem**: Auto-detect can't find metadata for agent **Solution**: Add entry to `agent-metadata.json` ```json { "agents": { "agent-id": { "id": "agent-id", "name": "Agent Name", "category": "core", "type": "agent", "version": "1.0.0", "author": "opencode", "tags": [], "dependencies": [] } } } ``` ### Registry Out of Sync **Problem**: Registry has old metadata **Solution**: Remove entry and re-run auto-detect ```bash # Remove old entry jq 'del(.components.agents[] | select(.id == "agent-id"))' registry.json > tmp.json && mv tmp.json registry.json # Re-add with current metadata ./scripts/registry/auto-detect-components.sh --auto-add ``` --- ## Related Files - **OpenCode Agent Docs**: https://opencode.ai/docs/agents/ - **Registry System**: `.opencode/context/openagents-repo/core-concepts/registry.md` - **Adding Agents**: `.opencode/context/openagents-repo/guides/adding-agent.md` - **Dependencies**: `.opencode/context/openagents-repo/quality/registry-dependencies.md` --- **Last Updated**: 2026-01-31 **Version**: 1.0.0