
Designing a Multi-Agent Swarm with Vercel AI SDK for Complex Workflows
Single-prompt chatbots are dead. Learn how to orchestrate a 'Swarm' of specialized agents that seamlessly hand off tasks and state to each other using the AI SDK's tool-calling capabilities.
Summary
TL;DR: Complex workflows require specialized agents. This guide details how to build a Multi-Agent Swarm where specialized Vercel AI SDK agents hand off tasks and state to one another via native tool-calling.
If you try to make one massive Large Language Model do everything—researching, coding, planning, reviewing, and formatting—it will fail. It will get confused, lose context, hallucinate, and output generic slop.
Human engineering teams do not work like this. A team has specialized roles: a Product Manager writes the spec, a Developer writes the code, and a QA Engineer reviews it.
We can replicate this architecture in software using a Multi-Agent Swarm. Instead of one monolithic prompt, we create multiple independent agents, each with a narrow system prompt and specialized tools. We then use the Vercel AI SDK to allow these agents to talk to each other and hand off tasks.
In this comprehensive tutorial, we will build a Swarm consisting of three agents: a Triage Router, a Web Researcher, and a Copywriter.
| Architecture | Context Window | Accuracy on Complex Tasks | Ease of Debugging |
|---|---|---|---|
| Monolithic God-Agent | Polluted with unrelated tools | Low | Very Hard |
| Multi-Agent Swarm | Clean (only relevant tools) | Extremely High | Easy (Traceable handoffs) |
The Handoff Architecture
The core mechanic of a Swarm is the "handoff."
An agent is just an LLM wrapped with a specific set of tools. To allow Agent A to hand off work to Agent B, we simply give Agent A a tool called transfer_to_agent_B. When the LLM decides to use this tool, it passes its output as an argument. Our backend catches that tool call, suspends Agent A, and instantly boots up Agent B using that argument as the new input prompt.
Let's build this using the Vercel AI SDK.
Step 1: Defining the Agents
First, we need to define the personalities and capabilities of our Swarm members. We will define them as simple objects containing a system prompt and a model configuration.
import { openai } from '@ai-sdk/openai';
// Define the configurations for our specialized agents
const AGENTS = {
Triage: {
model: openai('gpt-4o-mini'), // Fast, cheap model for routing
system: `You are the Triage Agent. Your only job is to route the user's request to the correct specialist.
If the user wants recent information, transfer them to the Researcher.
If the user wants marketing copy or an essay written, transfer them to the Copywriter.`
},
Researcher: {
model: openai('gpt-4o'), // Smarter model for complex tool use
system: `You are an elite Web Researcher. You have access to search the web.
Find accurate, factual information to answer the user's query.`
},
Copywriter: {
model: openai('gpt-4o'),
system: `You are an expert Copywriter. You write engaging, highly persuasive marketing copy.
Take any research provided to you and format it into a stunning blog post.`
}
};
Step 2: Creating the Tools
The Researcher agent needs actual tools to do its job. We will mock a web search tool for this tutorial (in production, use Tavily or Exa).
import { tool } from 'ai';
import { z } from 'zod';
const researcherTools = {
search_web: tool({
description: 'Search the internet for current information.',
parameters: z.object({ query: z.string() }),
execute: async ({ query }) => {
console.log(`[Researcher] Searching web for: ${query}`);
// Mock search result
return `Results for ${query}: The Vercel AI SDK v7 introduced durable Workflow agents and OpenTelemetry support in 2026.`;
}
})
};
Step 3: Building the Handoff Mechanism
Now for the critical part. We need to define tools that exist purely to transfer control from one agent to another.
We will create a helper function that returns a Vercel AI SDK tool which, when executed, throws a special "Handoff Exception" or returns a specific control payload that our main loop can catch.
type HandoffSignal = {
type: 'HANDOFF';
targetAgent: keyof typeof AGENTS;
context: string;
};
// This helper creates a tool that an agent can call to transfer control
function createHandoffTool(targetAgent: keyof typeof AGENTS, description: string) {
return tool({
description,
parameters: z.object({
context: z.string().describe("The information and instructions to pass to the next agent.")
}),
execute: async ({ context }): Promise<HandoffSignal> => {
console.log(`\n>>> Transferring control to ${targetAgent}...`);
// We return a structured signal that the outer loop will interpret
return { type: 'HANDOFF', targetAgent, context };
}
});
}
Now we equip the agents with their transfer tools:
const triageTools = {
transfer_to_researcher: createHandoffTool('Researcher', 'Transfer the user to the Web Researcher to find factual information.'),
transfer_to_copywriter: createHandoffTool('Copywriter', 'Transfer the user to the Copywriter to write marketing text.')
};
const researcherHandoffTools = {
transfer_to_copywriter: createHandoffTool('Copywriter', 'Transfer your research findings to the Copywriter to format them into an article.')
};
Step 4: The Swarm Orchestrator Loop
We need an orchestrator function that runs the Vercel AI SDK generateText. When it detects a HANDOFF signal returned from a tool call, it switches the active agent and recursively calls generateText again.
import { generateText, CoreMessage } from 'ai';
async function runSwarm(initialPrompt: string) {
let currentAgentName: keyof typeof AGENTS = 'Triage';
let messages: CoreMessage[] = [{ role: 'user', content: initialPrompt }];
console.log(`\n[User]: ${initialPrompt}`);
// The infinite orchestration loop
while (true) {
const activeAgent = AGENTS[currentAgentName];
// Determine which tools the active agent has access to
let activeTools = {};
if (currentAgentName === 'Triage') activeTools = triageTools;
if (currentAgentName === 'Researcher') activeTools = { ...researcherTools, ...researcherHandoffTools };
// Copywriter has no handoff tools; it is the end of the line
console.log(`\n--- Active Agent: ${currentAgentName} ---`);
const result = await generateText({
model: activeAgent.model,
system: activeAgent.system,
messages: messages,
tools: activeTools,
maxSteps: 5, // Allow the agent to use standard tools multiple times
});
// Check if the agent called a handoff tool
const handoffToolCall = result.toolResults.find(
(tr) => (tr.result as any)?.type === 'HANDOFF'
);
if (handoffToolCall) {
const signal = handoffToolCall.result as HandoffSignal;
// Save the transition in the chat history
messages.push({
role: 'assistant',
content: `I am transferring this task to the ${signal.targetAgent}. Context provided: ${signal.context}`
});
// Switch the active agent and loop again!
currentAgentName = signal.targetAgent;
continue;
}
// If no handoff was triggered, the agent is finished communicating
console.log(`\n[${currentAgentName} Final Output]:\n${result.text}`);
break;
}
}
Step 5: Execution
Let's test the Swarm with a complex request that requires both research and writing.
async function main() {
await runSwarm("Find out what features were released in Vercel AI SDK v7, and write a hyped-up marketing tweet about it.");
}
main();
If you watch the terminal output when this runs, you will see a fascinating chain of events:
- The Triage Agent boots up, reads the prompt, and realizes it requires research. It calls
transfer_to_researcher. - The orchestrator catches the signal and boots the Researcher Agent.
- The Researcher reads the history, calls
search_web, reads the results about "v7 Durable Workflows", and then callstransfer_to_copywriter. - The orchestrator boots the Copywriter Agent.
- The Copywriter reads the research context, generates a highly persuasive marketing tweet, and returns the final text since it has no transfer tools.
Why Swarms Win
This architecture is robust because it prevents context pollution. The Copywriter agent's system prompt doesn't need instructions about how to search the web or route traffic. It just focuses on writing.
By using the Vercel AI SDK's native tool-calling feature to orchestrate these handoffs, you avoid building complex state machines or relying on heavy frameworks like AutoGen. You maintain complete control over the execution flow, state, and API costs in pure TypeScript.
When you build complex AI applications, don't build one massive god-agent. Build a team.
Frequently Asked Questions (FAQ)
What is a Multi-Agent Swarm? A Swarm is an architecture where multiple LLMs with narrow, specialized prompts (e.g., a Researcher, a Coder, a Planner) collaborate to solve a problem, rather than relying on one massive monolithic agent.
How do agents communicate in Vercel AI SDK?
Agents communicate by calling specialized handoff tools (e.g., transfer_to_researcher). The orchestrator catches this tool execution, suspends the current agent, and boots up the target agent using the tool's arguments as the new context.
Is LangChain required to build multi-agent systems?
No. The Vercel AI SDK provides all the necessary primitives (like generateText, tool calling, and maxSteps) to build robust, type-safe multi-agent swarms in pure TypeScript without the overhead of heavy frameworks.
Related reading
Learn how to architect your AI applications to avoid LLM vendor lock-in. Discover strategies for migrating from OpenAI to self-hosted models like Llama 3.
Use Eve.dev's multi-agent orchestration to build an accounts-payable pipeline: a supervisor delegates invoice extraction, 3-way matching, and durable approvals.
Discover how to build an AI sales assistant that scores leads, crafts personalized emails, and uses durable wait states to manage multi-day follow-up sequences using Eve.dev.
Let's build something great.
Have a project in mind? We are an elite software and AI development studio ready to bring your ideas to production. Let's talk about your roadmap.