Kartheek Surampudi
← All posts

How agent architectures affect model serving characteristics and performance

August 30, 2026

Note: This blog post was generated in part using AI.

When building agents, the default assumption is to treat the model API as a blackbox that serves a model of a certain capability and the job of an agent engineer is to build a agent system (harness) that uses the capability of said model to the maximum to solve the task(s) at hand. For example, GPT 5.x can handle certain complexity of problems until a certain context length, therefore the harness should employ context management to match those constraints. However, the agent architecture or the agent topology that's chosen can very heavily affect the overall performance (mainly throughput) of the system as a whole. This is more relevant for internal model deployments where the model serving setup has to cater for a relatively lesser number of tasks/agents.

With many optimizations like prefix-caching, continuous batching, speculative decoding etc to choose from, it becomes even more important that the agent architecture and the serving config would need to go hand in hand when it comes to local/internal deployments.

To see how agent architecture affects serving we will setup 2 agent architectures:

  • Single ReAct Agent
  • Orchestrator: A parent agent that can break the task into sub-problems and spawn sub agents to solve them

Single ReAct agent

TaskReAct agentLLM call 1tool 1LLM call 2tool 2LLM call 3tool 3… up to 100 steps

Every LLM call resubmits the full history — the prompt grows by one assistant turn + one tool result per step.

Orchestrator + subagents

TaskOrchestrator(1 planning call)subagent 1tool subsetsubagent 2tool subsetsubagent 3tool subsetResult

Subagents run in parallel (capped), each with only its own history and tool subset — much shorter prompts.

Experiment Setup

The serving stack

We simulate a vLLM-style inference server running Kimi K2 — a 1T-parameter Mixture-of-Experts model with 32B active parameters per token — on a single 8×NVIDIA B200 node (1,536 GB HBM3e total). This is the reference single-node configuration for K2: FP8 weights occupy ~1,000 GB, leaving roughly 476 GB for the KV cache. The engine models continuous batching (up to 128 sequences decoding together), chunked prefill at ~60k tokens/s aggregate, and decode at ~32k tokens/s per node — in line with published B200 numbers for this model class.

The workload

Instead of synthetic prompts, we replay 295 real agent trajectories from the Toolathon benchmark (a tool-use benchmark where agents operate MCP tools: filesystem, browsers, cloud APIs, terminals, spreadsheets etc.,). We use the runs produced by kimi-k2-0905 itself, and reconstruct every LLM request with realistic token counts. A typical task makes ~28 LLM calls; the median request carries a ~15.5k-token prompt and produces only ~53 output tokens.

Both architectures solve the same 295 tasks. The ReAct agent replays each trajectory sequentially, its prompt growing by one assistant turn plus one tool result per step. The orchestrator makes one planning call, then splits the task by tool domain into parallel subagents (median 3, up to 8 concurrent), each carrying only the shared system prompt, the task, its tool subset, and its own history. We submit all 295 tasks at once and measure the makespan — the time to finish everything.

Results

Baseline: continuous batching, no caching

With plain serving, every request is prefilled from scratch. The queue you see below is the prefill queue: prompts are huge, outputs are tiny, so the GPU spends its life reading prompts, not writing answers. Hit play — watch how differently the two architectures load the server.

loading…

Single ReAct agent

Single ReAct agent: 295 agents each work through their task one LLM call at a time. Every call resubmits the full conversation history, so prefill volume is enormous (207M tokens total). Makespan: 111.6 min.

Orchestrator + subagents

Orchestrator: after a planning call, subagents attack sub-problems in parallel. Parallelism alone doesn't help a prefill-bound server — but each subagent carries only its own history, so total prompt volume drops 2.2× to 93M tokens. Makespan: 50.0 min (2.2× faster).

queuedprefilldecoding

The orchestrator wins even here — not because parallelism speeds up a prefill-bound GPU (it doesn't; the queue just gets longer), but because subagents send 2.2× fewer prompt tokens. When the bottleneck is reading prompts, the best architecture is the one that writes fewer of them.

Enter prefix-caching

Prefix caching (vLLM's APC, SGLang's RadixAttention) stores the KV tensors of computed prompt prefixes in GPU memory — in 16-token blocks, content-hashed and chained — so that a new request sharing a prefix can skip recompute entirely. Blocks no longer referenced are evicted LRU when the cache fills. For agent loops this is a natural goldmine: step k's prompt is a strict prefix of step k+1's.

But the cache is bounded — 476 GB here — and 295 agents generate more than 6.8M tokens of distinct KV. Watch the cache fill, and watch what gets evicted:

loading…

Single ReAct agent

Single ReAct agent + prefix cache: 91.5% of all prompt tokens are served from cache — each step only recomputes the previous step's new tokens. But full-history prompts keep 537k blocks evicted over the run. Makespan: 10.9 min (10.2× over no cache).

Orchestrator + subagents

Orchestrator + prefix cache: subagents share the system+task+schema prefix across all of an orchestrator's children, and each short history stays cache-resident. 87.2% hit rate with far fewer evictions (238k). Makespan: 7.6 min — the fastest configuration overall.

queuedprefilldecodingcached KV blockseviction

The overall picture

Time to finish all 295 tasks (makespan, lower is better)

ReAct (cache off)
111.5 min
Orchestrator (cache off)
50.0 min
ReAct (cache on)
10.9 min
Orchestrator (cache on)
7.6 min
295 Toolathon tasks submitted at once to a simulated 8×B200 node serving Kimi K2. Prefix caching lifts both topologies by an order of magnitude; the orchestrator is fastest in both settings.

So what we've seen so far is two effects stacking in the orchestrator's favor. First, it sends 2.2× fewer prompt tokens — subagents don't drag the whole conversation behind them — which is decisive in a prefill-bound regime. Second, its cache working set is smaller: shared shallow prefixes instead of deep per-agent histories, so it saturates the prefix cache at roughly half the memory budget (~100 GB vs ~200 GB in our sweeps) and suffers fewer than half the evictions. And even with the full 476 GB cache, where both topologies approach their hit-rate ceilings (91.5% vs 87.2%), the orchestrator still finishes first.

The caveat that surprised us: parallelism by itself buys nothing on a prefill-bound server. The orchestrator's win is an information-locality win — shorter prompts, smaller working set, gentler cache pressure. Architecture is a memory-system decision as much as a reasoning-quality one.

Caveats

  • Agentic workloads are prefill-dominated: the median request reads a ~15.5k-token prompt and writes only ~53 tokens, so everything above speaks to a prefill-bound server. Decode-heavy workloads (long reasoning traces, long generations) would shift the bottleneck — and possibly the conclusions.
  • This is a simulation: prefill/decode rates are calibrated to published 8×B200 figures for Kimi K2's model class, not measured on live hardware.
  • Token counts use the cl100k_base tokenizer as a proxy for Kimi K2's tokenizer — close enough for relative comparisons, not exact.
  • The orchestrator's decomposition is synthesized by grouping each trajectory's tool calls by tool domain. Real planners won't partition this cleanly.
  • Tool execution latency is synthetic (exponential, mean 0.6s); agent "think time" between steps comes only from the trace structure.
  • Decode memory-bandwidth contention is modeled and turns out negligible here — MLA's KV is small enough that decode stays weight-bound at batch 128. With a GQA model (or much longer contexts) this changes.
  • All 295 tasks arrive at once (fixed-batch makespan). A Poisson arrival process would change queueing dynamics, though not the token-volume conclusions.

Code, traces, and the full simulation report are available on request — the animations above replay real event streams from the simulator.