Skip to content

Tutorial 2: Multi-Agent Collaboration

⏱️ Time: 30 minutes | 🎯 Goal: Build a researcher-writer team

Now let’s create a team of agents that work together! You’ll build a system where XAgent coordinates specialist agents β€” a researcher gathers information and a writer creates content. This introduces the powerful concept of multi-agent collaboration.

  • How XAgent coordinates specialist agents
  • Using different agent modes
  • Building collaborative workflows
  • Managing multi-step tasks

In Viber, XAgent acts as the project manager. It coordinates specialist agents:

User β†’ XAgent β†’ [Researcher, Writer, Developer, ...]
↓
Task Completion

The specialist agents include:

AgentRole
ResearcherGathers information and sources
WriterCreates content and documentation
DeveloperWrites and reviews code
ReviewerProvides quality assurance
Web DesignerCreates HTML/CSS experiences

Create a new project:

Terminal window
mkdir research-writer-team
cd research-writer-team
pnpm init
pnpm add viber dotenv
pnpm add -D typescript tsx @types/node

Create your project structure:

research-writer-team/
β”œβ”€β”€ src/
β”‚ └── index.ts # Main application
β”œβ”€β”€ .env # API key
β”œβ”€β”€ package.json
└── tsconfig.json

Create src/index.ts:

import "dotenv/config";
import { XAgent } from "viber";
async function main() {
console.log("✍️ Research & Writing Team Demo");
console.log("Watch as XAgent coordinates specialist agents!\n");
console.log("═".repeat(50));
// Create a workspace for our research project
const xAgent = await XAgent.start(
"Research and write an article about sustainable energy"
);
const space = xAgent.getSpace();
console.log(`✨ Created Space: ${space.spaceId}`);
console.log(`πŸ“‹ Goal: ${space.goal}\n`);
// Phase 1: Research
console.log("πŸ“š Phase 1: Research");
console.log("─".repeat(40));
const researchStream = await xAgent.streamText({
messages: [
{
role: "user",
content: `Please research the current state of sustainable energy.
Focus on:
1. Solar and wind energy trends
2. Recent breakthroughs
3. Key statistics
Gather comprehensive information for an article.`,
},
],
metadata: { mode: "agent", requestedAgent: "X" },
});
for await (const chunk of researchStream.textStream) {
process.stdout.write(chunk);
}
console.log("\n");
// Phase 2: Writing
console.log("\n✍️ Phase 2: Writing");
console.log("─".repeat(40));
const writeStream = await xAgent.streamText({
messages: [
{
role: "user",
content: `Based on the research you've gathered, write a 500-word article about sustainable energy.
Include:
- An engaging introduction
- Key findings from your research
- Future outlook
- A compelling conclusion`,
},
],
metadata: { mode: "agent", requestedAgent: "X" },
});
for await (const chunk of writeStream.textStream) {
process.stdout.write(chunk);
}
console.log("\n");
// Phase 3: Review
console.log("\nπŸ” Phase 3: Review");
console.log("─".repeat(40));
const reviewStream = await xAgent.streamText({
messages: [
{
role: "user",
content:
"Review the article you just wrote. Check for clarity, flow, and accuracy. Suggest any improvements.",
},
],
metadata: { mode: "agent", requestedAgent: "X" },
});
for await (const chunk of reviewStream.textStream) {
process.stdout.write(chunk);
}
console.log("\n");
// Save the workspace
await space.persistState();
console.log("═".repeat(50));
console.log("πŸŽ‰ Collaboration complete!");
console.log(`πŸ’Ύ Space saved: ${space.spaceId}`);
console.log(
"\nYou can resume this workspace later to continue refining the article."
);
}
main().catch(console.error);

Add scripts to package.json:

{
"type": "module",
"scripts": {
"start": "tsx src/index.ts"
}
}

Run the team:

Terminal window
pnpm start

You’ll see something like:

✍️ Research & Writing Team Demo
Watch as XAgent coordinates specialist agents!
══════════════════════════════════════════════════
✨ Created Space: space_abc123xyz
πŸ“‹ Goal: Research and write an article about sustainable energy
πŸ“š Phase 1: Research
────────────────────────────────────────
I'll research the current state of sustainable energy for you...
[XAgent gathers information and presents findings]
✍️ Phase 2: Writing
────────────────────────────────────────
Based on the research, I'll now write a comprehensive article...
[XAgent creates the article]
πŸ” Phase 3: Review
────────────────────────────────────────
Let me review the article for clarity and accuracy...
[XAgent provides feedback]
══════════════════════════════════════════════════
πŸŽ‰ Collaboration complete!
πŸ’Ύ Space saved: space_abc123xyz

Create an interactive version in src/interactive.ts:

import "dotenv/config";
import { XAgent, Space } from "viber";
import * as readline from "readline";
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
function prompt(question: string): Promise<string> {
return new Promise((resolve) => {
rl.question(question, resolve);
});
}
async function main() {
console.log("🀝 Interactive Multi-Agent Collaboration\n");
// Check for existing space
const existingSpaceId = process.env.SPACE_ID;
let xAgent: XAgent;
let space: Space;
if (existingSpaceId) {
console.log(`πŸ“‚ Found existing space: ${existingSpaceId}`);
const resume = await prompt("Resume previous session? (y/n): ");
if (resume.toLowerCase() === "y") {
xAgent = await XAgent.resume(existingSpaceId);
space = xAgent.getSpace();
console.log(`\n✨ Resumed: ${space.name}`);
console.log(`πŸ“Š Previous messages: ${space.history.messages.length}`);
} else {
const result = await createNewSpace();
xAgent = result.xAgent;
space = result.space;
}
} else {
const result = await createNewSpace();
xAgent = result.xAgent;
space = result.space;
}
console.log("\nπŸ’‘ Commands:");
console.log(" - Type your request to collaborate with XAgent");
console.log(" - Type 'status' to see workspace info");
console.log(' - Type "quit" to save and exit\n');
// Main interaction loop
while (true) {
const input = await prompt("\nπŸ“ You: ");
if (input.toLowerCase() === "quit") {
console.log("\nπŸ’Ύ Saving workspace...");
await space.persistState();
console.log(`βœ… Saved! Space ID: ${space.spaceId}`);
break;
}
if (input.toLowerCase() === "status") {
console.log("\nπŸ“Š Workspace Status:");
console.log(` Space: ${space.name}`);
console.log(` Goal: ${space.goal}`);
console.log(` Messages: ${space.history.messages.length}`);
continue;
}
if (!input.trim()) continue;
console.log("\nπŸ€– XAgent: ");
const stream = await xAgent.streamText({
messages: [{ role: "user", content: input }],
metadata: { mode: "agent", requestedAgent: "X" },
});
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
console.log("");
}
rl.close();
}
async function createNewSpace(): Promise<{ xAgent: XAgent; space: Space }> {
const topic = await prompt("What would you like to work on? ");
const xAgent = await XAgent.start(topic || "Research and writing project");
const space = xAgent.getSpace();
console.log(`\n✨ Created new workspace: ${space.spaceId}`);
return { xAgent, space };
}
main().catch(console.error);

Add the script:

{
"scripts": {
"start": "tsx src/index.ts",
"interactive": "tsx src/interactive.ts"
}
}

Run:

Terminal window
pnpm interactive

You’ve built your first multi-agent collaborative system! Here’s what you accomplished:

βœ… Coordinated specialist agents through XAgent
βœ… Built multi-phase workflows (research β†’ write β†’ review)
βœ… Created interactive sessions with persistent context
βœ… Observed real-time collaboration between AI agents

  • XAgent Coordination: XAgent manages the overall workflow and delegates to specialists
  • Context Preservation: All phases share context within the Space
  • Iterative Refinement: Work improves through multiple passes
  • Persistent Collaboration: Resume work at any time
  1. Unified Context: All agents work within the same Space
  2. Accumulated Knowledge: Each phase builds on previous work
  3. Natural Workflow: Research β†’ Write β†’ Review mirrors how humans work
  4. Persistent State: Everything is saved automatically
  • Content Creation: Blog posts, documentation, marketing copy
  • Research Projects: Gather information, analyze, synthesize
  • Code Development: Plan, implement, review, refine
  • Customer Service: Triage, respond, follow-up

Your agents can collaborate, but they’re still limited to built-in capabilities. In Tutorial 3: Custom Tools, you’ll learn how to give your agents superpowers by creating custom tools that connect to external APIs and services.

  • Custom search tool that fetches real data
  • File operations for saving artifacts
  • External API integration for enhanced capabilities
  • Tool permissions and security

Agents not responding well?

  • Try more specific prompts
  • Break complex tasks into smaller steps
  • Provide clear context about what you need

Workflow getting stuck?

  • Check your API key and quota
  • Verify network connectivity
  • Try simpler requests to diagnose

Want to experiment?

  • Try different types of content (technical docs, creative writing)
  • Add more phases (outline β†’ draft β†’ revise β†’ polish)
  • Create domain-specific workflows

Ready to give your agents superpowers? Continue to Tutorial 3: Custom Tools! πŸ› οΈ