How to Create Custom Agents Using AgentDefinition in Codebuff: A Complete Guide

You create custom agents in Codebuff by exporting an AgentDefinition object from a TypeScript file placed in any .agents directory, then loading it with loadLocalAgents() and passing it to CodebuffClient.run().

Codebuff is an open-source AI assistant framework that allows you to extend its capabilities by creating custom agents using the AgentDefinition interface. These agents are plain TypeScript modules that define specialized behavior, tool access, and structured output schemas, enabling you to build tailored AI workflows that integrate seamlessly with the Codebuff ecosystem.

Understanding the AgentDefinition Interface

The AgentDefinition interface in /.agents/types/agent-definition.ts serves as the contract between your custom agent and the Codebuff runtime. It defines every configurable aspect of agent behavior, from identity to output formatting.

Core Identity and Model Configuration

Every agent requires a unique identity and model specification:

  • id: A unique string identifier used to reference the agent when calling client.run().
  • model: Specifies which OpenRouter model to use (e.g., 'openai/gpt-5-mini').
  • version and publisher: Optional metadata for versioning and attribution.
  • displayName: Human-readable name shown in UIs.

Tools, Prompts, and Schemas

The interface allows precise control over agent capabilities and behavior:

  • toolNames: An array of tools the agent can invoke (e.g., ['read_files', 'set_output']).
  • systemPrompt: The base personality and role definition for the agent.
  • instructionsPrompt: Specific task instructions provided to guide execution.
  • inputSchema: Zod-compatible schema defining expected input parameters.
  • outputSchema: Structure definition for the agent's response when using outputMode: 'structured_output'.
  • handleSteps: Optional generator function for programmatic step orchestration.

Where to Place Your Custom Agent Files

Codebuff discovers custom agents through a convention-based directory structure. You must place your agent definition files within a .agents folder using TypeScript or JavaScript.

Valid locations include:

  1. Project root: ./.agents/my-agent.ts
  2. Parent directory: ../.agents/my-agent.ts (useful for monorepos)
  3. Global directory: ~/.agents/my-agent.ts (user-wide agents)

The file must export a default object conforming to AgentDefinition:

// .agents/my-agent.ts
import type { AgentDefinition } from './types/agent-definition'

export const definition: AgentDefinition = {
  id: 'my-agent',
  model: 'openai/gpt-5-mini',
  systemPrompt: 'You are a specialized file analyzer.',
  toolNames: ['read_files'],
  outputMode: 'structured_output',
  outputSchema: {
    type: 'object',
    properties: {
      summary: { type: 'string' }
    }
  }
}

export default definition

Loading and Validating Custom Agents

Before running your agent, you must load and validate the definitions using the SDK utilities in /sdk/src/agents/load-agents.ts.

The loadLocalAgents() function handles the complete lifecycle:

import { loadLocalAgents } from '@codebuff/sdk/agents'

async function initializeAgents() {
  // Scan default directories, validate with Zod, resolve $ENV references
  const { agents, errors } = await loadLocalAgents({ 
    validate: true, 
    verbose: true 
  })
  
  if (errors.length > 0) {
    console.error('Validation failed:', errors)
    process.exit(1)
  }
  
  // agents is Record<string, LoadedAgentDefinition>
  return Object.values(agents)
}

Key loading behaviors:

  • Directory discovery: Automatically checks process.cwd()/.agents, ../.agents, and ~/.agents.
  • Dynamic imports: Uses cache-busting query strings to ensure edits reload instantly during development.
  • Environment resolution: Substitutes $ENV variables in MCP server configurations.
  • Zod validation: Optional schema validation via validateAgents() to catch missing required fields like id or model.

Running Your Custom Agent with CodebuffClient

Once loaded, pass your custom agent definitions to CodebuffClient.run() located in /sdk/src/client.ts.

import { CodebuffClient } from '@codebuff/sdk'
import { loadLocalAgents } from '@codebuff/sdk/agents'

async function main() {
  // Load custom definitions
  const { agents } = await loadLocalAgents({ validate: true })
  const agentDefinitions = Object.values(agents)

  // Initialize client
  const client = new CodebuffClient({ 
    apiKey: process.env.CODEBUFF_API_KEY 
  })

  // Execute the custom agent
  const result = await client.run({
    agent: 'my-agent',           // Must match the id in AgentDefinition
    prompt: 'Summarize README.md',
    agentDefinitions,            // Inject custom agents into the runtime
    handleEvent: (event) => {
      console.log('Event:', event.type, event.data)
    }
  })

  console.log('Output:', result.output)
}

main().catch(console.error)

The run() method merges your custom definitions with the client's default configuration and forwards the request to the Codebuff backend. The backend instantiates your agent with the specified model, prompts, and tool access, then streams events back through the handleEvent callback.

Summary

  • AgentDefinition is the TypeScript interface in /.agents/types/agent-definition.ts that defines your custom agent's identity, model, tools, prompts, and schemas.
  • Place agent files in any .agents directory (project root, parent, or home folder) with a default export of the definition object.
  • Use loadLocalAgents() from /sdk/src/agents/load-agents.ts to discover, validate, and import custom agents with optional Zod validation.
  • Pass the loaded definitions to CodebuffClient.run() along with the specific agent id to execute your custom logic with structured output support.

Frequently Asked Questions

What fields are required in an AgentDefinition?

At minimum, you must provide an id (unique string identifier) and a model (OpenRouter model name like 'openai/gpt-5-mini'). The loadLocalAgents() function in /sdk/src/agents/load-agents.ts explicitly validates these required fields before loading the definition into the runtime.

Can I use environment variables in my agent configuration?

Yes. The loading system supports $ENV variable substitution in MCP server configurations and other string values. When loadLocalAgents() processes your definition files, it resolves these environment references automatically, allowing you to keep sensitive values like API keys out of your agent source code.

How do I enforce structured output from my custom agent?

Set outputMode: 'structured_output' in your AgentDefinition and provide a valid JSON Schema object in the outputSchema field. When you run the agent via CodebuffClient.run(), the backend constrains the model to return valid JSON matching your schema, which appears in the result.output field as a parsed object.

Where should I place my custom agent files for the SDK to find them?

The SDK searches three default locations: a .agents folder in your current working directory (process.cwd()/.agents), a .agents folder in the parent directory (../.agents), and a global .agents folder in your home directory (~/.agents). You can also specify custom paths by passing a dirs array to loadLocalAgents().

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →