kritsana.devpassing
runartifactsdocsworkhistorydispatch

© 2026 Kritsana Prasit — built from source on a self-hosted runner

resume.pdfrssdispatch

back to artifacts
category: aidate: 06 Apr 2026read: 6 min readsource: posts/building-sub-agents.mdxfeatured

Building Sub-Agents: How to Design Multi-Agent AI Systems

Learn how to architect and build sub-agent systems — breaking complex AI tasks into specialized agents that collaborate, delegate, and deliver better results.

Building Sub-Agents: How to Design Multi-Agent AI Systems

As AI agents grow more capable, the tasks we assign them grow more complex. A single monolithic agent often struggles with multi-step workflows that require different expertise at each stage. The solution? Sub-agents — specialized agents that each handle one part of the problem, coordinated by a parent agent.

This guide covers the architecture, patterns, and practical implementation of sub-agent systems.

What is a Sub-Agent?

A sub-agent is a specialized AI agent that is invoked by a parent (orchestrator) agent to handle a specific subtask. Think of it like a team lead delegating work:

  • Orchestrator Agent — receives the user's request, breaks it into subtasks, and delegates
  • Sub-Agent A — handles research and information gathering
  • Sub-Agent B — handles code generation
  • Sub-Agent C — handles review and quality assurance

Each sub-agent can have its own system prompt, tools, context window, and even a different model.

Why Use Sub-Agents?

| Single Agent | Multi-Agent | | ----------------------------------- | --------------------------------------------- | | One system prompt for everything | Specialized prompts per task | | Single context window fills up fast | Each agent gets a fresh context | | One model for all tasks | Use cheaper models for simple tasks | | Hard to debug failures | Isolate failures to specific agents | | Difficult to extend | Add new agents without changing existing ones |

Architecture Patterns

Pattern 1: Sequential Pipeline

Agents execute in a fixed order, each passing output to the next.

plaintext
User Request
     ↓
[Research Agent]
     ↓
[Writer Agent]
     ↓
[Editor Agent]
     ↓
Final Output
typescript
async function sequentialPipeline(userRequest: string) {
  // Step 1: Research
  const research = await researchAgent.execute({
    task: `Research the following topic: ${userRequest}`,
    tools: ['web_search', 'read_url'],
  });
 
  // Step 2: Write
  const draft = await writerAgent.execute({
    task: `Write an article based on this research: ${research.output}`,
    tools: ['file_write'],
  });
 
  // Step 3: Edit
  const final = await editorAgent.execute({
    task: `Review and improve this draft: ${draft.output}`,
    tools: ['file_edit'],
  });
 
  return final.output;
}

Pattern 2: Parallel Fan-Out

The orchestrator dispatches independent subtasks simultaneously.

plaintext
User Request
     ↓
[Orchestrator]
     ├─→ [Frontend Agent] ─┐
     ├─→ [Backend Agent] ──┤
     └─→ [Test Agent] ─────┤
                           ↓
                      [Merge Agent]
                           ↓
                         Output
typescript
async function parallelFanOut(userRequest: string) {
  const plan = await orchestrator.plan(userRequest);
 
  // Execute independent tasks in parallel
  const results = await Promise.all([
    frontendAgent.execute(plan.frontendTask),
    backendAgent.execute(plan.backendTask),
    testAgent.execute(plan.testTask),
  ]);
 
  // Merge results
  const merged = await mergeAgent.execute({
    task: 'Combine these outputs into a cohesive result',
    context: results.map(r => r.output),
  });
 
  return merged.output;
}

Pattern 3: Router (Dynamic Dispatch)

The orchestrator analyzes the request and routes to the appropriate agent.

typescript
async function routerPattern(userRequest: string) {
  // Classify the request
  const classification = await orchestrator.classify(userRequest);
 
  // Route to the right specialist
  switch (classification.type) {
    case 'code_generation':
      return codeAgent.execute(userRequest);
    case 'data_analysis':
      return dataAgent.execute(userRequest);
    case 'documentation':
      return docAgent.execute(userRequest);
    default:
      return generalAgent.execute(userRequest);
  }
}

Pattern 4: Supervisor Loop

The orchestrator iteratively delegates and reviews until quality criteria are met.

typescript
async function supervisorLoop(userRequest: string) {
  let result = await workerAgent.execute(userRequest);
  let approved = false;
  let iterations = 0;
  const maxIterations = 3;
 
  while (!approved && iterations < maxIterations) {
    const review = await reviewerAgent.evaluate(result.output);
 
    if (review.score >= 0.9) {
      approved = true;
    } else {
      result = await workerAgent.execute({
        task: userRequest,
        feedback: review.feedback,
        previousAttempt: result.output,
      });
    }
    iterations++;
  }
 
  return result.output;
}

Implementing a Sub-Agent System

Here is a minimal but practical implementation using TypeScript:

Define the Agent Interface

typescript
interface AgentConfig {
  name: string;
  model: string;
  systemPrompt: string;
  tools: Tool[];
  maxTokens?: number;
}
 
interface AgentResult {
  output: string;
  tokensUsed: number;
  toolCalls: ToolCall[];
}
 
class SubAgent {
  private config: AgentConfig;
 
  constructor(config: AgentConfig) {
    this.config = config;
  }
 
  async execute(input: string): Promise<AgentResult> {
    const response = await llm.chat({
      model: this.config.model,
      system: this.config.systemPrompt,
      messages: [{ role: 'user', content: input }],
      tools: this.config.tools,
      maxTokens: this.config.maxTokens ?? 4096,
    });
 
    return {
      output: response.content,
      tokensUsed: response.usage.totalTokens,
      toolCalls: response.toolCalls,
    };
  }
}

Create Specialized Agents

typescript
const researchAgent = new SubAgent({
  name: 'researcher',
  model: 'claude-4-5-sonnet-20260101',
  systemPrompt: `You are a research specialist. Your job is to gather 
    accurate, relevant information on a given topic. Always cite sources 
    and distinguish facts from opinions.`,
  tools: [webSearchTool, urlReaderTool],
});
 
const codeAgent = new SubAgent({
  name: 'coder',
  model: 'claude-4-5-sonnet-20260101',
  systemPrompt: `You are a senior software engineer. Write clean, 
    well-tested, production-ready code. Follow best practices and 
    include error handling.`,
  tools: [fileReadTool, fileWriteTool, terminalTool],
});
 
const reviewAgent = new SubAgent({
  name: 'reviewer',
  model: 'claude-4-5-haiku-20260101', // Cheaper model for review
  systemPrompt: `You are a code reviewer. Check for bugs, security 
    issues, and style violations. Be concise and actionable.`,
  tools: [fileReadTool],
});

Build the Orchestrator

typescript
class Orchestrator {
  private agents: Map<string, SubAgent>;
 
  constructor() {
    this.agents = new Map();
  }
 
  registerAgent(name: string, agent: SubAgent) {
    this.agents.set(name, agent);
  }
 
  async run(task: string): Promise<string> {
    // Step 1: Plan
    const plan = await this.planTask(task);
 
    // Step 2: Execute sub-tasks
    const results: string[] = [];
    for (const step of plan.steps) {
      const agent = this.agents.get(step.agentName);
      if (!agent) throw new Error(`Agent ${step.agentName} not found`);
 
      const result = await agent.execute(step.instruction);
      results.push(`[${step.agentName}]: ${result.output}`);
    }
 
    // Step 3: Synthesize
    return results.join('\n\n');
  }
 
  private async planTask(task: string) {
    // Use LLM to decompose the task
    const response = await llm.chat({
      model: 'claude-4-5-haiku-20260101',
      system: 'Decompose this task into steps. Return JSON.',
      messages: [{ role: 'user', content: task }],
    });
 
    return JSON.parse(response.content);
  }
}

Best Practices

1. Keep Agents Focused

Each sub-agent should do one thing well. If an agent's system prompt exceeds a paragraph, consider splitting it.

2. Use the Right Model for the Job

Not every subtask needs the most powerful model:

  • Planning/Orchestration — use a strong model (Sonnet, GPT-4o)
  • Simple classification — use a fast model (Haiku, GPT-4o-mini)
  • Code generation — use a code-specialized model

3. Limit Context Passing

Only pass relevant output between agents. Sending entire conversation histories wastes tokens and dilutes focus.

4. Add Error Boundaries

typescript
async function safeExecute(agent: SubAgent, input: string) {
  try {
    return await agent.execute(input);
  } catch (error) {
    console.error(`Agent ${agent.name} failed:`, error);
    return { output: `Error: ${error.message}`, tokensUsed: 0, toolCalls: [] };
  }
}

5. Log Everything

Track which agent handled what, how many tokens were used, and what tools were called. This is essential for debugging and cost optimization.

Wrapping Up

Sub-agent architectures let you decompose complex AI tasks into manageable, specialized units. Whether you use a sequential pipeline, parallel fan-out, router, or supervisor loop depends on your specific use case.

Start simple with two agents (worker + reviewer), measure the results, and scale up as needed. The key is to treat each agent as a composable building block — focused, testable, and replaceable.

contents

  • What is a Sub-Agent?
  • Why Use Sub-Agents?
  • Architecture Patterns
  • Pattern 1: Sequential Pipeline
  • Pattern 2: Parallel Fan-Out
  • Pattern 3: Router (Dynamic Dispatch)
  • Pattern 4: Supervisor Loop
  • Implementing a Sub-Agent System
  • Define the Agent Interface
  • Create Specialized Agents
  • Build the Orchestrator
  • Best Practices
  • 1. Keep Agents Focused
  • 2. Use the Right Model for the Job
  • 3. Limit Context Passing
  • 4. Add Error Boundaries
  • 5. Log Everything
  • Wrapping Up

related documents

ai · 3
  • Developer ในยุค AI ในมุมของผม: งานไม่ได้หายไป แค่ย้ายจาก "พิมพ์โค้ด" ไป "ตัดสินใจและรับผิดชอบ"

    16 Nov 2026 · 2 min read

  • สรุป: เปลี่ยน Grokbot ให้เป็นระบบ Multi-Agent 300 ตัวด้วย Kimi K3

    15 Nov 2026 · 3 min read

  • Gemini 4 Hydrogen: โมเดลที่ทำงานเร็วและราคาถูกสำหรับ agent workflow และการสลับโมเดลกลางคัน

    13 Nov 2026 · 4 min read

comments