Skip to content

Adding a New Agent

This guide explains how to add a new AI agent to the pipeline.

Agent Structure

Every agent follows this interface:

typescript
// src/lib/server/ai/agents/base.ts
interface Agent<TInput, TOutput> {
  name: string
  run(input: TInput, context: PipelineContext): Promise<TOutput>
}

Step-by-Step

1. Create the Agent File

typescript
// src/lib/server/ai/agents/my-new-agent.ts
import Anthropic from '@anthropic-ai/sdk'
import { AGENT_CONFIG } from '../config'

const client = new Anthropic()

export interface MyAgentInput {
  // Define input shape
  designBrief: DesignBrief
}

export interface MyAgentOutput {
  // Define output shape
  result: string
}

export async function runMyAgent(input: MyAgentInput): Promise<MyAgentOutput> {
  const response = await client.messages.create({
    model: 'claude-opus-4-5',
    max_tokens: 4096,
    messages: [{
      role: 'user',
      content: buildPrompt(input)
    }]
  })

  return parseResponse(response.content[0].text)
}

function buildPrompt(input: MyAgentInput): string {
  return `
    Based on this design brief: ${JSON.stringify(input.designBrief)}
    
    Your task: ...
    
    Return your response as JSON with this shape: { result: string }
  `
}

function parseResponse(text: string): MyAgentOutput {
  const json = text.match(/\{[\s\S]*\}/)?.[0]
  if (!json) throw new Error('Agent returned invalid JSON')
  return JSON.parse(json)
}

2. Wire into Pipeline

typescript
// src/lib/server/ai/pipeline.ts
import { runMyAgent } from './agents/my-new-agent'

export async function runPipeline(brief: string, projectId: string) {
  // ... existing agents ...
  
  const myResult = await runMyAgent({ designBrief: brief })
  
  // Pass result forward to next agents
  const executorResult = await runExecutor({ 
    brief, 
    images,
    myResult  // ← include in context
  })
}

3. Add to API Endpoint

Update the SSE stream in src/routes/api/generate/+server.ts to emit progress for the new agent stage:

typescript
controller.enqueue(`data: ${JSON.stringify({ stage: 'my-agent', status: 'running' })}\n\n`)
const result = await runMyAgent(input)
controller.enqueue(`data: ${JSON.stringify({ stage: 'my-agent', status: 'done' })}\n\n`)

Rules

  • ✅ Always define typed input/output interfaces
  • ✅ Always pass full context forward (never strip fields)
  • ✅ Always handle JSON parse errors gracefully
  • ✅ Use AGENT_CONFIG.maxRetries for retry logic
  • ❌ Never make HTTP calls outside of Anthropic SDK
  • ❌ Never store secrets in agent files

Testing

bash
# Run agent in isolation
bun run src/lib/server/ai/agents/my-new-agent.test.ts

Create a test fixture with sample DesignBrief data and assert the output shape is correct.

Internal documentation for development team