← All questions
System DesignMedium· System Design

When should an agent run synchronously versus asynchronously, and what does the hybrid streaming approach actually solve?

The choice isn’t ideological — it follows directly from how long the task actually takes, and getting it wrong shows up immediately as either timeouts or a frozen-looking UI.

  • Synchronous — the client sends a request and blocks until the agent returns a complete answer. Simple to implement, but only workable for tasks that reliably finish in a few seconds; past that, HTTP connections start timing out and the user stares at nothing.
  • Asynchronous — the client gets a task ID back immediately, the agent runs against a background worker pool pulling from a queue, and the client either polls for status or gets notified via webhook when it’s done. This is the right model for batch processing and for genuinely long tasks — multi-minute research, deep multi-step analysis — where making the caller hold a connection open the whole time doesn’t make sense.
  • Streaming (the hybrid that wins for interactive use) — return tokens and intermediate steps over a persistent connection (SSE or WebSocket) as they’re generated, rather than waiting for the full run to complete. This is worth being precise about: streaming does not reduce total latency at all — the full response still takes exactly as long to generate. What it changes is perceived latency, from the full run time down to time-to-first-token, roughly 100ms instead of ten seconds, and that’s the number that actually determines whether a chat interface feels responsive.

Production rule of thumb: under 3 seconds, stay synchronous; 3 to 30 seconds, add streaming so the user sees progress; past 30 seconds, go fully asynchronous with an explicit progress indicator, since even streaming stops feeling acceptable once a task runs that long.

Code playground (Python)