Two Agents Made the Right Call and Still Broke the Workflow
A practical Google ADK pattern for safe fan-out, joins, single-writer state, failure policy, and topology-based agent tests.
Two agents working together in a production workflow can sometimes make the right choice, but also create more complexity. Separating operations into distinct agents may seem beneficial, but it can lead to additional state, coordination challenges, and difficulty in explaining how the system works. In many production workflows, the most dangerous assumption is that separate agents should run simultaneously.
Parallelism is only safe when the branches are truly independent. If one branch alters the state while another is evaluating it, both agents might make reasonable decisions individually, but those decisions could result in an unsafe outcome when combined. AgentInspect, an open-source execution-evidence tool, is mentioned in this context, but the ADK architecture and examples discussed here are not tied to that project.
Google's ADK 2.0 introduces workflow topology through graph-based Workflow objects, making sequences, branches, and joins part of the program rather than an implicit agreement between supervisors. When designing a system, start by focusing on dependencies rather than the number of agents. For example, consider a hotel recommendation system that requires live inventory, company travel policy, and a final recommendation.
Inventory lookup and policy evaluation can be run concurrently since they both observe the same request and do not change shared state. However, the final decision must wait for both operations to complete. Before creating a parallel branch, ask whether both operations only read the same starting state, if one operation can change data consumed by the other, if either operation could produce an irreversible side effect, and if there is a deterministic way to combine their results.
If these questions cannot be answered, parallelism should not be implemented yet. When parallelism is necessary, it should be encoded as fan-out and join nodes. The ADK's TypeScript Workflow graph can handle two independent branches and a join barrier directly. By using sequences when state must move in order, such as in a booking workflow (normalize request → search inventory → request approval → create booking → send confirmation), the system's behavior becomes safer and more predictable.
Instead of relying on a supervisor model to remember the required order, the workflow owns the invariant. Parallel branches should produce evidence, not mutations, as shared mutable state can lead to dangerous outcomes. Staging should be organized into three stages: parallel branches for gathering and normalizing evidence, a join for verifying that all required evidence has arrived, and a decision node for selecting the outcome.
Mutation nodes should own state transitions or side effects. If distributed mutation is unavoidable, use idempotency keys, resource-level concurrency control, and a durable result record. Do not rely on a model to notice if another branch is already acting. Failure semantics should be clearly defined in the graph, with each branch having a timeout and retry budget appropriate to its operation.
The join needs a rule for handling partial failure, such as fail closed, using a degraded mode, or requesting human review. The "continue with whatever arrived" approach should be a named policy, not an accident.
Written by urgent.news from HackerNoon's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.