AgentKit 2.0 made building multi-agent systems easier, but production deployments reveal new challenges. This deep-dive covers the seven most common pitfalls encountered by Antigravity teams in real-world scenarios—complete with diagnostics, code examples, and proven fixes.
Pitfall 1: Context Sharing Breakdown
The Symptom
Agent A extracts data from an API, but Agent B claims the data is "unknown." Information that should cascade through the system vanishes.
Root Cause
AgentKit 2.0 isolates each agent's memory space by default. Without explicit context passing, agents operate in silos. The framework doesn't automatically broadcast one agent's output to another.
// ❌ Wrong: assumes automatic context sharing
const agentA = new AntigravityAgent({ name: "DataFetcher" });
const agentB = new AntigravityAgent({ name: "DataAnalyzer" });
const dataA = await agentA.run("Fetch user data from API");
// agentB has no knowledge of dataA's result
const analysis = await agentB.run("Analyze users");The Fix
Explicitly pass context between agents:
// ✓ Correct: explicit context handoff
const agentA = new AntigravityAgent({ name: "DataFetcher" });
const agentB = new AntigravityAgent({ name: "DataAnalyzer" });
const resultA = await agentA.run("Fetch user data from API");
// Pass Agent A's output into Agent B's context
const contextB = {
userData: resultA.output,
timestamp: new Date().toISOString()
};
const analysis = await agentB.run("Analyze users", {
context: contextB
});Or use an Orchestrator for cleaner orchestration:
const orchestrator = new AgentOrchestrator({
agents: [
{ name: "Fetcher", agent: agentA },
{ name: "Analyzer", agent: agentB }
]
});
const result = await orchestrator.execute([
{ agentName: "Fetcher", task: "Fetch user data from API" },
{
agentName: "Analyzer",
task: "Analyze users",
dependsOn: "Fetcher"
}
]);Pitfall 2: Loop Detection Misconfiguration
The Symptom
An agent repeats the same operation endlessly. Logs show "validation failed → retry" cycling forever, eventually timing out.
Root Cause
Loop Detection's threshold doesn't match your workflow's complexity. The default—"stop after 3 identical decisions"—is too strict for multi-step processes and causes legitimate retries to be flagged as loops.
// ❌ Default Loop Detection too tight
const agent = new AntigravityAgent({
// loopDetection: { maxRepetitions: 3 }
});
await agent.run("Complex multi-step workflow");The Fix
Adjust Loop Detection to match workflow complexity:
// ✓ Correct: tuned for multi-step work
const agent = new AntigravityAgent({
loopDetection: {
maxRepetitions: 5,
cooldownMs: 2000,
similarityThreshold: 0.9
}
});
await agent.run("Complex multi-step workflow");Pitfall 3: Timeout Configuration Mismatch
The Symptom
Two opposite problems:
- Too short: "Timed out after 10 seconds" when the task clearly needs more
- Too long: Agent waits 5 minutes for something that should take 30 seconds
Root Cause
Global or per-task timeouts don't reflect actual task execution time. Network I/O especially requires buffer; ignoring latency causes frequent premature timeouts.
// ❌ Too short: ignores network latency
const agent = new AntigravityAgent({
timeout: 10000
});The Fix
Tune timeouts per task type:
// ✓ Correct: different timeouts for different work
const quickTask = await agent.run(
"Translate this text",
{ timeout: 5000 }
);
const complexTask = await agent.run(
"Fetch from 3 APIs, perform statistical analysis",
{
timeout: 60000,
retryOnTimeout: true,
maxRetries: 2
}
);Pitfall 4: Race Conditions in Parallel Execution
The Symptom
Running agents in parallel sometimes produces inconsistent results. Two agents write conflicting values to the same record. Data integrity issues appear sporadically.
Root Cause
executeParallel() launches multiple agents against shared resources without locking. When two agents update the same database row simultaneously, writes collide and one overwrites the other.
// ❌ Unsafe: parallel access to shared resource
const [result1, result2] = await Promise.all([
agent1.run("Increment counter in DB"),
agent2.run("Increment counter in DB")
]);The Fix
Parallelize only independent work; serialize shared-resource access:
// ✓ Correct: parallelize independent tasks
const [userData, analyticsData] = await Promise.all([
agent1.run("Fetch user master data"),
agent2.run("Fetch analytics data")
]);
await agent3.run("Merge data and update DB", {
context: { userData, analyticsData }
});Pitfall 5: Runaway AI Credit Consumption
The Symptom
Actual credit usage is 2–3x expected. Especially bad with Planning Mode.
Root Cause
- Using Planning Mode for tasks that work fine in Fast Mode
- Recomputing results instead of caching them
- Agent configured to "think" repeatedly on the same problem
// ❌ Wasteful: Planning Mode for everything
const results = [];
for (const item of items) {
results.push(
await agent.run(`Process ${item}`, {
mode: "planning"
})
);
}The Fix
Choose mode based on task complexity; cache aggressively:
// ✓ Correct: simple tasks in Fast Mode; cache results
const cache = new Map();
for (const item of items) {
const cacheKey = hashFunction(item);
if (cache.has(cacheKey)) {
results.push(cache.get(cacheKey));
continue;
}
const mode = item.split(' ').length > 20 ? "planning" : "fast";
const result = await agent.run(`Process ${item}`, { mode });
cache.set(cacheKey, result);
results.push(result);
}Pitfall 6: Error Propagation Design Flaws
The Symptom
One agent fails, and the entire job fails. Partial results are discarded. Systems can't tolerate any component failure.
Root Cause
Orchestrator uses "fail-fast" error handling. The first error stops everything. There's no distinction between fatal errors (stop everything) and recoverable errors (log and continue).
// ❌ Fragile: single failure = total failure
const results = await orchestrator.execute([
{ agentName: "A", task: "Task A" },
{ agentName: "B", task: "Task B" },
{ agentName: "C", task: "Task C" }
]);The Fix
Classify errors and allow partial failures:
// ✓ Correct: tolerate partial failures
const results = await orchestrator.execute([
{
agentName: "A",
task: "Task A",
errorHandling: "critical"
},
{
agentName: "B",
task: "Task B",
errorHandling: "warn"
},
{
agentName: "C",
task: "Task C",
errorHandling: "silent"
}
], {
continueOnError: true
});Pitfall 7: Debugging Asynchronous Agents
The Symptom
The agent is a "black box." What's it doing? Why did it time out after 5 minutes? No visibility.
Root Cause
Agent internals are hidden. You don't know which step is executing, what the agent is thinking, or where time is spent.
// ❌ No visibility: opaque execution
const result = await agent.run(task);The Fix
Build observability: structured logs, distributed tracing, metrics:
// ✓ Correct: detailed instrumentation
const agent = new AntigravityAgent({
logging: {
level: "debug",
format: "json",
destination: "cloudwatch"
},
tracing: {
enabled: true,
samplingRate: 1.0,
exportTo: "jaeger"
}
});Looking back
Multi-agent systems introduce complexity beyond single-agent work. But these seven pitfalls are avoidable with proper design. The key principles:
- Context sharing: Implement explicitly via Orchestrator
- Loop detection + timeouts: Tune to workflow characteristics
- Parallel execution: Protect shared resources with locks
- Error handling: Allow partial failures with error classification
- Observability: Invest in logging, tracing, and metrics from day one
With these patterns in place, you can build large-scale, reliable multi-agent systems that survive production.