Create specialized agents that work together to solve complex problems
You've built an agent with tools and memory, but as requirements grow, you realize one agent trying to do everything becomes a nightmare to maintain.
Let's build a creative team: one agent writes stories, another translates them. Much simpler than customer support!
import { VoltAgent, Agent, createTool } from "@voltagent/core";
import { VercelAIProvider } from "@voltagent/vercel-ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
// Story Writer Agent
const writerAgent = new Agent({
name: "writer",
instructions: `You are a creative story writer. You write engaging short stories based on user requests.
Keep stories between 2-3 paragraphs.
Make them interesting and creative.
Always include vivid descriptions and engaging characters.`,
llm: new VercelAIProvider(),
model: openai("gpt-4o-mini"),
tools: [
createTool({
name: "save_story",
description: "Save a completed story",
parameters: z.object({
title: z.string().describe("Title of the story"),
content: z.string().describe("The story content"),
genre: z.string().describe("Genre of the story")
}),
execute: async ({ title, content, genre }) => {
console.log("Saving story:", { title, genre });
return {
storyId: "STORY-" + Date.now(),
status: "saved",
wordCount: content.split(' ').length
};
},
})
]
});
// Translator Agent
const translatorAgent = new Agent({
name: "translator",
instructions: `You are a professional translator. You translate text into multiple languages:
- German (Deutsch)
- Japanese (日本語)
- Italian (Italiano)
Provide accurate, natural translations that maintain the story's tone and meaning.`,
llm: new VercelAIProvider(),
model: openai("gpt-4o-mini"),
tools: [
createTool({
name: "save_translation",
description: "Save a translation",
parameters: z.object({
originalText: z.string().describe("Original text"),
translatedText: z.string().describe("Translated text"),
language: z.string().describe("Target language")
}),
execute: async ({ originalText, translatedText, language }) => {
console.log("Saving translation to", language);
return {
translationId: "TRANS-" + Date.now(),
language: language,
status: "saved"
};
},
})
]
});
// Creative Director - Coordinates the team
const creativeDirector = new Agent({
name: "creative-director",
instructions: `You are a creative director managing a story writing and translation team.
When users request stories:
1. First use the WRITER agent to create the story
2. Then use the TRANSLATOR agent to translate it into German, Japanese, and Italian
3. Present the original story and all translations
ALWAYS delegate - don't write stories or translate yourself.
Your job is coordination only.
Example flow:
User: "Write a story about a magic cat"
→ Use writer agent to create story
→ Use translator agent for German version
→ Use translator agent for Japanese version
→ Use translator agent for Italian version
→ Present all versions to user`,
llm: new VercelAIProvider(),
model: openai("gpt-4o-mini"),
subAgents: [writerAgent, translatorAgent],
});
new VoltAgent({
agents: {
"creative-director": creativeDirector,
writer: writerAgent,
translator: translatorAgent,
},
});
The supervisor agent automatically knows how to use subagents based on the conversation context. Here's what happens:
Let's test your customer support team in VoltOps console to see how subagents coordinate automatically.
Update your code with the story writing team (above) and save the file
Your agents will automatically reload with the new creative team configuration
Go to VoltOps Console and set userId:
userId: "writer-123"
conversationId: "creative-session"
Try these test scenarios to see immediate subagent routing:
"Write a story about a magical cat"
"Tell me a story about space adventure"
"Create a mystery story set in Victorian London"
Watch how the creative director coordinates the writer and translator agents:
Creative coordination: Story creation followed by multilingual translation
In the VoltOps console, you'll see the complete creative process:
Here are some powerful tricks from the VoltAgent docs to make your subagents even better:
Add custom rules to your creative director's behavior:
const creativeDirector = new Agent({
name: "creative-director",
subAgents: [writerAgent, translatorAgent],
// Add custom guidelines
supervisorConfig: {
customGuidelines: [
"Always ask user about preferred story genre first",
"Include word count in final response",
"Thank the team members by name",
"Offer to create illustrations for stories"
]
}
});
See exactly when tasks are handed off between agents:
const creativeDirector = new Agent({
name: "creative-director",
subAgents: [writerAgent, translatorAgent],
// Monitor delegation flow
hooks: {
onHandoff: ({ agent, source }) => {
console.log(`${source.name} → ${agent.name}`);
// Output: "creative-director → writer"
// Output: "creative-director → translator"
}
}
});
Prevent infinite loops and control complexity:
// Global step limit for all subagents
const creativeDirector = new Agent({
name: "creative-director",
subAgents: [writerAgent, translatorAgent],
maxSteps: 15 // Prevents runaway workflows
});
// Or per-request control
const response = await creativeDirector.generateText(
"Write a story about time travel",
{
maxSteps: 8, // Override for this request
userId: "user123"
}
);
Add or remove team members on the fly:
import { createSubAgent } from "@voltagent/core";
// Method 1: Traditional subAgent array
const creativeDirector = new Agent({
name: "creative-director",
subAgents: [writerAgent, translatorAgent]
});
// Method 2: Using createSubAgent function (more powerful!)
const managerAgent = new Agent({
name: "project-manager",
instructions: "Coordinate creative projects and manage team workflows",
llm: new VercelAIProvider(),
model: openai("gpt-4o-mini"),
tools: [
// This creates a tool that can delegate to writer
createSubAgent(writerAgent),
// This creates a tool that can delegate to translator
createSubAgent(translatorAgent),
// Add other business tools
createTool({
name: "schedule_meeting",
description: "Schedule team meetings",
parameters: z.object({
time: z.string(),
attendees: z.array(z.string())
}),
execute: async ({ time, attendees }) => {
return { meetingId: "MTG-" + Date.now(), scheduled: true };
}
})
]
});
// Dynamic team management
const illustratorAgent = new Agent({
name: "illustrator",
instructions: "Create visual content and illustrations"
});
// Add new team member dynamically
managerAgent.addTool(createSubAgent(illustratorAgent));
// Remove team member
managerAgent.removeTool("illustrator");
Use custom guidelines + monitoring + step control for production-ready agent teams:
Notice how our billing tools don't ask for email addresses? This is a crucial UX principle: tools should use context (userId) instead of asking users for information we already have.
context.userId
to lookup user dataHere are the key principles for designing effective agent teams:
Once you've built your agent team, test it with realistic scenarios to make sure the coordination works smoothly.
// Test the creative team
const testCreativeTeam = async () => {
console.log("Testing creative writing team...");
// Scenario 1: Simple story request
const magicalStory = await creativeDirector.generateText(
"Write a story about a magical cat",
{ userId: "writer123" }
);
// Scenario 2: Themed story
const mysteryStory = await creativeDirector.generateText(
"Create a mystery story set in Victorian London",
{ userId: "writer123" }
);
// Scenario 3: Adventure story
const spaceAdventure = await creativeDirector.generateText(
"Tell me an exciting space adventure story",
{ userId: "writer123" }
);
console.log("All creative scenarios completed!");
console.log("Each story created in English + German + Japanese + Italian!");
};
// Test individual agents
const testIndividualAgents = async () => {
// Test writer directly
const story = await writerAgent.generateText(
"Write a short story about friendship",
{ userId: "writer123" }
);
// Test translator directly
const translation = await translatorAgent.generateText(
"Translate this to German: 'Once upon a time, there was a brave knight.'",
{ userId: "writer123" }
);
};
// Run tests
testCreativeTeam();
testIndividualAgents();
In production, you can integrate your creative team into apps or websites. Here's how to call your creative director via REST API to get stories with translations.
# Story request - creative director coordinates writer + translator
curl -X POST http://localhost:3141/agents/creative-director/text \
-H "Content-Type: application/json" \
-d '{
"input": "Write a story about a magical cat",
"options": {
"userId": "writer-123",
"conversationId": "creative-session-001"
}
}'
# Themed story request - full creative workflow
curl -X POST http://localhost:3141/agents/creative-director/text \
-H "Content-Type: application/json" \
-d '{
"input": "Create a mystery story set in Victorian London",
"options": {
"userId": "writer-123",
"conversationId": "creative-session-001"
}
}'
# Adventure story - writer creates, translator translates to 3 languages
curl -X POST http://localhost:3141/agents/creative-director/text \
-H "Content-Type: application/json" \
-d '{
"input": "Tell me an exciting space adventure story",
"options": {
"userId": "writer-123",
"conversationId": "creative-session-001"
}
}'
With this creative team setup:
Congratulations! You've built a complete AI agent system with:
You now have all the tools to build production-ready AI agents. Whether you're creating a customer support system, content creation team, or something completely new, you're ready to go.