Building a Multi-Agent Ghost Story: How Kiro’s Hybrid Development Changed Everything
Source: Dev.to
Overview
I built a gothic ghost story with five independent AI agents that debate in real‑time using Kiro IDE. Each agent was created with a different development approach—vibe coding, spec‑driven, and steering docs—yet they function together as a coherent family. This “Frankenstein” magic stitches incompatible paradigms into something unexpectedly powerful.
Tech Stack: Next.js, Groq (llama‑3.3‑70b), Azure TTS, Kiro IDE
Live Demo:
Source Code:
How to try: Click “Click to begin” and watch the five AI personalities debate your choices.
“The agents genuinely disagree, creating emergent storytelling that’s never the same twice.”
The Challenge
When building a game with five AI agents that need to:
- Maintain distinct personalities
- Debate with each other in real‑time
- Stay consistent across 50+ generations
- Create authentic conflict (not forced agreement)
traditional AI development quickly becomes a nightmare of prompt engineering, context management, and constant tweaking.
Kiro IDE’s Solution
Kiro IDE lets you combine multiple development paradigms in a single project and automatically stitches them together. Below is a breakdown of how each ghost character was built.
Vibe‑Coding (Emotional Character)
Conversation with Kiro
Me: I need a maternal ghost character
Kiro: What's her role?
Me: She's the mother. Gentle, prioritizes family harmony
Kiro: [Generates initial personality]
Me: More poetic. Less formal. Under 30 words per response.
Kiro: [Refines to final version]
Result: A fully‑formed character with emotional depth in about five minutes.
Why it works
- Fast iteration on “feeling”
- Hard to specify “maternal warmth” formally
- Natural language captures nuance better than technical specs
Spec‑Driven (Logical Character)
const harlan = {
name: 'Harlan',
personality: 'scientific, amnesiac, logical but confused',
systemPrompt: `You are Dr. Harlan Voss, the scientist ghost
with fragmented memories. You analyze problems logically but
struggle to remember emotional context. When debating, you
cite facts but defer to family on emotional matters. Keep
responses under 30 words. Use technical language mixed with
uncertainty.`
};
Why it works
- Rock‑solid consistency
- Debuggable (“Line 47 violates spec”)
- Ideal for logical, technical characters
Steering Docs (Rule‑Based Character)
File: .kiro/steering/ghost-agent-rules.md
## Inter‑Agent Debate Protocol
- Each agent MUST respond independently
- Agents can disagree – conflict is good for drama
- Mira often sides with emotional choices
- Harlan provides logical analysis but defers to family
- Selene demands honesty, Theo seeks forgiveness
Why it works
- Prevents personality mix‑ups across many generations
- Defines relationships between agents, not just individual traits
- Generates authentic conflict instead of forced agreement
Model Context Protocol (MCP) Server
A custom MCP server acts as a blockchain‑style ledger for eternal vows.
File: app/api/mcp/vows/route.ts
// Simple in‑memory vow ledger (simulates blockchain MCP)
const vows = new Map([
['theo-marry-selene', {
person: 'Theo',
vow: 'Marry Selene',
kept: false,
timestamp: '2039-01-15'
}],
['theo-return', {
person: 'Theo',
vow: 'Return to make amends',
kept: true,
timestamp: '2039-06-20'
}],
]);
export async function POST(req: NextRequest) {
const { action, person, vow } = await req.json();
if (action === 'check') {
const key = `${person.toLowerCase()}-${vow.toLowerCase().replace(/\s+/g, '-')}`;
const record = vows.get(key);
if (record) {
return NextResponse.json({
found: true,
...record,
message: record.kept
? `✓ Vow kept: ${record.person} did ${record.vow} on ${record.timestamp}`
: `✗ Vow broken: ${record.person} failed to ${record.vow}`
});
}
return NextResponse.json({
found: false,
message: 'No record of this vow in the ledger'
});
}
}
In‑Game Integration
File: HallwayScene.tsx
const handleCheckVow = async () => {
try {
const response = await fetch('/api/mcp/vows', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
action: 'check',
person: 'Theo',
vow: 'Return'
})
});
const result = await response.json();
setVowResult(result.message);
// Selene speaks the eternal record
speechService.speak(result.message, 'selene');
} catch (error) {
console.error('Failed to check vow:', error);
}
};
Player Experience
When players click “Check Theo’s Vow” in the Hallway scene, the API checks the ledger. Because the request uses vow: 'Return' while the ledger stores 'Return to make amends', the response is:
No record of this vow in the ledger
Why MCP fits
- Development‑time testing directly in Kiro IDE
- Separation of concerns: vow logic lives on a dedicated server
- Easy extensibility for more vows or characters
- Adds narrative depth through interactive verification
Real‑Time Debate Flow
When the player asks for a hint, all five agents are invoked in parallel:
// Invoke all 5 agents in parallel
const debatePromises = Object.keys(GHOST_AGENTS).map(async (ghostName) => {
const response = await invokeGhostAgent(ghostName, context, apiKey);
return { ghost: ghostName, message: response };
});
const debate = await Promise.all(debatePromises);
Example Debate
Player: “I need help with the tapestry puzzle”
- Elara: “Focus on love and emotional memories, dear one.”
- Harlan: “I… categories. Logic. But family transcends data.”
- Mira: “The happy ones! When we played together!”
- Theo: “Your family moments define you, brother.”
- Selene: “Truth matters. Match honestly, not hopefully.”
Consensus (Elara): “Look for the emotional connections in each photo—love, joy, and family bonds will guide you.”
Because the agents genuinely disagree, each playthrough yields a unique narrative.
Development Efficiency
| Task | Traditional Approach | With Kiro IDE |
|---|---|---|
| Create character personality | 2 hours (multiple prompt iterations) | ~5 minutes (natural conversation) |
| Maintain context across generations | Frequent manual prompt engineering | Automatic context preservation |
| Resolve conflicts between agents | Manual stitching of prompts | Steering docs act as “stitches” |
Result: Five distinct AI personalities built in under an hour instead of 10+ hours.
The Frankenstein Metaphor
Each agent was built using a different method:
- 🎨 Vibe‑coded Elara – fluid, emotional
- 📋 Spec‑driven Harlan – rigid, logical
- 📖 Steering‑enforced Mira – rule‑based simplicity
Although they shouldn’t work together, steering documents keep the chimera coherent, allowing authentic conflict while preventing chaos.
Key takeaway: By mixing development paradigms and letting Kiro handle the integration, you can create complex multi‑agent systems that are greater than the sum of their parts.