You ask a coding agent to fix a bug. A little later, an answer appears. What ran in between? This page follows one real task, step by step, through the model server, the software that steers the agent, and the ordinary computer that searched, edited, compiled, and tested the code. The task is not one model call. It is a loop, and most of that loop runs on a CPU.
See how one task moves through the whole machine.
Let's walk the sixteen steps of one real task through the actual machine. Press play and the camera goes to the part doing the work: the MacBook Pro you typed on (and, because Codex runs its tools locally, the logic board inside it), or the model server in its rack. Software steps show the window they run in. Anything ghosted is a part this trace never touched.
The deployment is illustrative. The separately measured fixture ran on an Intel Core i7-9750H host with Darwin/x64—not on Vera Rubin. No live model, Linux container, provider device, or network path was measured.
Task “Find why the duration formatter says ‘60 min’ instead of ‘1 hr,’ fix it, and verify the change.”
01 User submits the debugging task, representative, wall time not captured
01 Your sentence leaves the laptop.
02 Before any model sees it, a program writes the model's briefing.
03 The request reaches a machine you will never see.
04 The model's suggestion becomes a permitted command.
05 A scratch copy of the code is made first.
06 A search program reads through the files looking for the bug.
07 The suspect file is opened.
08 The compiler turns the code into something that can run.
09 The tests run, and two of them fail, as expected.
10 The failure goes back to the model for a diagnosis.
11 The fix is written into the file.
12 The compiler runs again on the fixed code.
13 All three tests pass.
14 The proof is packaged for the model.
15 The model would write the answer from that proof.
16 The answer lands back on your screen.
codex harness, session, build context
context ← system prompt
context ← AGENTS.md, repository notes
context ← 16 tool schemas (shell, read, edit, …)
context ← task: "Find why the duration formatter says '60 min' instead of '1 hr,' fix it, and verify the change."
→ request #1 to the model service
model service, request #1, not executed
POST /responses
input: system, AGENTS.md, tools[16], task
── response (what a live model would return) ──
tool_call shell: rg -n 'formatDuration|minutes' src test tsconfig.json
latency: null tokens: null device: not observed
workspace: /private/tmp/mts-agent-stack.wLugI3
copy 5 fixture files, hash sha256
in-process, no shell spawned 9 ms
bash, execution host
$ /usr/bin/time -lp rg -n 'formatDuration|minutes' src test tsconfig.json
src/format-duration.ts:1:export function formatDuration(minutes: number): string {
src/format-duration.ts:2: if (minutes >= 60) {
src/format-duration.ts:3: return `${minutes} min`;
…real 0.01 user 0.00 sys 0.00 3887104 max RSS exit 0
bash, execution host
$ sed -n 1,160p src/format-duration.ts
export function formatDuration(minutes: number): string {
if (minutes >= 60) {
return `${minutes} min`;
}
return `${minutes} min`;
}
real 0.00 602112 max RSS exit 0
bash, execution host
$ node node_modules/typescript/bin/tsc
(no output)real 1.34 user 2.40 sys 0.19 320258048 max RSS exit 0
bash, execution host
$ node --test test/format-duration.test.mjs
✔ leaves durations shorter than one hour in minutes✖ converts an exact hour to a singular hour label✖ formats partial and plural hours
ℹ tests 3 ℹ pass 1 ℹ fail 2
exit 1
model service, request #2, not executed
input: + tool_result (exit 1, 2 failing assertions)
── response (what a live model would return) ──
apply_patch src/format-duration.ts
not executed: the reviewed fix was scripted
$ node node_modules/typescript/bin/tsc
(no output)real 1.55 user 2.74 sys 0.23 319369216 max RSS exit 0
bash, execution host
$ node --test test/format-duration.test.mjs
✔ leaves durations shorter than one hour in minutes
✔ converts an exact hour to a singular hour label
✔ formats partial and plural hours
ℹ tests 3 ℹ pass 3 ℹ fail 0
exit 0
codex harness, process result
← exit 0, stdout: 3 passed
attach: exit code, test output, diff src/format-duration.ts
→ request #3 to the model service
model service, request #3, not executed
input: + tool_result (exit 0, 3 passed), diff
── response (what a live model would return) ──
message: the fix and its verification
latency: null tokens: null device: not observed
Let's start where you are: a MacBook Pro with an Intel Core i7-9750H, running macOS. You type one sentence into the Codex CLI and press enter. What leaves the machine is an ordinary HTTPS request, the same kind your browser sends. From this moment you are waiting. Nothing about the request itself was timed.
The request arrives at the harness. The harness is a program, not a place, so it gets a window here instead of a box. Its first job is to write the model's briefing: the standing instructions, the notes about this repository, the list of sixteen tools the model is allowed to ask for, and your sentence. All of that is ordinary CPU work, and it happens before any model does anything. This trace documents the step but did not time it.
Now the briefing crosses a boundary into a model server, drawn here as NVIDIA's published Vera Rubin design. Think of that board as two workers at a shared desk. The CPU on the left runs the serving program and prepares the request. The GPU on the right does the model's arithmetic, reading its weights from the memory stacked beside it. A link between them lets the two share memory directly. A live model would send back one small decision: search the repository. This trace never called a live model, so the board stays ghosted and every number on the request card is null.
The model's suggestion comes back to the harness as a proposed tool call. Before anything runs, a second program, the tool router, checks it against policy: a read-only search is allowed. Then it sends the command down the tool path to the machine that will actually do the work. Still documented behavior, still not timed.
Here is the first thing that was actually measured, and it happens back on your own Mac: Codex runs its tools locally, so the keyboard deck lifts and the logic board is in view. Before the agent touches the code, the harness makes a scratch copy: five files go into an isolated working folder on the SSD and are SHA-256 hashed, in 9 ms. Notice the transparent box around the board. A Linux container would wall this work off from the rest of the machine; in this run, none was started.
The search starts as its own process on the Intel Core i7-9750H: rg, the ripgrep tool, reads through the source and test files looking for formatDuration and minutes and prints every line that matches. The terminal shows the exact command and what came back: 18 ms, 4 MB of memory at peak, exit code 0. The model asked; a CPU answered.
Now the agent opens the suspect file with sed. Seven lines come back from the SSD in 5.9 ms, and you can already see the bug: sixty minutes or more still prints as minutes. One honesty note: those are logical bytes. Whether they came from the SSD or from the page cache in RAM was not measured.
tsc, the TypeScript compiler, is the heaviest worker in this task. It reads the code, checks its types, and emits JavaScript that Node.js can run. Watch the six cores fill and the memory slab rise: 1,352.2 ms of waiting, 2,400 ms of CPU time because the work spread across several cores at once, and 320 MB peak resident set out of 64 GB. Nothing here touched a GPU.
node --test runs the three tests: 220 ms, exit code 1. Two of three fail, because 60 minutes and 90 minutes still print as minutes. That flag is the point of the whole round. A failing test is not a mistake; it is the evidence the model needs to decide what to change.
The two red lines travel back across the boundary to the model service. A live model would read them and propose an edit to the file. In this trace that did not happen: the fix was written in advance by the people who built the fixture, so the GPU stays ghosted and carries no number.
The corrected code replaces the old file on the SSD in 2.2 ms. Read the diff in the window: the old line returned minutes no matter what; the new lines divide by sixty and pick hr or hrs. Even a tiny edit like this is a CPU and storage event.
tsc again, same job, on the fixed code: 1,559.2 ms of waiting, 2,740 ms of CPU time, 319 MB peak resident set. Slightly longer than the first pass.
node --test runs the same three tests again: 199 ms, exit code 0. All green. This pair of results, red before the edit and green after, is the only proof this task has that the fix worked.
Back in the harness. It collects the exit code, the three passing lines, and the diff, and packs them into the next briefing so the model can see what happened. Documented behavior; production timing unknown.
One last crossing to the model service. A live model would read the proof and write the answer you see on screen. Not executed here. The switch, the network card, and the tray behind the board are context from NVIDIA's published design, not parts of this measured path.
The answer lands on the MacBook's screen. Pull back and the whole loop is in view: 3 visits to the model server, 8 programs that ran on the Intel Core i7-9750H, one tool path carrying every command. Add up what was measured and you get about 3.4 seconds, all of it on the CPU side. The model's share is unknown, and this page will not guess it.
Event 1 of 16
Accelerated model system
Network + infrastructure
Agent + execution
1 / 16
Illustrative Codex deployment: one tangible arrangement, not a claim about production. The NVIDIA parts are a published design, not the machine this trace ran on. Official NVIDIA component imagery, cropped from the January 2026 Rubin platform launch view; NVIDIA later described a seventh chip. NVLink 6 is shown as scale-up context and is distinct from the NVLink-C2C connection. View source ↗
Figure 1. One debugging task repeatedly crosses model, control, and execution boundaries. Selection marks a causal locus, not utilization or workload share. 8 environment-side spans were observed in the separate fixture; the NVIDIA hardware is official vendor imagery used as architecture context.
Sequence: OpenAI agent-loop and harness documentation; Anthropic managed-agent engineering; MTS fixture capture. Hardware image and specifications: NVIDIA. Vendor claims are labeled and the provider boundary remains unobserved.
The answer arrives in rounds.
Why does one question take sixteen steps? Because the chat window shows you two things, your request and the answer, and hides everything in between. Let’s open that gap up.
Here is what actually happens. A coding agent does not answer your question. It asks a model a much smaller one: what should I do next? The model replies with an action, such as search the repository for the formatter. Software around the model, the agent harness, carries that action out on a real computer, collects what came back, and asks the model again: now what? That is one round. One user turn can contain many model calls. The task is a stack of rounds, and it ends only when the model says it is finished, a limit is reached, or something breaks.
Follow the trace and you can count the rounds. The first useful action is not an answer. The agent has to locate the formatter and its tests. Search results identify the files. The source reveals the faulty condition. A compiler checks the program. A failing test confirms the behavior. That failure is not the end of the task. It is new information for the next round.
How many rounds is normal? There is no typical number, but there are measured ones. In the Autellix systems study, the evaluated ShareGPT and BFCL traces averaged 6.66 and 10.75 model calls, with maxima of 80 and 70; a tree-search LATS workload averaged 159.7. Those are research workloads, not a typical count for Codex. They make one point: a single chat turn is not a meaningful unit of hardware work.
Each round covers real distance. The request leaves your machine, waits in a queue, is prepared by CPU-side serving code, runs on an accelerator, and travels back, all before the harness can start the tool. Then the tool creates its own processes and its own reads and writes. Notice what this does not mean: there are not hundreds of identical CPU-to-GPU hops, and not every step uses both kinds of chip. The number and shape of the handoffs depend on the program, the serving system, batching, where the tools live, and when the loop is told to stop.
One more thing hides in the word context. The session record and what the model actually sees are not the same. A long-running agent keeps a durable history but retrieves, summarizes, or selects only what the next request needs. Choosing that is work too: it costs CPU time, memory, storage, and sometimes a network call before the accelerator sees a single token.
A tool call becomes work on a real computer.
What does “run the tests” actually make a computer do? Let’s take one tool call apart. “Search the repository,” “read this file,” and “run the tests” are structured requests, not the work itself. The harness must translate each one into operations a computer can perform.
Start with the search in Figure 1, step six. The harness asks the operating system to start a program, gives it permissions and a place in the filesystem, and hands it the command. That program may start others. A shell can launch a search tool; a package script can launch a compiler; a test runner can create workers. The operating system schedules their instructions, maps memory for them, serves their file requests, captures their output, and reports whether they exited successfully. Every one of those things is CPU work.
You will hear the word sandbox for the fence around this activity. It describes permissions, not one universal kind of machine. Depending on the product, an agent may be constrained by operating-system rules, a container, a virtual machine, or several layers together. The fence controls which files, networks, credentials, and system calls a process can reach. It does not make the work abstract.
The measured fixture ran a small version of this path, and you watched it: an isolated working directory, a bounded search, one file read and one file replaced, two compiles, and the same tests run before and after the edit. The first run failed in the expected way. The second passed all three assertions. For each subprocess the capture kept elapsed time, coarse user and system CPU time, peak resident memory, and the exit code.
Those numbers need careful reading; steps eight and twelve in Figure 1 are the place to look. Elapsed time is how long a person waits for a command to return. CPU time counts up while cores execute that process’s instructions, so a compiler spread across several cores can rack up more CPU time than wall time; that is exactly what the two compile steps show. A process can also spend its wall time waiting: for a file, a child process, a lock, or a network reply. One duration cannot tell you which part was busy at every instant.
Files carry the same ambiguity. The byte length of a source file is not physical device traffic. The file may arrive from a cache in memory; metadata and dependencies may cause more reads than the named file; writes may be buffered. The fixture records the logical bytes it handled, not total filesystem traffic, cache behavior, or storage queueing.
Network is plural as well. The laptop talks to a harness service; the harness calls a hosted model; a tool may use local input and output or remote HTTP; a build may reach a package registry; a browser may contact many origins. A single model-latency number can include transport and provider-side waiting that the client cannot separate.
One concrete architecture makes the roles visible.
Where does each of those steps physically live? Agent systems can place these layers in different locations. Figure 2 chooses one tangible arrangement so the path does not dissolve into boxes labeled “compute.” Here is how to read it.
At one end is a MacBook Pro running Codex: the only part you can see. Between it and everything else sits the control layer, the harness that keeps the session and routes tools; it runs on a server somewhere, so the figure shows it as the log it writes rather than as a box. The work itself lands on a test machine. In the figure that is a Linux container, Node.js, TypeScript, and an NVMe workspace, drawn as one logic board. The observed fixture was narrower than that picture: an Intel Core i7-9750H host running Darwin/x64, an isolated temporary directory, and a bounded set of search, compile, edit, and test operations. It is a laptop-class chip, and every measured step in this task ran on it.
At the far end is the model server, and here the figure borrows NVIDIA’s published Vera Rubin platform because it makes the roles legible. Think of that board as two workers at a shared desk. Vera, the CPU, runs the serving program: it takes the request off the network, prepares it, and feeds the accelerator. Rubin, the GPU, does the model’s arithmetic. HBM4 is the desk Rubin works from, the memory that holds the model’s weights close enough to read at full speed. NVLink-C2C is the door between the two workers, wide enough that they can read each other’s memory instead of copying it. Around them, ConnectX-9 is where the request arrives, BlueField-4 moves data so the CPU does not have to, and Spectrum-6 connects the board to the rest of the building. Model serving is already a whole system, not a GPU in isolation.
Now the honest part. That board tells you where work could live. It does not say how Codex is deployed, which device handled this task, how much time or energy each part used, or whether a queue at the provider dominated the wait. The trace did not run on Vera Rubin and did not observe its coherent link. The event record says what the fixture actually saw; the board is there so the words CPU, GPU, and memory point at something real.
Memory needs the same care, because the word covers several different things. The laptop’s working memory, the operating system’s file cache, a sandbox’s saved state, the GPU’s weights, its activations, and its KV cache are not interchangeable. Capacity is not bandwidth. Peak use is not average use. Allocated memory is not consumed memory. A useful trace names the memory it measured and leaves the rest unknown.
The slowest component is not always the bottleneck.
The compiler took 1.4 seconds and the model took an unknown time, so which one made you wait? A task finishes when its chain of dependencies finishes. The component holding that chain open can change from one step to the next.
Look at the two compile steps in Figure 1, then at the three model steps that carry no number. During a compile, several cores are busy and nothing else can proceed; during a model call, the same cores sit idle while a remote request is answered. A warm file read is almost invisible; a cold dependency install can dominate a task. A model endpoint can be slow because of queueing, batching, transport, or the inference itself. So faster model serving helps only the model spans, and faster execution helps only the environment spans, and only when they are the ones the chain is waiting on.
Put many agents on the same hardware and the machine changes without the task changing. Agents wait for a model slot, a tool worker, a sandbox, a process slot, a CPU core, a storage operation, a connection, a rate limit, or a human approval. Batching can raise accelerator throughput while making the first token slower. Shared CPU caches, memory channels, storage, and network links become contended even when a single-agent run looked comfortable.
That is why a trustworthy systems trace needs parent-child relationships, monotonic timestamps, queue boundaries, and a distinction between active work, transport, blocking, and waiting on a dependency. Add every component’s duration together and you double-count overlap. Look only at elapsed time and you hide who worked and who waited.
Sources: OpenAI documentation on the Codex loop, harness, tool execution, and sandbox safety; Anthropic engineering on managed agents and containment; Autellix on multi-call agent programs; NVIDIA Vera CPU and Rubin platform documentation; and the disclosed MTS fixture. Direct links and qualifications appear in Methodology.
A solved task does not explain the system that solved it.
So could you just benchmark this? Here is the gap. The fixture proves a red-to-green outcome. Existing benchmarks usually measure task success, inference, or an execution substrate. Few expose the physical critical path connecting all three.
Coding-agent benchmarks such as SWE-bench ask whether a system can resolve a software issue. Inference benchmarks such as MLPerf measure bounded model serving. Both answer important questions, but neither result alone reconstructs the journey you just watched, from user request through model calls, tools, processes, files, verification, and final response.
Closest public full-loop study found, but recent, unreproduced, mixed local/API visibility, and code-unreleased at review time.
Outcome framing: SWE-bench and SWE-bench Verified. Inference framing: MLPerf Inference. Emerging whole-loop work: AgentSysBench, a recent preprint without released code or independent reproduction at review time.
The completed task is the unit that matters.
Let’s put it back together. An agent is not a model with accessories. It is a computer system organized around repeated model decisions and observations from the world outside the model.
The model proposes. The harness prepares, checks, routes, and remembers. The execution environment turns requests into processes. Memory and storage hold working state. Networks connect whichever parts are remote. Tests, browsers, databases, and other tools return the evidence that decides what happens next. In the task you followed, three of sixteen steps belonged to the model, and every measured millisecond belonged to a CPU.
Improving one stage helps only when that stage is the one holding up the task. The durable lesson of the sixteen-step trace is to follow the work all the way through, record what each step touched, and keep the places where the instrumentation stops visible instead of filling them in.
The useful question is no longer only, “How fast was the model?” It is: What path did the task take, where did it wait, and what evidence tells us so?
What was measured—and what remains null
Missing and unknown do not mean zero. Every null on this page is listed here with its reason, so the gaps stay attached to the record without becoming a second story.
Not executed: No live model call, container startup, or browser run occurred. Therefore Model identity, Tokens, Model latency, Container startup, and Browser execution remain null.
Not instrumented: The fixture recorded command timing, peak resident memory, exits, and selected logical bytes—but not CPU utilization, Total filesystem traffic, Network bytes, Energy, or Task allocation. Those values remain null.
Outside the observer boundary: Provider CPU/GPU activity, Accelerator identity, Internal queueing, Serving topology, and per-request energy are unavailable without self-hosting or provider cooperation. Those values remain null.
Inspect local measurements, transformations, and 24 direct sources
Observed local spans
Observed event
Wall
User CPU
System CPU
Peak memory
Exit
Create an isolated working copyenvironment
8.98 ms
Not executed
Not executed
Not executed
0
Search for the formatter and its teststool
18.0 ms
Below 10 ms resolution
Below 10 ms resolution
3.9 MB
0
Read the faulty implementationtool
5.89 ms
Below 10 ms resolution
Below 10 ms resolution
602.1 kB
0
Compile the initial TypeScriptverification
1352.2 ms
2400.0 ms
190.0 ms
320.3 MB
0
Behavior test fails as expectedverification
220.0 ms
180.0 ms
40.0 ms
41.8 MB
1
Apply the reviewed formatter fixtool
2.18 ms
Not executed
Not executed
Not executed
0
Compile the fixed TypeScriptverification
1559.2 ms
2740.0 ms
230.0 ms
319.4 MB
0
All three behavior tests passverification
199.0 ms
160.0 ms
40.0 ms
41.3 MB
0
Transformations
The raw harness trace is preserved unchanged under research/agent-infrastructure/trace/raw/observations.json.
Measured command spans were normalized into the publication schema without converting null values to zero.
Documented context, tool-routing, model, and result-processing boundaries were added as representative events with null measurements.
Observed timings retain millisecond values; visual widths use an editorial sequence so missing provider latency is never implied.
Important limitations
No model or paid API was called, so the trace is not a production Codex or Claude Code telemetry capture.
Model identity, tokens, inference latency, provider CPU/GPU activity, queueing, utilization, and energy are missing.
CPU time is a command total at 0.01-second source precision, not sampled utilization or loaded-core performance.
Storage figures are selected logical file sizes, not total filesystem or device traffic; network bytes were not measured.
One deterministic fixture cannot establish an industry-wide CPU/GPU workload share.
The article was updated in March 2026 to add a seventh platform chip; the reused January Figure 4 remains the original six-chip lineup and must be dated as such.
No live model or paid API was called. Registry version 1.0.0. Machine-readable endpoints: summary, trace, and sources and claims.