Design orchestrator-worker architectures, invoke specialist agents synchronously or asynchronously, and share state between agents using the Memory Store and Event Bus.
Why use multiple agents
A single agent that tries to handle every variation of a complex task tends to become large, hard to maintain, and difficult to test. Multi-agent architectures solve this by decomposing a complex problem into specialized sub-tasks, each handled by a focused agent. An orchestrator agent receives the top-level goal, breaks it into sub-tasks, delegates each to a specialist agent, and assembles the results. Benefits include: each specialist agent is smaller and easier to test independently, specialists can run in parallel for speed, and you can swap out or upgrade a specialist without rewriting the orchestrator.
The Invoke Agent action
Use the Invoke Agent action to call another agent from within your current agent. Configure it with the target agent's ID (or name), the input payload the target agent expects, and an optional timeout. The action supports two execution modes: synchronous (the calling agent waits for the invoked agent to complete and receives its output) and asynchronous (the calling agent fires the invoked agent and continues without waiting, useful for fan-out patterns). The invoked agent runs as a separate run with its own run ID, logs, and metrics, but is linked to the parent run in the Run Inspector for end-to-end traceability.
Orchestrator-worker patterns
A common multi-agent pattern is the orchestrator-worker architecture. The orchestrator agent receives the initial task, uses an LLM to decompose it into a list of sub-tasks, and then uses a Loop + Invoke Agent combination to delegate each sub-task to a worker agent. Worker agents are specialists: a research worker, a writing worker, a data-validation worker. Each worker runs independently, possibly in parallel if you configure the loop for concurrent iteration. The orchestrator collects all worker outputs and uses a final LLM step to synthesize them into a coherent result. This pattern scales to arbitrarily complex tasks while keeping each individual agent manageable.
Shared state and inter-agent communication
When multiple agents need to share state — for example, a progress counter, a shared result set, or a lock to prevent duplicate processing — use the Memory Store with a shared namespace. Configure each agent to read from and write to the same namespace key. For event-driven coordination (one agent triggering another based on a condition rather than a direct invocation), use the Cotonity Event Bus: emit a named event from one agent and subscribe another agent to it with an Event trigger. Event-driven patterns decouple agents more completely than direct invocation, making the system easier to extend without modifying existing agents.