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

> Learn to create custom agents in Codebuff using AgentDefinition. Export, load, and run your own agents with this complete guide.

- Repository: [Codebuff/codebuff](https://github.com/CodebuffAI/codebuff)
- Tags: how-to-guide
- Published: 2026-03-08

---

**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`](https://github.com/CodebuffAI/codebuff/blob/main//.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`](https://github.com/CodebuffAI/codebuff/blob/main/./.agents/my-agent.ts)
2. **Parent directory**: [`../.agents/my-agent.ts`](https://github.com/CodebuffAI/codebuff/blob/main/../.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`:

```typescript
// .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`](https://github.com/CodebuffAI/codebuff/blob/main//sdk/src/agents/load-agents.ts).

The `loadLocalAgents()` function handles the complete lifecycle:

```typescript
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`](https://github.com/CodebuffAI/codebuff/blob/main//sdk/src/client.ts).

```typescript
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`](https://github.com/CodebuffAI/codebuff/blob/main//.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`](https://github.com/CodebuffAI/codebuff/blob/main//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`](https://github.com/CodebuffAI/codebuff/blob/main//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()`.