Creating Your First Agent
Create, test, and publish a simple code reviewer agent.
Video Walkthrough
Step 1: Install and Initialize
Install Codebuff globally:
npm install -g codebuff
Then navigate to your project and run:
codebuff init-agents
This creates a .agents directory with:
- Type definitions in
.agents/types/ - Example agents in
.agents/examples/ - A starter template:
.agents/my-custom-agent.ts
Typical output:
📁 Creating agent files:✓ .agents/README.md - Documentation for your agents✓ .agents/types/agent-definition.ts - TypeScript type definitions for agents✓ .agents/my-custom-agent.ts - Your first custom agent example✓ .agents/examples/01-basic-diff-reviewer.ts - Basic diff reviewer agent example
Step 2: Create Your Agent
Create a new file .agents/simple-code-reviewer.ts:
import type { AgentDefinition } from './types/agent-definition'const definition: AgentDefinition = {id: 'simple-code-reviewer',displayName: 'Simple Code Reviewer',model: 'anthropic/claude-sonnet-4.5',// Tools this agent can usetoolNames: ['read_files','run_terminal_command','code_search','spawn_agents',],// Other agents this agent can spawn// Browse https://www.codebuff.com/store to see available agentsspawnableAgents: ['codebuff/file-explorer@0.0.2'],// When should other agents spawn this one?spawnerPrompt: 'Spawn when you need to review local code changes',// System prompt defines the agent's identitysystemPrompt: `You are an expert software developer specializing in code review.Your job is to review code changes and provide helpful, constructive feedback.`,// Instructions for what the agent should doinstructionsPrompt: `Review code changes by following these steps:1. Use git diff to see what changed2. Read the modified files to understand the context3. Look for potential issues: bugs, security problems, style violations4. Suggest specific improvements with examples5. Highlight what was done well`,}export default definition
You can also ask @Bob the Agent Builder inside Codebuff for help, but building one manually first makes the pieces clearer.
Step 3: Test Your Agent Locally
Now test your agent with Codebuff:
-
Start Codebuff:
bashcodebuff -
Have Codebuff spawn your agent using the @ command:
text@Simple Code Reviewer please review my recent changes -
Watch it work:
- It runs
git diffto see changes - Reads the modified files
- Provides a review
- It runs
Make some local changes first so it has something to inspect.
Step 4: Create a Publisher Profile
Before publishing, you need a publisher profile:
-
Visit the publisher creation page:
-
Choose ownership type:
- Personal: Publish under your own name
- Organization: Publish under a team/company
-
Fill in basic information:
- Publisher Name: Your display name (e.g., "John Smith")
- Publisher ID: URL-friendly identifier (e.g., "john-smith")
- Email: Contact email (optional)
-
Add profile details:
- Bio: Brief description of yourself
- Avatar: Profile picture (optional)
-
Create your profile
Step 5: Prepare for Publishing
Add your publisher ID to your agent definition:
// Add this field to your agent definitionconst definition: AgentDefinition = {id: 'simple-code-reviewer',displayName: 'Simple Code Reviewer',publisher: 'your-publisher-id', // ← Add this linemodel: 'anthropic/claude-sonnet-4.5',// ... rest of your definition}
Replace 'your-publisher-id' with the ID you created in Step 4.
Step 6: Publish Your Agent
Publish your agent to the Codebuff store:
codebuff publish simple-code-reviewer
You should see:
Publishing:- Simple Code Reviewer (simple-code-reviewer)✅ Successfully published:- Simple Code Reviewer (your-publisher-id/simple-code-reviewer@1.0.0)
Step 7: Test Your Published Agent
Now anyone can use your agent:
codebuff --agent your-publisher-id/simple-code-reviewer@0.0.1
Advanced Example: Deep Code Reviewer
Once the basics work, try handleSteps for programmatic control. The agent below shows one way to structure it:
.agents/deep-code-reviewer.ts:
import type { AgentDefinition } from './types/agent-definition'const definition: AgentDefinition = {id: 'deep-code-reviewer',displayName: 'Deep Code Reviewer',publisher: 'your-publisher-id',model: 'anthropic/claude-sonnet-4.5',spawnerPrompt:'Spawn when you need to review code changes in the git diff or staged changes',toolNames: ['read_files','code_search','run_terminal_command','spawn_agents',],// Use fully qualified agent names with publisher and version// Browse https://www.codebuff.com/store to see available agentsspawnableAgents: ['codebuff/file-explorer@0.0.4','codebuff/deep-thinker@0.0.3',],instructionsPrompt: `Review code changes comprehensively:1. Analyze git diff and untracked files2. Find related files using file explorer3. Use multiple perspectives for thorough review4. Look for simplification opportunities5. Check for logical errors and edge cases`,handleSteps: function* () {// Step 1: Get changed files from gitconst { toolResult: gitDiffResult } = yield {toolName: 'run_terminal_command',input: { command: 'git diff HEAD --name-only' },}// Step 2: Get untracked filesconst { toolResult: gitStatusResult } = yield {toolName: 'run_terminal_command',input: { command: 'git status --porcelain' },}// Step 3: Show the actual diffyield {toolName: 'run_terminal_command',input: { command: 'git diff HEAD' },}// Step 4: Parse file paths (with error handling)const changedFiles = (gitDiffResult || '').split('\n').map((line) => line.trim()).filter((line) => line && !line.includes('OSC'))const untrackedFiles = (gitStatusResult || '').split('\n').filter((line) => line.startsWith('??')).map((line) => line.substring(3).trim()).filter((file) => file)const allFiles = [...changedFiles, ...untrackedFiles]// Step 5: Read all the filesif (allFiles.length > 0) {yield {toolName: 'read_files',input: { paths: allFiles },}}// Step 6: Spawn file explorer to find related filesyield {toolName: 'spawn_agents',input: {agents: [{agent_type: 'codebuff/file-explorer@0.0.1',prompt: 'Find files related to the changed code',},],},}// Step 7: Let the LLM generate the final reviewyield 'STEP_ALL'},}export default definition
Understanding handleSteps
The handleSteps generator function gives you direct control over your agent's execution:
Key Concepts:
-
yieldtool calls: Execute tools and get resultstypescriptconst { toolResult, toolError } = yield {toolName: 'run_terminal_command',input: { command: 'git status' }} -
yield 'STEP_ALL': Let the LLM take over and generate responsestypescriptyield 'STEP_ALL' // LLM runs until completion -
yield 'STEP': Let the LLM take one step, then return controltypescriptyield 'STEP' // LLM takes one turn, then back to your code -
return: End the agent's execution immediatelytypescriptreturn // Agent stops here
When to Use Programmatic Control:
- Complex workflows with multiple steps
- Conditional logic based on file contents
- Error handling for tool failures
- Dynamic agent spawning based on analysis
- Data transformation between steps
When to Use Simple Prompts:
- Straightforward tasks with clear instructions
- Creative tasks that benefit from LLM flexibility
- Quick prototypes that don't need complex logic
Spawnable Agents
Agents can spawn other agents for specific tasks.
Agent Store vs Local Agents
Agent Store Agents (Use Fully Qualified IDs):
When spawning agents from the Codebuff Agent Store, always use the full publisher/agent-name@version format:
spawnableAgents: ['codebuff/file-explorer@0.0.4', // ✅ Correct'john-smith/security-scanner@2.1.4', // ✅ Correct]
Local Agents (Use Simple IDs):
When spawning agents defined in your own .agents directory, use just the agent ID:
spawnableAgents: ['my-custom-reviewer', // ✅ Correct for local agent'database-migrator', // ✅ Correct for local agent'codebuff/file-explorer@0.0.4', // ✅ Also correct: you can mix local and published agents.]
You now have a published agent, a pattern for using handleSteps, and the basics for spawning other agents.