<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>AA-AgentPerf-Local on RockB</title><link>https://baeseokjae.github.io/tags/aa-agentperf-local/</link><description>Recent content in AA-AgentPerf-Local on RockB</description><image><title>RockB</title><url>https://baeseokjae.github.io/images/og-default.png</url><link>https://baeseokjae.github.io/images/og-default.png</link></image><generator>Hugo</generator><language>en-us</language><lastBuildDate>Thu, 15 Oct 2026 00:30:00 +0000</lastBuildDate><atom:link href="https://baeseokjae.github.io/tags/aa-agentperf-local/index.xml" rel="self" type="application/rss+xml"/><item><title>AA AgentPerf Local: What Replaying Real Agent Trajectories Measures (and What It Cannot)</title><link>https://baeseokjae.github.io/posts/aa-agentperf-local-llm-serving-benchmark-2026/</link><pubDate>Thu, 15 Oct 2026 00:30:00 +0000</pubDate><guid>https://baeseokjae.github.io/posts/aa-agentperf-local-llm-serving-benchmark-2026/</guid><description>AA-AgentPerf-Local replays 8 recorded agent tasks and 168 model turns to measure local serving speed on agent-shaped traffic. What the replay measures, the comparability rules, and the vendor&amp;#39;s launch results.</description><content:encoded><![CDATA[<p>AA-AgentPerf-Local is an open-source tool from Artificial Analysis that replays recorded agent trajectories against a local OpenAI-compatible server and reports throughput and latency. The short answer to what it measures: serving speed on agent-shaped traffic - requests that carry the whole conversation so far, with long prompts and heavy key-value cache reuse - and deliberately nothing about output quality. The short answer to what it cannot do: it cannot give you a portable number. A result from it is only comparable if the context size was full, the output policy was <code>exact</code>, and the tool mode is stated. Miss any of those and you have an indicative run, not a benchmark.</p>
<p>That distinction is the whole point of this review. If you are sizing local inference for coding agents, the number you quote in a purchasing meeting has to travel with its conditions.</p>
<h2 id="what-the-default-replay-actually-is">What the default replay actually is</h2>
<p>The default workload is <code>agentperf-default-v1</code>: eight recorded agent tasks spanning 168 model turns. It uses the <code>exact</code> output policy, which makes every turn generate its recorded number of tokens, so every system does the same work. Each request carries the full conversation so far, so context grows to roughly 56K tokens, and the largest single turn in the default replay needs about 58,000 tokens. Tool execution is skipped by default; the intent is to isolate inference speed rather than to simulate a working day.</p>
<p>A second replay exists for install checks. <code>--replay aa-mini-v1</code> selects a six-turn synthetic replay, which the project describes as a quick install check whose results are not comparable.</p>
<p>One structural caveat is worth stating early: the eight tasks behind <code>agentperf-default-v1</code> are the vendor&rsquo;s recorded set. The public documentation we read defines their shape (task count, turn count, token behaviour) but does not enumerate them, so you cannot rebuild an identical workload from the docs alone - you replay the shipped trajectory set or you record your own with <code>convert</code>.</p>
<h2 id="why-agent-shaped-traffic-breaks-single-prompt-benchmarks">Why agent-shaped traffic breaks single-prompt benchmarks</h2>
<p>A single-prompt tokens-per-second figure tells you almost nothing about an agent workload, and the vendor&rsquo;s own numbers show why (VENDOR RESULTS, Artificial Analysis&rsquo; announcement page, not our measurement):</p>
<ul>
<li>Between 73% and 93% of prompt tokens were served from the KV cache, so most of the prompt is never recomputed - decode is not the only bottleneck.</li>
<li>Reading each turn&rsquo;s new input during prefill still consumed a substantial share of end-to-end completion time - the vendor reports 22-41% for Qwen3.8-27B.</li>
<li>Each session still carried roughly 196K new input tokens against about 31K output tokens.</li>
<li>When a tool returned a large file, the vendor measured the agent pausing up to 24 seconds on the Ryzen AI Halo and 39 seconds on the MacBook Pro before replying, against about 2 seconds on the GeForce RTX 5090.</li>
</ul>
<p>Two practical consequences follow. First, a workload that is mostly cache hits is still prefill-sensitive: the tokens you do have to read dominate wall-clock time, which is why low-precision compute and prefill throughput matter as much as memory bandwidth. Second, agent turns are bursty and long-tailed. A mean latency hides the turn where a tool dumped a file into context and the agent stalled for half a minute.</p>
<h2 id="the-comparability-contract-the-part-most-reviews-skip">The comparability contract: the part most reviews skip</h2>
<p>The tool enforces a contract, and the contract is the most useful thing in the documentation.</p>
<p>A full run needs a 65,536-token context at batch size 1. Every catalog profile launches at that context, and an attached server that serves more, such as 131,072 tokens, also counts as full. Anything below is marked <code>reduced: true</code> and is not comparable with full-context results. The default replay&rsquo;s largest turn needs about 58,000 tokens, so it only runs at the full 65,536; below that, the documented fallback is <code>aa-mini-v1</code>, which needs 8,192.</p>
<p>The <code>exact</code> policy sends <code>ignore_eos</code>, which is not part of the OpenAI API. Before the replay, <code>run</code> and <code>managed-run</code> check that the server honours it; if it does not, they stop and name the flag to change, and the TUI switches to the <code>recorded</code> policy instead and says so. This matters more than it looks: it means the tool refuses to silently publish a number that is not comparable.</p>
<p>The sharpest edge of this rule is Ollama. Ollama cannot honour <code>ignore_eos</code>. The tool detects Ollama before the run and warns, the run then uses the <code>recorded</code> policy, which lets the model stop on its own and reports end-to-end latency as a normalized estimate - and that result is not directly comparable with <code>exact</code> runs. In other words, the most widely installed local server on developer machines cannot produce a comparable AgentPerf run. If your plan was &ldquo;install Ollama, run the agent benchmark, compare to the published charts&rdquo;, the tool itself will tell you why that comparison does not hold.</p>
<p>For attached servers the tool reads the context at the start of the run: <code>meta.n_ctx</code> from llama.cpp, <code>max_model_len</code> from vLLM and SGLang, or <code>maximum_context_tokens</code> from the Splash status endpoint. A server that reports none of them is recorded as not comparable.</p>
<h2 id="tool-time-three-modes-three-different-questions">Tool time: three modes, three different questions</h2>
<p>Tool execution is skipped by default, so the default result answers &ldquo;how fast does this machine serve the model turns&rdquo;. Two opt-in modes answer different questions:</p>
<ul>
<li><code>run --tool-mode fixed_delay</code> sleeps after each turn for the tool time recorded there - useful when you want end-to-end session time to include realistic tool gaps without running anything.</li>
<li><code>run --tool-mode live</code> runs the recorded shell commands in Docker containers, so tool time is real. It is opt-in, needs Docker and prebuilt images, and the docs are explicit that the recorded commands are untrusted input and Docker is not a security boundary; Docker daemon access is equivalent to root on most hosts, the task workspace is mounted read-write under the output directory, containers have no network by default but a replay manifest can ask for one, and <code>--live-network none</code> forces no network.</li>
</ul>
<p>The build path matters for planning: the SWE-bench validation image script is arm64-only, so a live tool-mode run is not a same-day exercise on every laptop.</p>
<h2 id="how-to-run-it-on-your-own-box">How to run it on your own box</h2>
<p>The documented path is short. Install with <code>uv tool install agentperf-local</code> (or run it without installing via <code>uvx agentperf-local</code>; <code>pipx install agentperf-local</code> also works), then either point <code>run</code> at a server you already have:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>agentperf-local run \
</span></span><span style="display:flex;"><span>  --base-url http://127.0.0.1:8080/v1 \
</span></span><span style="display:flex;"><span>  --model served-model \
</span></span><span style="display:flex;"><span>  --output-dir results/my-server
</span></span></code></pre></div><p>or let the tool download, start and stop a pinned recipe itself:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>agentperf-local managed-run \
</span></span><span style="display:flex;"><span>  --profile-id qwen38-27b-q4-k-m \
</span></span><span style="display:flex;"><span>  --framework llama-cpp \
</span></span><span style="display:flex;"><span>  --output-dir results/qwen38-27b
</span></span></code></pre></div><p>Typical base URLs for attached servers are <code>http://127.0.0.1:8080/v1</code> for llama.cpp, <code>http://127.0.0.1:1234/v1</code> for LM Studio, <code>http://127.0.0.1:8000/v1</code> for vLLM and <code>http://127.0.0.1:30000/v1</code> for SGLang. API keys are passed by variable name with <code>--api-key-env</code>; no flag takes a literal key. <code>deployment-options --profile-id &lt;id&gt;</code> shows which frameworks can serve a recipe on that machine, and <code>doctor</code> prints local hardware facts without identifiers. Submission is optional and nothing is uploaded unless you ask.</p>
<p>The pinned recipes are the part worth copying even if you never use the tool: each is a YAML file pinning a model, a quantization and a framework version, and <code>managed-run</code> verifies each file&rsquo;s SHA-256 before serving. The Splash recipe is a good example - it pins Splash 1.2.1 and the <code>incoai/Qwen3.8-27B-Splash</code> package by commit, so it never resolves a newer revision.</p>
<h2 id="the-vendors-launch-results-with-the-label-they-need-vendor-results">The vendor&rsquo;s launch results, with the label they need (VENDOR RESULTS)</h2>
<p>These rows are Artificial Analysis&rsquo; own published results. We did not reproduce them, and every figure below is attributed to the vendor&rsquo;s announcement page and results page.</p>
<p>The launch hardware set is NVIDIA DGX Spark (128 GB), AMD Ryzen AI Halo (128 GB), MacBook Pro M5 Pro (64 GB) and NVIDIA GeForce RTX 5090 (32 GB), chosen to span CUDA, ROCm, Vulkan and Metal. The launch models are Qwen3.5-9B, Qwen3.8-27B, Qwen3.6-35B-A3B and Ling 3.0 Flash (124B total, 5B active), each benchmarked at 4-bit quantizations. All 14 published serving configs use speculative decoding (MTP, DFlash or DSpark), and where an official off-the-shelf config existed for a system and model pair the vendor used it.</p>
<p>The headline findings as the vendor states them:</p>
<ul>
<li>Completion time tracked each model&rsquo;s active parameter count most closely: Qwen3.6-35B-A3B (3B active) was fastest on every system, 2.5-3.3x faster than the dense Qwen3.8-27B; but Ling 3.0 Flash (5B active) still finished behind Qwen3.5-9B on all hardware that supports it.</li>
<li>The GeForce RTX 5090 was the fastest system for every model that fits in its 32 GB, with completion times more than 3.5x faster than the other systems, and more than 5x faster decode than the unified-memory devices - 1,792 GB/s of memory bandwidth against 256-307 GB/s.</li>
<li>The DGX Spark and the Ryzen AI Halo are broadly similar systems at the same $4,000 launch MSRP, yet the Spark was 1.4-1.7x faster on three of four models and tied on Qwen3.5-9B. The vendor attributes the gap, which is far larger than their 7% bandwidth difference, to the Spark&rsquo;s greater low-precision compute for prefill and its more mature CUDA software for MoE and speculative decoding.</li>
<li>The MacBook Pro (M5 Pro, 64 GB, 20-core GPU) finished within 2-9% of the Ryzen AI Halo on Qwen3.6-35B-A3B and Qwen3.8-27B while being 21% slower on Qwen3.5-9B, with the highest bandwidth of the three unified-memory systems at 307 GB/s.</li>
<li>Speculative decoding raised Qwen3.8-27B decode speeds roughly 30-120% above the bandwidth-constrained roofline on the most successful configs.</li>
<li>On price, the vendor states that most hardware is significantly inflated versus launch MSRP, that the page defaults to launch MSRP with custom price entry allowed, and that at current market prices the MacBook Pro is the cheapest and the RTX 5090 system by far the most expensive.</li>
</ul>
<p>Read those rows as vendor-run numbers under the vendor&rsquo;s own configs. The announcement page does not publish per-run raw traces, and no third party has replicated them.</p>
<h2 id="what-we-checked-on-our-own-hardware-and-what-it-is-not">What we checked on our own hardware (and what it is not)</h2>
<p>To verify that the client behaves as documented rather than to measure any hardware, we ran a bounded smoke run on our build box on 2026-10-15 between 00:12:32Z and 00:13:46Z: <code>agentperf-local</code> 0.3.3, the six-turn <code>aa-mini-v1</code> replay, against Ollama 0.20.3 serving qwen2.5:0.5b on an aarch64 box with 2 vCPUs, about 12 GiB of memory and no supported accelerator. We measured 6 successful turns out of 6, zero failures, 5 tool calls and 67.5 seconds of measured replay time.</p>
<p>The interesting output was not the timing. The client emitted both comparability guards on its own: the documented warning that Ollama cannot honour <code>ignore_eos</code> so the run uses the <code>recorded</code> policy and reports a normalized latency estimate, and a second warning that the endpoint did not prove its context window, so the run was recorded with <code>reduced: true</code> and marked not eligible for ranking. Every one of the six turns was additionally flagged as short output - 29 generated tokens against a 256-token target in the example we inspected - because a 0.5B model cannot follow a recorded trajectory.</p>
<p>That is exactly the evidence trail you want from a benchmarking tool, and it is also why none of those numbers may be quoted as a performance result. This was not the 168-turn workload, not full context, not an <code>exact</code>-policy run and not a hardware benchmark; it is a private local author check that the install path and the guard rails work. If you want a number that means something, you have to produce it on your own hardware.</p>
<h2 id="how-to-read-any-agentperf-number-honestly">How to read any AgentPerf number honestly</h2>
<p>Before you compare two results, or quote one, check that the following travel with the number: the tool version and client (Python or the experimental Rust client), the replay ID (<code>agentperf-default-v1</code> or something else), the context in tokens and whether <code>reduced: true</code> was recorded, the output policy (<code>exact</code> or <code>recorded</code>), the tool mode (none, fixed_delay or live), the model and quantization, the serving framework and the pinned recipe or config, and the hardware. If the run was submitted, <code>run --attached-server FILE</code> is what makes a run on a server you started traceable.</p>
<p>If any item is missing, treat the result as directional. Two numbers produced under different output policies, different context sizes or different tool modes are not a comparison; they are two different experiments.</p>
<h2 id="limitations-we-are-stating-up-front">Limitations we are stating up front</h2>
<ul>
<li>Every hardware, model, price and percentage figure in the vendor-results section is the vendor&rsquo;s own published claim, labelled as such; nothing in this article is an independent replication.</li>
<li>We did not run the default 168-turn replay, no managed pinned recipe, no vLLM, SGLang or Splash target, no <code>fixed_delay</code> or <code>live</code> tool-mode run, and no power measurement (the tool&rsquo;s GPU power sampling is NVIDIA-only).</li>
<li>The recorded task set behind <code>agentperf-default-v1</code> is not enumerated in the public documentation we read, so the workload cannot be independently reconstructed from the docs alone.</li>
<li>The project is young and moving: the tool was first published in late September 2026 and the package version we checked, 0.3.3, was released on 2026-10-01. Star counts, open issues, recipes and hardware rows will date quickly.</li>
</ul>
<p>For the surrounding decisions, see our companion pieces on <a href="/posts/local-ai-model-serving-frameworks-2026/">local AI model serving frameworks</a>, <a href="/posts/vllm-vs-ollama-production-2026/">vLLM versus Ollama in production</a>, <a href="/posts/llm-benchmarks-api-hosting-comparison-2026/">LLM benchmarks and API hosting</a> and <a href="/posts/llm-inference-engineering-guide/">LLM inference engineering</a>.</p>
<h2 id="sources">Sources</h2>
<ul>
<li>Project repository (Apache-2.0): <a href="https://github.com/ArtificialAnalysis/aa-agentperf-local">https://github.com/ArtificialAnalysis/aa-agentperf-local</a></li>
<li>README as read on 2026-10-15: <a href="https://raw.githubusercontent.com/ArtificialAnalysis/aa-agentperf-local/main/README.md">https://raw.githubusercontent.com/ArtificialAnalysis/aa-agentperf-local/main/README.md</a></li>
<li>Licence file: <a href="https://github.com/ArtificialAnalysis/aa-agentperf-local/blob/main/LICENSE">https://github.com/ArtificialAnalysis/aa-agentperf-local/blob/main/LICENSE</a></li>
<li>Package metadata: <a href="https://github.com/ArtificialAnalysis/aa-agentperf-local/blob/main/pyproject.toml">https://github.com/ArtificialAnalysis/aa-agentperf-local/blob/main/pyproject.toml</a></li>
<li>Repository metadata (created/pushed dates, stars, issues): <a href="https://api.github.com/repos/ArtificialAnalysis/aa-agentperf-local">https://api.github.com/repos/ArtificialAnalysis/aa-agentperf-local</a></li>
<li>Releases endpoint: <a href="https://api.github.com/repos/ArtificialAnalysis/aa-agentperf-local/releases">https://api.github.com/repos/ArtificialAnalysis/aa-agentperf-local/releases</a></li>
<li>Published package metadata: <a href="https://pypi.org/pypi/agentperf-local/json">https://pypi.org/pypi/agentperf-local/json</a></li>
<li>Vendor announcement (VENDOR RESULTS quoted above): <a href="https://artificialanalysis.ai/articles/aa-agentperf-local">https://artificialanalysis.ai/articles/aa-agentperf-local</a></li>
<li>Vendor laptops and workstations results page: <a href="https://artificialanalysis.ai/hardware-inference-stack/laptops-workstations">https://artificialanalysis.ai/hardware-inference-stack/laptops-workstations</a></li>
</ul>
]]></content:encoded></item></channel></rss>