Beyond the Agentic Loop, in TypeScript: building a shopping agent with the Orchestrator pattern A developer built a shopping agent in TypeScript using the Orchestrator pattern, which separates decision-making from execution with exactly two LLM calls per request. The system routes queries to single-purpose agents via a registry, avoiding the latency and unpredictability of agentic loops. This post is a TypeScript implementation of the pattern described in "Beyond the Agentic Loop: The Orchestrator Pattern for Multi-Agent Systems" https://stackademic.com/blog/beyond-the-agentic-loop-the-orchestrator-pattern-for-multi-agent-systems by Before the pattern, the scene. The demo is a small storefront assistant backed by a few single-purpose agents: A customer request might need just one of these, several of them at once, or a few in a strict order — and deciding which of those shapes a request calls for is exactly what the orchestrator is for. while loop The default way to build a multi-agent system is the agentic loop : you hand the model a bag of tools and let it drive. think → call a tool → observe the result → think again → call another tool → … The LLM is both the brain and the control flow. That's wonderfully flexible, and it's the right tool when the task is open-ended and you genuinely don't know the steps in advance. But in production it has three nasty properties: If you already know which agents exist and what they do, an open-ended reasoning loop on every request is more freedom than the job needs. The orchestrator's move is to separate the decision from the execution . Instead of letting the model loop, you make exactly two LLM calls with plain, deterministic code in between: query ──▶ ROUTE: LLM 1 ──▶ EXECUTE: agents, no LLM ──▶ SYNTHESIZE: LLM 2 ──▶ answer Two calls, every time, no matter how many agents run. That fixed shape is the whole point: a plan you can inspect before anything happens, latency that doesn't depend on the model's mood, and independent work you can fan out. It's cheaper too — the article puts the same query at ~2 calls instead of ~7 — but the cost isn't the headline; the outcomes are. An agent is a name, a description for the router , a JSON-Schema for its arguments, and an execute function. Nothing more. // src/server/orchestrator/types.ts export type ExecuteFn = args: AgentArgs, context: AgentContext = Promise