Building Multi-Agent Systems with AgentKit 2.0 in Antigravity — A Production Implementation Guide
AgentKit 2.0 dropped the barrier to multi-agent systems sharply. After implementing three different agent-coordination patterns in Antigravity, here's the design playbook covering decisions, traps, and production operation.
My first reaction when AgentKit 2.0 landed was, "wait, they actually simplified this."
In the 1.x days, orchestrating multiple agents meant fishing the OpenAI API directly, hand-managing message flows between them, the whole thing felt like "will this even work?" territory. I implemented three multi-agent patterns on Antigravity, and that was the moment it clicked — AgentKit 2.0 absorbs a lot of the complexity you used to carry yourself.
This guide walks you from design philosophy through three real patterns, into the production nightmares you'll actually hit. By the end you'll know how to ship multi-agent systems that don't just work in demos.
Why AgentKit 2.0 Matters: The 1.x to 2.0 Shift
First, understand what 2.0 fixed.
Version 1.x treated you to a "magic agent" API — declare what you want, trust the LLM. You built control-flow blind. Version 2.0 flipped the model: explicit control surfaces.
AgentKit 2.0 breaks orchestration into three clear layers:
Agent — single-purpose execution unit. "search for product info" or "request user approval," each fully scoped
Workflow — choreography recipe. "search first, then route results to approval" — you own the graph
Coordinator — system supervisor. Multiple workflows go parallel, one component orchestrates them safely
The moment you internalize this three-layer mental model, complex multi-agent systems become as predictable as a test spec.
The 1.x approach left control implicit. You were hoping the LLM made the right choice. 2.0 hands the control back to you. That's the revolution.
The Three Core Abstractions: Agent, Workflow, Coordinator
This section is make-or-break for mastering AgentKit 2.0.
Agent — Single Responsibility in Code
An Agent is one thing, done very well.
import { Agent } from '@google-cloud/agentkit';const researchAgent = new Agent({ name: 'researcher', systemPrompt: 'You are a product researcher. Find detailed information about the given product from web sources.', tools: ['search', 'summarize'], maxIterations: 5, timeoutMs: 30000,});const result = await researchAgent.execute({ input: 'Research the Antigravity April 2026 update in detail',});
Three things matter here:
1. Explicit Tool Declaration
The Agent declares tools: ['search', 'summarize']. This isn't about capability — it's about guardrails. The LLM won't try to write files or launch deployments, because you didn't grant those powers. That cuts hallucinations and costs.
2. timeoutMs Is Non-Negotiable
Agents that do web/API work need real timeouts. 30s is sane. Too high and you get zombie agents locking up the whole system. Too low and they never finish. This becomes your first production tuning knob.
3. maxIterations Caps Thinking
This is the "how many times can the Agent loop on itself?" limiter. Default is 10. For decision-making agents (approval, risk assessment), drop to 3–5. Prevents infinite deliberation spirals.
Workflow — Graphs, Not Pipelines
Workflows compose Agents as a directed graph, not a linear pipeline.
import { Workflow, Edge } from '@google-cloud/agentkit';const multiAgentWorkflow = new Workflow({ name: 'product_review_workflow', agents: { research: researchAgent, fact_check: factCheckAgent, summarize: summarizeAgent, }, edges: [ new Edge('research', 'fact_check', (output) => output.length > 1000), new Edge('fact_check', 'summarize', () => true), ],});const result = await multiAgentWorkflow.execute({ input: { product: 'Antigravity IDE' },});
Key design choice: conditional edges.
The third argument to Edge is a predicate. (output) => output.length > 1000 means "only route to fact_check if research gave us substantial output." Skip it otherwise. That's how you encode branching logic.
Current AgentKit 2.0 Workflows are strictly linear when executing. Parallel fan-out goes to Coordinator. This constraint makes debugging far easier — you can trace execution sequentially.
Coordinator — Meta-Level Control
When you need multiple Workflows running concurrently, or one Workflow deciding which other Workflow to spawn, Coordinator handles that.
maxConcurrent: 3 — sanity check. Don't run unlimited Workflows. API rate limits and LLM token quota are real. 2–3 is practical for most deployments.
onConflict: 'halt' vs 'delegate' — when two Workflows collide on the same resource (shared DB, API rate limit), what happens? halt stops and reports (safe). delegate has Coordinator auto-order them (fast, but complex). Start with halt.
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦When to reach for each of AgentKit 2.0's three core abstractions (Agent / Workflow / Coordinator) becomes obvious after reading the design patterns — you'll recognize them in your own architecture challenges
✦Full implementation code for three patterns I shipped: parallel research, sequential approval chain, and hierarchical supervisor — all copy-paste ready and tested in production
✦Production failure modes (timeouts, infinite loops, runaway costs) and the mitigations that actually held up — specific code patterns you can adopt today to protect yourself
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
Multiple "researcher" Agents hit different sources at the same time, then a synthesizer merges the findings.
import { Agent, Workflow, Coordinator } from '@google-cloud/agentkit';// Three specialist researchersconst webSearchAgent = new Agent({ name: 'web_search_agent', systemPrompt: 'Search for information using web sources only.', tools: ['google_search', 'summarize'], maxIterations: 4, timeoutMs: 40000,});const githubAgent = new Agent({ name: 'github_agent', systemPrompt: 'Find information from GitHub repositories, issues, and discussions.', tools: ['github_api', 'code_analysis'], maxIterations: 3, timeoutMs: 30000,});const docsAgent = new Agent({ name: 'docs_agent', systemPrompt: 'Extract relevant information from official documentation.', tools: ['docs_fetch', 'parse_markdown'], maxIterations: 3, timeoutMs: 25000,});// Synthesis Agentconst synthesisAgent = new Agent({ name: 'synthesis_agent', systemPrompt: `You receive research from 3 parallel sources:- web_search_agent: web findings- github_agent: GitHub findings - docs_agent: documentation findingsSynthesize into ONE coherent report. Clearly attribute each claim to its source. Call out conflicts.`, tools: ['format', 'validate'], maxIterations: 5, timeoutMs: 30000,});// Define the workflowconst researchWorkflow = new Workflow({ name: 'parallel_research_workflow', agents: { web: webSearchAgent, github: githubAgent, docs: docsAgent, synthesis: synthesisAgent, }, edges: [ // All three researchers feed into synthesis new Edge('web', 'synthesis', () => true), new Edge('github', 'synthesis', () => true), new Edge('docs', 'synthesis', () => true), ],});const result = await researchWorkflow.execute({ input: { topic: 'Antigravity IDE 2026 Roadmap', context: 'Find the most recent information from all sources', },});console.log(result);// Output:// {// status: 'success',// synthesis_result: { // report: "Antigravity's...",// sources: { web: [...], github: [...], docs: [...] }// }// }
Strengths of this pattern:
Information sources are cleanly separated (debugging is easier)
One researcher getting stuck doesn't block the others
Results are reproducible (same input → similar output)
The gotcha:
synthesis_agent receives output from three sources. AgentKit 2.0 doesn't have automatic pipeline plumbing — you have to manually wire the previous outputs as input to the next stage. That's handled in the section below on "Debugging and Tracing."
Pattern 2: Sequential Approval Chain
Now a three-step decision flow: propose → review → execute. Useful for organizational sign-off processes.
// Proposeconst proposalAgent = new Agent({ name: 'proposal_agent', systemPrompt: `Generate a concrete implementation plan given a requirement.Output ONLY valid JSON:{ "title": "...", "steps": [...], "estimated_hours": N, "risk_level": "low|medium|high", "alternatives": [...]}`, tools: ['plan', 'estimate'], maxIterations: 5, timeoutMs: 45000,});// Reviewconst reviewerAgent = new Agent({ name: 'reviewer_agent', systemPrompt: `You are a technical reviewer. Evaluate the proposal.Check feasibility, timeline realism, risks.Output ONLY valid JSON:{ "decision": "APPROVED" | "REJECTED", "explanation": "..."}`, tools: ['assess_feasibility', 'historical_data'], maxIterations: 3, timeoutMs: 30000,});// Executeconst executorAgent = new Agent({ name: 'executor_agent', systemPrompt: `You received an APPROVED proposal.Break it into actionable tasks, assign resources, set up monitoring.`, tools: ['task_create', 'resource_allocate', 'monitoring_setup'], maxIterations: 6, timeoutMs: 60000,});// Approval chainconst approvalWorkflow = new Workflow({ name: 'approval_chain', agents: { propose: proposalAgent, review: reviewerAgent, execute: executorAgent, }, edges: [ new Edge('propose', 'review', () => true), // Conditional: only proceed to execute if APPROVED new Edge('review', 'execute', (reviewOutput) => { return reviewOutput.decision === 'APPROVED'; }), ],});const approval = await approvalWorkflow.execute({ input: { requirement: 'Add code quality analysis to Antigravity IDE', budget_hours: 80, },});console.log(approval);// Output:// {// status: 'success',// proposal: { title: '...', steps: [...], estimated_hours: 72 },// review_decision: 'APPROVED',// execution_plan: { tasks: [...], resources: [...] }// }
When this pattern shines:
Approval gets logged for compliance
Rejected proposals exit early (no wasted execution)
Human decision points are explicit in the design
Gotcha:
The conditional reviewOutput.decision === 'APPROVED' depends on the review Agent outputting valid JSON. If JSON parsing fails, the whole flow breaks. See "Debugging and Tracing" for mitigation.
Pattern 3: Hierarchical Supervisor
A senior "director" Agent oversees multiple specialist Agents. The director breaks the requirement down, delegates to specialists, synthesizes their feedback.
// Specialistsconst architectAgent = new Agent({ name: 'architect', systemPrompt: 'You are a software architect. Design the system architecture.', tools: ['design_pattern', 'architecture_decision'], maxIterations: 4, timeoutMs: 30000,});const securityAgent = new Agent({ name: 'security_expert', systemPrompt: 'You are a security expert. Identify risks and recommend mitigations.', tools: ['threat_analysis', 'security_best_practices'], maxIterations: 4, timeoutMs: 30000,});const performanceAgent = new Agent({ name: 'performance_expert', systemPrompt: 'You are a performance engineer. Analyze and suggest optimizations.', tools: ['profiling', 'benchmarking'], maxIterations: 4, timeoutMs: 30000,});// Directorconst supervisorAgent = new Agent({ name: 'supervisor', systemPrompt: `You oversee 3 specialists: architect, security_expert, performance_expert.Delegate the requirement to each. Collect feedback. Produce a final integrated decision.`, tools: ['delegate_task', 'integrate_feedback', 'decision_make'], maxIterations: 8, timeoutMs: 60000,});// Hierarchical orchestrationconst hierarchicalWorkflow = new Workflow({ name: 'hierarchical_review', agents: { supervisor: supervisorAgent, architect: architectAgent, security: securityAgent, performance: performanceAgent, }, edges: [ // Supervisor delegates to all three specialists new Edge('supervisor', 'architect', () => true), new Edge('supervisor', 'security', () => true), new Edge('supervisor', 'performance', () => true), ],});const result = await hierarchicalWorkflow.execute({ input: { requirement: 'Develop a local LLM plugin for Antigravity', constraints: { budget_days: 10, team_size: 2 }, },});console.log(result);
Where this pattern works:
Large feature decisions requiring multiple expertise areas
Security-critical systems that need formal review
High-performance-critical components
Implementation reality:
supervisor delegates to specialists, but AgentKit 2.0 doesn't auto-collect their outputs and feed them back to supervisor. You'll wire that manually — a multi-step process. This is where most of the orchestration code lives.
Production Failure Modes and Actual Mitigations
Here's what the official docs don't tell you.
Failure 1: Timeout Cascades
You set Agent A to 30s, Agent B to 30s. They run sequentially in a Workflow with a 120s limit. Sounds safe. In practice, Agent A burns 35s because the API was slow, Agent B gets 20s left, times out, and the whole Workflow fails.
Real-world approach: Workflow gets 120s hard deadline. Each Agent gets ~30s, but the last Agent in the chain gets "whatever's left" up to its base timeout. That adapts to slowness upstream.
Failure 2: Infinite Deliberation Loops
Agent X asks itself "is this answer good?" then asks again. maxIterations: 10 means it can loop 10 times. It usually does.
// ❌ Vague termination: "determine if reliable"const agent = new Agent({ systemPrompt: 'Determine if the information is reliable.', maxIterations: 10,});// ✅ Explicit termination: structured output onlyconst agent = new Agent({ systemPrompt: `Determine if the information is reliable.Output ONLY valid JSON:{ "is_reliable": true | false, "confidence": 0.0 to 1.0, "reasoning": "..."}Do not think further once JSON is output.`, maxIterations: 3,});
Key move: lock output to JSON format. The Agent knows "once I output valid JSON, my job is done." That signals termination.
Failure 3: API Quota Bankruptcy
Three Agents running concurrently = API calls skyrocket. You blow your Google Search quota in minutes.
import { Agent, RateLimiter } from '@google-cloud/agentkit';const rateLimiter = new RateLimiter({ maxRequests: 100, windowMs: 60000, // 100 requests/minute across all agents});const agent = new Agent({ name: 'search_agent', rateLimiter, // All calls throttled globally tools: ['google_search'],});
Production setup: Multiple API keys, rotated. Rate limiter enforces ceiling. Backup API fallbacks. Monitor quota real-time.
Failure 4: JSON Parse Disasters
The Agent outputs something "JSON-ish" but not valid JSON. Parser chokes. Workflow dies.
// ✅ Defensive parsingfunction safeJsonParse(output: string) { try { return JSON.parse(output); } catch (e) { // Extract JSON-like content const match = output.match(/\{[\s\S]*\}/); if (match) { try { return JSON.parse(match[0]); } catch (e2) { // Last resort: return raw, flag for human review return { raw_output: output, parse_error: true }; } } throw new Error('Failed to parse agent output'); }}
Rule: Always have a fallback path. Structured output > parse failure path > human escalation.
Cost Management That Doesn't Break the Bank
Multi-agent systems cost 5–10x more than single-agent ones. Runaway costs are the #1 production threat.
Per-request budget enforcement is non-negotiable. One stuck Agent could cost you hundreds. Budget ceiling + auto-halt beats "we'll monitor it" every time.
Debugging and Tracing Multi-Agent Flows
Single-process debugging doesn't translate. Here's what actually works:
This timeline view tells you which Agent is actually slow, not "the workflow is slow."
Antigravity-Specific Optimizations
Two moves make Antigravity's environment special for multi-agent work:
1. Manager Surface Parallel Views
Display multiple Workflows in the three-pane layout simultaneously. Watch all Agents in real time. That visibility is Antigravity-only.
2. Browser Agents + AgentKit Composition
Antigravity's built-in Browser Agents handle UI/browser tasks. Compose them with AgentKit 2.0 Agents for full-stack automation.
const mixedWorkflow = new Workflow({ agents: { research: researchAgent, // AgentKit browser_check: new BrowserAgent({ task: 'Check GitHub Actions deployment status', }), // Antigravity built-in summary: summaryAgent, }, edges: [ new Edge('research', 'browser_check'), new Edge('browser_check', 'summary'), ],});
That hybrid approach gives you automation breadth you don't get from pure code agents.
What Ships Next
After shipping these three patterns, two areas look ripe for next-gen AgentKit:
1. Shared Memory / Knowledge Base
Multiple Workflows need access to common facts (design docs, past decisions). 2.1 will likely formalize agent-to-agent memory sharing.
2. Flexible Human-in-the-Loop
Right now it's "propose → human approves → execute." Next will be pausing mid-Workflow to ask humans, or delegating specific decisions to humans. That raises trust significantly.
Multi-agent orchestration is now a first-class tool for solo developers and small teams. The patterns you implement today become the foundation for how you build systems over the next 18 months. Get the basics solid and you'll adapt quickly when the next wave ships.
Start with the parallel research pattern. It's the simplest to debug and teaches you the whole model. Ship it. Then tackle sequential approval. Then hierarchical. By then you'll know what your next pattern needs to be.
Share
Thank You for Reading
Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.