This guide teaches you how to build efficient, scalable OpenCode systems using the 4-layer architecture. Master this formula to create powerful AI workflows with minimal token usage and maximum reusability.
Layer 1: TOOLS → Atomic operations (read, test, lint)
Layer 2: SUBAGENTS → Specialized skills (security, testing, refactoring)
Layer 3: COMMANDS → User shortcuts + templates (slash commands)
Layer 4: MAIN AGENTS → Orchestration (build, plan, general)
Each layer serves a specific purpose and builds upon the previous one.
Create tools for frequent, verbose operations that need output filtering or caching.
// .opencode/tool/[operation].ts
export default tool({
description: "One-line: what it does, when to use",
args: { /* minimal params */ },
async execute(args, ctx) {
// Run operation
// Parse output
// Return only what matters
return conciseResult
}
})
test-runner - Run tests, return pass/fail + errors onlylint-check - Return only errors in changed filesbuild-check - Return warnings/errors, not full logs# Create your first efficient tool
mkdir -p .opencode/tool
cat > .opencode/tool/test.ts << 'EOF'
import { tool } from "@opencode-ai/plugin"
import { z } from "zod"
export default tool({
description: "Run tests, return summary or failures only",
args: { path: z.string() },
async execute(args, ctx) {
const result = await ctx.$`npm test -- ${args.path}`.nothrow()
const output = await new Response(result.stdout).text()
return result.exitCode === 0
? `✅ Tests passed`
: `❌ Failed:\n${output.split('\n').filter(l => l.includes('FAIL') || l.includes('●')).slice(0, 20).join('\n')}`
}
})
EOF
# Test it
opencode tui
# Type: "run the tests"
Create subagents for complex, reusable workflows that require domain expertise.
# .opencode/agent/[domain]/[specialist].md
---
mode: "subagent"
description: "Use WHEN/AFTER [trigger condition]"
tools:
[essential-tool]: true
task: false # Prevent recursion
---
You are [role]. You specialize in:
1. [Specific capability]
2. [Specific capability]
Always [output format/requirement].
.opencode/agent/
├── security/
│ ├── code-scanner.md # Vulnerability detection
│ ├── dependency-audit.md # Supply chain check
│ └── secrets-detector.md # Credential scanning
├── testing/
│ ├── unit-generator.md # Generate unit tests
│ ├── e2e-builder.md # E2E test creation
│ └── test-fixer.md # Fix failing tests
└── refactor/
├── modernizer.md # Update legacy code
├── optimizer.md # Performance improvements
└── simplifier.md # Reduce complexity
# .opencode/agent/security/code-scanner.md
---
mode: "subagent"
description: "Use AFTER writing auth code to scan for vulnerabilities"
tools:
lint-check: true
test-runner: true
task: false
---
You are a Security Specialist. You scan code for:
1. SQL injection vulnerabilities
2. XSS attack vectors
3. Authentication/authorization flaws
4. Insecure dependencies
Always return a structured report with severity levels.
Create commands for common user workflows that benefit from templates and context.
# .opencode/command/[workflow]/[action].md
---
description: "What this does"
agent: "[subagent-name]" # Routes to subagent
---
[Detailed prompt with context]
@$1 # File references
@AGENTS.md # Project standards
Additional: $2
Command = Subagent + Context Files + Template
/security/scan file.ts # → security/code-scanner + project files
/test/generate service.ts # → testing/unit-generator + test patterns
/refactor/modernize legacy.js # → refactor/modernizer + standards
# .opencode/command/security/audit.md
---
description: "Run comprehensive security audit on file"
agent: "security/auditor"
---
Run a full security audit on @$1
Include:
- Vulnerability scanning
- Dependency checks
- Secret detection
- Best practice validation
Reference project standards: @AGENTS.md
Customize builtin agents, rarely create new primary agents.
# .opencode/agent/build.md (override built-in)
---
mode: "primary"
tools:
test-runner: true
lint-check: true
---
## Testing Protocol
After code changes: use test-runner
On failure: analyze and fix
On complex failure: use Task(subagent_type="testing/test-fixer")
## Quality Checks
Before completing: lint-check
If issues: fix automatically
build, plan, general insteadUser Request
↓
Main Agent (build) - uses tools for atomic ops
↓ (if complex)
Task Tool → Subagent - specialized workflow
↓ (if needs helpers)
Task Tool → More Subagents - parallel execution
↓
Return to Main Agent
↓
User Response
User: /security/full-audit auth.ts
↓
Command loads template + context files
↓
Routes to subagent (mode: "subagent")
↓
Subagent uses tools (test-runner, lint-check)
↓
Returns focused report
.opencode/tool/
├── test.ts # Smart test runner
├── lint.ts # Filtered linter
└── deps.ts # Dependency checker
.opencode/agent/
├── security/
│ └── auditor.md # Comprehensive security
├── testing/
│ ├── generator.md # Generate tests
│ └── fixer.md # Fix failures
└── code-review/
└── reviewer.md # Code quality
.opencode/command/
├── check.md # Quick health check
├── security/
│ └── audit.md # Full security audit
└── test/
├── generate.md # Generate tests
└── fix.md # Fix failing tests
.opencode/agent/
└── build.md # Customized build agent
Is it called 10+ times/session? → YES
Does it need output filtering? → YES
Can bash do it well enough? → NO if frequently used
Is it 3+ step workflow? → YES
Does it need isolated context? → YES
Is it single atomic operation? → NO (make it a tool)
Do users type this often? → YES
Can it reuse existing subagent? → YES (just template it)
Needs new capability? → NO (build subagent first)
Do you need a new mode? → Probably NO (customize existing)
.opencode/
├── tool/
│ └── test.ts # 1 efficient test tool
├── agent/
│ ├── build.md # Customized with tool usage
│ └── code-review/
│ └── reviewer.md # 1 specialized subagent
└── command/
└── review.md # 1 user shortcut
This gives you:
.opencode/
├── tool/ [2-5 tools max]
│ ├── test.ts
│ ├── lint.ts
│ └── build.ts
├── agent/ [5-15 subagents organized by domain]
│ ├── security/
│ ├── testing/
│ ├── refactor/
│ └── documentation/
└── command/ [10-20 shortcuts]
├── security/
├── test/
└── refactor/
Week 1: Add test-runner tool
Week 2: Add code-review subagent
Week 3: Add shortcuts you use 3+ times
description: "Use AFTER writing auth code to scan for vulnerabilities"
Main agent sees this in Task tool and knows when to call it.
# Command template
@AGENTS.md # Always include standards
@.cursorrules # Always include rules
@$1 # Target file
❌ Separate tool + subagent doing same thing
✅ Tool for efficiency, subagent calls tool + adds intelligence
┌─────────────────────────────────────────┐
│ USER │
│ /security/audit auth.ts │
└──────────────┬──────────────────────────┘
│
↓
┌──────────────────────────────────────────┐
│ COMMAND (Template + Context) │
│ • Loads audit template │
│ • Attaches @auth.ts, @AGENTS.md │
│ • Routes to: security/auditor │
└──────────────┬───────────────────────────┘
│
↓
┌──────────────────────────────────────────┐
│ SUBAGENT (Specialized Workflow) │
│ • Calls lint-check tool │
│ • Calls test-runner tool │
│ • Analyzes with domain expertise │
│ • Returns focused report │
└──────────────┬───────────────────────────┘
│
↓
┌──────────────────────────────────────────┐
│ TOOLS (Efficient Operations) │
│ • lint-check: 30K chars → 200 chars │
│ • test-runner: 15K chars → 50 chars │
│ • Total context: 250 chars vs 45K │
└──────────────────────────────────────────┘
Result: 99% token savings, specialized analysis, user convenience.
mkdir -p .opencode/tool
cat > .opencode/tool/test.ts << 'EOF'
import { tool } from "@opencode-ai/plugin"
import { z } from "zod"
export default tool({
description: "Run tests, return summary or failures only",
args: { path: z.string() },
async execute(args, ctx) {
const result = await ctx.$`npm test -- ${args.path}`.nothrow()
const output = await new Response(result.stdout).text()
return result.exitCode === 0
? `✅ Tests passed`
: `❌ Failed:\n${output.split('\n').filter(l => l.includes('FAIL') || l.includes('●')).slice(0, 20).join('\n')}`
}
})
EOF
opencode tui
# Type: "run the tests"
# Agent will use your new tool
Once your tool works, add:
The Power User Formula is simple:
Start with one tool, grow organically, and always think in layers.
That's the formula. Now go build something powerful.