This guide covers everything you need to know about building custom Codebuff agents.
Each agent is a TypeScript file that exports an AgentDefinition object:
export default {
id: 'my-agent', // Unique identifier (lowercase, hyphens only)
displayName: 'My Agent', // Human-readable name
model: 'claude-3-5-sonnet', // AI model to use
toolNames: ['read_files', 'write_file'], // Available tools
instructionsPrompt: 'You are...', // Agent behavior instructions
spawnerPrompt: 'Use this agent when...', // When others should spawn this
spawnableAgents: ['helper-agent'], // Agents this can spawn
// Optional: Programmatic control
async *handleSteps() {
yield { tool: 'read_files', paths: ['src/config.ts'] }
yield 'STEP' // Let AI process and respond
}
}id: Unique identifier using lowercase letters and hyphens onlydisplayName: Human-readable name shown in UImodel: AI model from OpenRouter (see available models)instructionsPrompt: Detailed instructions defining the agent's role and behavior
toolNames: Array of tools the agent can use (defaults to common tools)spawnerPrompt: Instructions for when other agents should spawn this onespawnableAgents: Array of agent names this agent can spawnhandleSteps: Generator function for programmatic control
read_files: Read file contentswrite_file: Create or modify entire filesstr_replace: Make targeted string replacementscode_search: Search for patterns across the codebase
run_terminal_command: Execute shell commandsspawn_agents: Delegate tasks to other agentsend_turn: Finish the agent's response
web_search: Search the internet for informationread_docs: Read technical documentationbrowser_logs: Navigate and inspect web pages
See types/tools.ts for detailed parameter information.
Use the handleSteps generator function to mix AI reasoning with programmatic logic:
async *handleSteps() {
// Execute a tool
yield { tool: 'read_files', paths: ['package.json'] }
// Let AI process results and respond
yield 'STEP'
// Conditional logic
if (needsMoreAnalysis) {
yield { tool: 'spawn_agents', agents: ['deep-analyzer'] }
yield 'STEP_ALL' // Wait for spawned agents to complete
}
// Final AI response
yield 'STEP'
}'STEP': Let AI process and respond once'STEP_ALL': Let AI continue until completion- Tool calls:
{ tool: 'tool_name', ...params }
Choose models based on your agent's needs:
claude-3-5-sonnet: Best for complex reasoning and code generationgpt-4: Strong general-purpose capabilitiesclaude-3-haiku: Fast and cost-effective for simple tasksgemini-pro: Good for analysis and research tasks
See OpenRouter for all available models and pricing.
Agents can spawn other agents to create sophisticated workflows:
// Parent agent spawns specialists
async *handleSteps() {
yield { tool: 'spawn_agents', agents: [
'security-scanner',
'performance-analyzer',
'code-reviewer'
]}
yield 'STEP_ALL' // Wait for all to complete
// Synthesize results
yield 'STEP'
}- Be specific about the agent's role and expertise
- Include examples of good outputs
- Specify when the agent should ask for clarification
- Define the agent's limitations
- Start with file exploration tools (
read_files,code_search) - Use
str_replacefor targeted edits,write_filefor major changes - Always use
end_turnto finish responses cleanly
- Include error checking in programmatic flows
- Provide fallback strategies for failed operations
- Log important decisions for debugging
- Choose appropriate models for the task complexity
- Minimize unnecessary tool calls
- Use spawnable agents for parallel processing
- Local Testing:
codebuff --agent your-agent-name - Debug Mode: Add logging to your
handleStepsfunction - Unit Testing: Test individual functions in isolation
- Integration Testing: Test agent coordination workflows
- Validate: Ensure your agent works across different codebases
- Document: Include clear usage instructions
- Publish:
codebuff publish your-agent-name - Maintain: Update as models and tools evolve
async *handleSteps() {
const config = yield { tool: 'read_files', paths: ['config.json'] }
yield 'STEP'
if (config.includes('typescript')) {
yield { tool: 'spawn_agents', agents: ['typescript-expert'] }
} else {
yield { tool: 'spawn_agents', agents: ['javascript-expert'] }
}
yield 'STEP_ALL'
}async *handleSteps() {
for (let attempt = 0; attempt < 3; attempt++) {
yield { tool: 'run_terminal_command', command: 'npm test' }
yield 'STEP'
if (allTestsPass) break
yield { tool: 'spawn_agents', agents: ['test-fixer'] }
yield 'STEP_ALL'
}
}- Agent not spawning: Check the
idformat (lowercase, hyphens only) - Tool errors: Verify tool parameters match the expected schema
- Infinite loops: Always include exit conditions in loops
- Memory issues: Avoid storing large objects in generator state
- Use
console.loginhandleStepsfor debugging - Test individual tool calls before adding to workflows
- Start simple and add complexity gradually
- Discord: Join our community for help and inspiration
- Examples: Study the
examples/directory for patterns - Documentation: Check
types/for detailed type information - Issues: Report bugs and request features on GitHub
Happy agent building! 🤖