SUB-SECOND MULTI-AGENT STREAMING WITH EVENT WORKFLOWS
InnvoLabs
Technical Architecture & Engineering Systems
Chaining multiple AI agents together in a sequential pipeline—where Agent A finishes, passes text to Agent B, who processes it and calls Agent C—creates intolerable latency. In enterprise customer-facing applications, users wait 25+ seconds staring at a loading spinner before seeing the first word.
We eliminated sequential bottlenecks by rebuilding our multi-agent orchestrator around an event-driven asynchronous DAG. Specialized agents run in parallel, stream intermediate tokens over WebSockets, and speculatively execute downstream dependencies.
Here is the event-driven architecture, WebSocket streaming protocol, and production Node.js engine.
The Latency Tax of Sequential Multi-Agent Pipelines
Traditional agent frameworks execute steps in a strict linear sequence:
[User Request]
|
v (Wait 6.2s)
[Research Agent] ----(Full JSON Output)----> [Risk Agent]
|
v (Wait 7.1s)
[Final Client Brief] <---(Full Summary)---- [Synthesizer Agent]
Structural Pain Points:
- Compounding Latency: The user receives zero feedback while agents execute sequentially in the background.
- Brittle Error Propagation: If the Risk Agent fails at second 13, the entire workflow crashes, wasting all prior LLM execution tokens.
- State Corruption: Concurrent user requests modifying shared resource states led to race conditions in database mutations.
Event-Driven Architecture: Asynchronous DAG and Streaming States
To break sequential dependencies, we migrated to an event-driven architecture powered by Redis Pub/Sub, Async DAG State Machine, and WebSocket Stream Multiplexing.
+------------------------+
| User WebSocket Gateway |
+-----------+------------+
|
v
+------------------------+
| Event Stream Bus |
| (Redis Pub/Sub) |
+----+--------------+----+
| |
+-------------------+ +--------------------+
v v
+--------------------+ +--------------------+
| Researcher Agent | | Market Data Agent |
| (Streams Tokens) | | (Fetches Tickers) |
+---------+----------+ +---------+----------+
| |
+-------------------+--------------+--------------------+
| Chunk Stream |
v v
+-----------------------------------+
| Risk & Compliance Agent |
| (Speculative Early Execution) |
+-----------------+-----------------+
|
v
+-----------------------------------+
| WebSocket UI Chunk Streamer |
+-----------------------------------+
Pillar 1: Speculative Early Execution
Instead of waiting for the Researcher Agent to finish its full 2,000-token generation, it streams output chunks into Redis Pub/Sub. The Risk Agent listens to the stream. As soon as key entities are detected (via regex/NER stream parsing), the Risk Agent begins speculative validation concurrently while the Researcher Agent is still completing its response.
Pillar 2: Distributed State Synchronization
To manage state across decoupled workers, we implemented atomic state locks using Redis Redlock:
- State mutations are versioned with optimistic concurrency control.
- If two sub-agents attempt to update the project plan simultaneously, the lock engine enforces determinism based on DAG topological ordering.
Pillar 3: Single-Pass WebSocket Stream Multiplexing
All agent events (token streaming, tool invocations, state updates, errors) are wrapped in typed event envelopes and pushed through a single multiplexed WebSocket connection to the frontend UI.
TypeScript Implementation: Async Multi-Agent Event Dispatcher
Here is our production TypeScript Event Dispatcher that routes streaming tokens between concurrently executing agent workers:
import { EventEmitter } from "events";
import Redis from "ioredis";
interface AgentEvent {
traceId: string;
agentId: string;
eventType: "TOKEN_STREAM" | "TOOL_START" | "TOOL_END" | "STATE_MUTATION";
payload: Record<string, any>;
}
export class MultiAgentEventDispatcher extends EventEmitter {
private redisPub: Redis;
private redisSub: Redis;
constructor(redisUrl: string) {
super();
this.redisPub = new Redis(redisUrl);
this.redisSub = new Redis(redisUrl);
}
public async publishAgentEvent(channel: string, event: AgentEvent): Promise<void> {
const serialized = JSON.stringify(event);
await this.redisPub.publish(channel, serialized);
}
public async subscribeToTrace(traceId: string, onEvent: (event: AgentEvent) => void): Promise<void> {
const channel = `trace:${traceId}`;
await this.redisSub.subscribe(channel);
this.redisSub.on("message", (chan, message) => {
if (chan === channel) {
const parsed: AgentEvent = JSON.parse(message);
onEvent(parsed);
}
});
}
}
Production Benchmarks: Latency Reduction and TTFT Comparison
We measured performance across 2,500 execution traces in enterprise customer deployments:
| Metric | Sequential Chain | Event-Driven Async DAG | Improvement |
|---|---|---|---|
| Time to First Token (TTFT) | 6,400 ms | 380 ms | 94.0% reduction |
| P95 Total Execution Time | 22.4 seconds | 4.1 seconds | 81.7% faster |
| Workflow Completion Rate | 91.2% | 99.4% | +8.2% reliability |
| Concurrent Workflows / Server | 45 workflows | 320 workflows | 7.1x scale factor |
Engineering Lessons for Event-Driven AI Systems
- Stream everything early: Never wait for complete agent responses before triggering downstream analytical tasks.
- Use explicit DAG state graphs: Do not rely on unpredictable LLM prompts to decide which agent runs next; use hardcoded event routing for control flow.
- Isolate state mutations: Wrap shared agent state in atomic distributed locks to eliminate race conditions under heavy load.