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 callingclient.run().model: Specifies which OpenRouter model to use (e.g.,'openai/gpt-5-mini').versionandpublisher: 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 usingoutputMode: '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:
- Project root:
./.agents/my-agent.ts - Parent directory:
../.agents/my-agent.ts(useful for monorepos) - 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
$ENVvariables in MCP server configurations. - Zod validation: Optional schema validation via
validateAgents()to catch missing required fields likeidormodel.
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.tsthat defines your custom agent's identity, model, tools, prompts, and schemas. - Place agent files in any
.agentsdirectory (project root, parent, or home folder) with a default export of the definition object. - Use
loadLocalAgents()from/sdk/src/agents/load-agents.tsto discover, validate, and import custom agents with optional Zod validation. - Pass the loaded definitions to
CodebuffClient.run()along with the specific agentidto 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →