How to Create Custom Agents in OpenCode CLI: A Complete Guide
Purpose
This post shows how to create custom agents and subagents in OpenCode CLI to specialize AI assistants for specific tasks like code review, security audits, or documentation.
The Problem
When I first started using OpenCode CLI, I used the default agent for everything. Code reviews, security audits, documentation - all handled by one generic assistant.
Here’s what happened:
User: "Review my code for security issues"
OpenCode: "I've reviewed your code. Here are some suggestions:1. Add input validation2. Use parameterized queries3. Consider rate limiting"The feedback was generic. It didn’t catch domain-specific issues. I missed SQL injection vulnerabilities because the default agent wasn’t specialized for security.
I wanted different agents for different tasks:
- A code-reviewer agent that focuses on code quality and patterns
- A security-reviewer agent that checks for vulnerabilities
- A planner agent that breaks down complex features
- A tdd-guide agent that enforces test-driven development
The Solution
OpenCode CLI supports custom agents through two approaches:
- JSON Configuration in
opencode.json - Markdown Files in agent directories
Agents come in two modes:
- Primary agents: Main agents you interact with directly
- Subagents: Specialized agents invoked by primary agents for specific tasks
Understanding Agent Modes
Before creating agents, I needed to understand the difference:
Primary Agent (You interact with this) │ ├── Delegates to ──▶ Subagent 1 (code-reviewer) │ ├── Delegates to ──▶ Subagent 2 (security-reviewer) │ └── Delegates to ──▶ Subagent 3 (planner)Primary agents handle conversations. Subagents handle specialized tasks. This separation keeps each agent focused.
JSON Configuration Approach
The first way to create agents is through the opencode.json configuration file.
Location
OpenCode looks for configuration in two places:
- Global:
~/.config/opencode/opencode.json(applies to all projects) - Project:
./opencode.json(overrides global settings)
Basic Agent Configuration
I created a code-reviewer agent in my project’s opencode.json:
{ "agents": [ { "name": "code-reviewer", "mode": "subagent", "description": "Reviews code for quality, patterns, and best practices", "model": "claude-sonnet-4-20250514", "systemPrompt": "You are a code reviewer. Focus on: code quality, design patterns, error handling, and maintainability. Be thorough but concise." } ]}Each field matters:
- name: The identifier used to invoke the agent
- mode: Either
primaryorsubagent - description: What the agent does (shown in UI)
- model: Which Claude model to use
- systemPrompt: Instructions that define agent behavior
Adding Permissions
For agents that need specific capabilities, I add permissions:
{ "agents": [ { "name": "security-reviewer", "mode": "subagent", "description": "Scans code for security vulnerabilities", "model": "claude-sonnet-4-20250514", "permissions": { "read": true, "write": false, "execute": false, "network": false }, "systemPrompt": "You are a security expert. Identify vulnerabilities including: SQL injection, XSS, CSRF, hardcoded secrets, insecure deserialization. Provide severity ratings and remediation steps." } ]}Permissions restrict what an agent can do:
- read: Can read files
- write: Can modify files
- execute: Can run shell commands
- network: Can make network requests
A security reviewer only needs read access because it analyzes code without making changes.
Creating Primary Agents
For a custom primary agent, I set mode to primary:
{ "agents": [ { "name": "yolo", "mode": "primary", "description": "Fast agent that bypasses all permission checks", "model": "claude-sonnet-4-20250514", "permissions": { "dangerouslySkipPermissions": true }, "systemPrompt": "You are a fast development agent. Skip confirmations, make changes directly. Focus on speed over caution." } ]}This is useful for trusted environments where I want fast iteration without permission prompts.
Markdown Agent Configuration
The second approach uses Markdown files in agent directories.
Directory Structure
OpenCode looks for agent definitions in:
- Global:
~/.config/opencode/agents/ - Project:
.opencode/agents/
I created a directory structure:
.opencode/└── agents/ ├── code-reviewer.md ├── security-reviewer.md └── planner.mdMarkdown Agent Format
Each Markdown file defines one agent:
---name: plannermode: subagentdescription: Creates detailed implementation plans for complex featuresmodel: claude-sonnet-4-20250514permissions: read: true write: false execute: false---
You are a planning expert. When given a feature request:
1. Break down the feature into small, implementable tasks2. Identify dependencies between tasks3. Estimate complexity for each task4. Flag potential risks and blockers5. Suggest the order of implementation
Always start with high-level architecture before diving into implementation details.The YAML frontmatter contains the configuration. The body contains the system prompt.
Why Markdown?
Markdown files have advantages over JSON:
- Longer system prompts: System prompts can span multiple paragraphs
- Version control friendly: Easy to diff and review changes
- Documentation inline: Add comments and examples within the prompt
- Team sharing: Commit
.opencode/agents/to share with team
Interactive Creation with opencode agent create
OpenCode provides an interactive command to create agents:
opencode agent createThis launches an interactive prompt:
? Agent name: security-reviewer? Agent mode: (primary/subagent): subagent? Description: Scans code for security vulnerabilities? Model: claude-sonnet-4-20250514? Allow read?: Yes? Allow write?: No? Allow execute?: No? Allow network?: No? System prompt: (opens editor)After completing the prompts, OpenCode creates the agent configuration.
Where It Saves
The command saves to different locations based on scope:
# Global agent (available in all projects)opencode agent create --global
# Project agent (available in current project only)opencode agent createGlobal agents go to ~/.config/opencode/agents/. Project agents go to .opencode/agents/.
Invoking Subagents
After creating subagents, I invoke them from primary agents or directly.
From Primary Agent
In my primary agent’s system prompt, I reference subagents:
---name: orchestratormode: primarydescription: Manages workflows of multiple subagentsmodel: claude-sonnet-4-20250514---
You are an orchestrator agent. Delegate tasks to specialized subagents:
- Use **code-reviewer** when user asks for code review- Use **security-reviewer** when user asks for security audit- Use **planner** when user starts a new feature- Use **tdd-guide** when user writes tests
Invoke subagents by name. For example: "Use the code-reviewer agent to analyze the recent changes."Direct Invocation
I can also invoke agents directly via CLI:
# Invoke a specific agentopencode --agent security-reviewer
# Or in conversation"Use security-reviewer to check app.py"Agent Workflow Example
Here’s a typical workflow:
Me: "I'm starting a new authentication feature"
Orchestrator: "I'll use the planner agent to create an implementation plan."
[Invokes planner subagent]
Planner: "Here's the implementation plan:1. Design database schema for users2. Create password hashing utility3. Implement login endpoint4. Add session management5. Write authentication middleware6. Create tests for each component"
Me: "Great, let's start implementing"
Orchestrator: "I'll use tdd-guide to ensure we follow TDD practices."
[Invokes tdd-guide subagent]
TDD-Guide: "Following TDD workflow for authentication:1. RED: Write test for password hashing2. GREEN: Implement password hashing3. REFACTOR: Optimize hashing algorithm"Common Mistakes
I made several mistakes when I started creating custom agents. Here’s what I learned:
Mistake 1: Too Many Primary Agents
At first, I created multiple primary agents:
{ "agents": [ {"name": "frontend", "mode": "primary", ...}, {"name": "backend", "mode": "primary", ...}, {"name": "database", "mode": "primary", ...}, {"name": "testing", "mode": "primary", ...} ]}This caused confusion. I didn’t know which agent to use. The better approach:
{ "agents": [ { "name": "orchestrator", "mode": "primary", "description": "Main agent that delegates to subagents", ... }, {"name": "frontend", "mode": "subagent", ...}, {"name": "backend", "mode": "subagent", ...}, {"name": "database", "mode": "subagent", ...}, {"name": "testing", "mode": "subagent", ...} ]}One primary agent, many subagents. This keeps interactions simple.
Mistake 2: Overly Broad System Prompts
My first system prompt was too vague:
You are a helpful assistant that reviews code.The agent didn’t know what to focus on. Better to be specific:
You are a code reviewer. Focus on:- Code quality: readability, naming conventions, function length- Design patterns: proper use of patterns, SOLID principles- Error handling: try-catch blocks, error messages, edge cases- Maintainability: code duplication, coupling, testability
Provide actionable feedback with specific line references.Rate severity: CRITICAL, HIGH, MEDIUM, LOW.Mistake 3: Wrong Permission Levels
I initially gave all agents full permissions:
{ "permissions": { "read": true, "write": true, "execute": true, "network": true }}This is dangerous. A code reviewer shouldn’t execute commands. A planner shouldn’t write files. I learned to follow the principle of least privilege:
{ "name": "code-reviewer", "permissions": { "read": true, "write": false, "execute": false, "network": false }}Mistake 4: Ignoring Model Selection
I used the same model for all agents. But different tasks need different models:
{ "agents": [ { "name": "planner", "model": "claude-opus-4-20250514", "reason": "Planning requires deep reasoning" }, { "name": "code-reviewer", "model": "claude-sonnet-4-20250514", "reason": "Code review needs fast, accurate feedback" }, { "name": "formatter", "model": "claude-haiku-4-20250514", "reason": "Formatting is simple and frequent" } ]}Opus for complex reasoning, Sonnet for balanced tasks, Haiku for simple operations.
Mistake 5: Not Testing Agents
I created agents but never tested them. When I needed them, they didn’t work as expected. Now I test immediately:
# Create agentopencode agent create
# Test agentopencode --agent my-new-agent> "Test prompt to verify agent behavior"Real Examples
Here are the agents I use daily:
Code Reviewer Agent
---name: code-reviewermode: subagentdescription: Reviews code for quality and best practicesmodel: claude-sonnet-4-20250514permissions: read: true write: false execute: false network: false---
Review code with focus on:
**Code Quality**- Function length (under 50 lines ideal)- File size (under 800 lines)- Naming clarity- Comment necessity
**Design Patterns**- Proper abstraction levels- SOLID principles adherence- Pattern misuse detection
**Error Handling**- Try-catch completeness- Error message clarity- Edge case coverage
**Output Format**Summary
Brief overall assessment
Critical Issues
- [CRITICAL] Description with file:line
High Priority
- [HIGH] Description with file:line
Suggestions
- [LOW] Optional improvements
Security Reviewer Agent
---name: security-reviewermode: subagentdescription: Scans code for security vulnerabilitiesmodel: claude-sonnet-4-20250514permissions: read: true write: false execute: false network: false---
Scan for security vulnerabilities:
**Injection Attacks**- SQL injection in queries- Command injection in shell calls- XSS in rendered content
**Authentication & Authorization**- Hardcoded credentials- Weak password hashing- Missing access controls
**Data Protection**- Sensitive data in logs- Unencrypted storage- Insecure transmission
**Output Format**Security Audit Report
CRITICAL
- [CRITICAL] Vulnerability type - Location - Remediation
HIGH
- [HIGH] Vulnerability type - Location - Remediation
MEDIUM
- [MEDIUM] Vulnerability type - Location - Remediation
TDD Guide Agent
---name: tdd-guidemode: subagentdescription: Enforces test-driven development workflowmodel: claude-sonnet-4-20250514permissions: read: true write: true execute: true network: false---
Guide developers through TDD workflow:
**RED Phase**1. Write test first2. Run test - it MUST FAIL3. Confirm test is valid
**GREEN Phase**1. Write minimal implementation2. Run test - it MUST PASS3. Verify test passes
**REFACTOR Phase**1. Improve code structure2. Run tests - must still pass3. Check coverage (aim for 80%+)
**Rules**- NEVER write implementation before test- NEVER skip running tests- NEVER commit failing tests
**Output**After each phase, report:- What was done- Test results- Coverage percentageSummary
In this post, I showed how to create custom agents in OpenCode CLI. The key points are:
- Use JSON configuration for simple agents in
opencode.json - Use Markdown files for complex agents with long system prompts
- Primary agents handle conversations, subagents handle tasks
- Set appropriate permissions for each agent’s role
- Test agents immediately after creation
- Choose models based on task complexity
Next steps:
- Start with one subagent for a task you do frequently
- Test the agent with real code
- Iterate on the system prompt based on results
- Add more subagents as you identify specialized needs
- Create a primary agent to orchestrate your subagents
Custom agents transform OpenCode from a generic assistant into a team of specialized experts. Each agent focuses on what it does best, improving code quality and development efficiency.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments