Evaluating Agents Across Runtime Contracts: When Mismatch Costs Efficiency or Quality
Organizations: Ontocord · École Polytechnique · Carnegie Mellon University · MPI-IS Tübingen ·
Abstract
In CodeAct, language-model agents write Python that calls tools and use execution feedback to choose actions. Persistent runtimes preserve Python variables between actions; stateless runtimes clear them without resetting task progress. Training traces demonstrate task-solving strategies and runtime-specific ways to store and recover intermediate results. We study runtime transfer: whether agents trained under one contract remain effective under the other, a dependence that fixed-runtime evaluations can conceal. Across three tasks requiring a working record built from tool feedback, we fine-tune separate Qwen3-8B agents per task and runtime on instance-paired persistent and stateless traces and evaluate all four training-deployment combinations. We vary the per-turn tool-call cap: how many calls one Python action may execute. In our primary task, agents inspect hidden item attributes and select a high-value subset under a weight limit. At 80 calls per turn, a persistent-trained agent deployed statelessly scores 0.61 of optimal value against 0.77 under matched persistent deployment, but uses 4.4 times as many tokens rebuilding its record. Tightening the cap to 25 reduces mismatched quality to 0.07 while matched quality remains 0.66. Trace replay shows that the cap interrupts inspection, the reset erases the partial record, and rebuilding consumes calls needed for progress. The widening gap replicates across training seeds, a second rollout, and two additional base models. Across the settings studied, cap tightening produces a mismatch-specific collapse only where interruptions are frequent and matched execution resumes while mismatched execution restarts. Evaluations of trace-fine-tuned agents should specify episode limits, test runtime transfer across caps, and report cost alongside quality; otherwise, the same mismatch may appear as redundant computation or near-total quality loss.
Figures & tables
| Training runtime | Persistent deployment | Stateless deployment |
|---|---|---|
| Persistent | : matched | : main mismatch |
| Stateless | : reverse transfer | : matched |
| Task | Working record | What a reset disrupts |
|---|---|---|
| Opaque Knapsack | Table of inspected items | A reset erases the table left by a cut |
| Navigation | Map of locks, traps and keys | A reset erases a partly checked map |
| Rule Diagnosis | Probes and a revised hypothesis | A reset breaks the gathered evidence |
| Limit | What it controls |
|---|---|
| Per-turn cap | Tool calls inside one action block |
| Task budget | How much hidden task information the agent may reveal |
| Turn limit | Model calls an episode may attempt |
| Token and context limit | Maximum transcript length |
| Wall-clock limit | Maximum execution time |
| -trained | -trained | cost | |||||
|---|---|---|---|---|---|---|---|
| Cap | Runtime gap | Tokens/ep. | Cap-hit | ||||
| (binding) | 0.66 | 0.12 | 0.26 | +0.59 [+0.46,+0.71] | 498k | 71% | |
| (slack) | 0.77 | 0.61 | 0.23 | 0.51 | +0.15 [+0.00,+0.32] | 162k | 4% |
Appendix figures & tables20 assets
Supplementary material from the paper’s appendix.
Appendix
| Task | Latent information | Working record | Verifier | Key anti-collapse constraint |
|---|---|---|---|---|
| Opaque Knapsack | Item attributes and the allowed-class set | Inspected-item table | Exact DP optimum over allowed items | Non-degenerate optimum: optimal set items, no item above of optimal value |
| Navigation | Graph mechanics: traps, keys, locks | Map, keys, traps, locks | Goal / shortest-path progress score | Exactly locked gate into the goal, its key reachable trap-free |
| Rule Diagnosis | Hidden piecewise rule | Probe map and hypothesis | Exact latent rule | intervals of length , at least two internal breakpoints |
| Call return | Budget / constraints |
|---|---|
| list_items() JSON array of all opaque item IDs | Free (no budget cost). |
| inspect(id) JSON {"weight","value","class"} | Consumes one unit of on the first inspection of an ID, and repeat inspections are cached and free. Errors if is exhausted or the ID is unknown. |
| take_item(id) None | Adds the item. Errors if already taken, of a disallowed class, or if it would exceed . Every rejection is checked before any state change, and there is no drop tool, so an accepted take is irreversible. |
| finish() None | Terminates the episode (runtime-provided). |
| Component | Persistent condition | Stateless condition | Changes with cap? |
|---|---|---|---|
| Interpreter bindings | Survive the turn boundary | Cleared each turn | No |
| active_globals | Prior names shown as active | Empty | No |
| State rule | “globals persist; never re-paste code” | “state resets; redefine each step” | No |
| Few-shot behavior | Reuses variables across turns | Prints and rebuilds state | No |
| Tool-cap instruction | Same wording with substituted | Same | Yes |
| Setting | Value |
|---|---|
| Teacher | Gemini 3 Flash ( gemini/gemini-3-flash-preview ) |
| Teacher runtime | Runtime-matched (one rollout per instance per runtime) |
| Teacher cap / turns (Opaque Knapsack) | / |
| Candidate pairs | 1,900 |
| Dual-valid pairs | 1,109 (58.4% paired yield) |
| Retained pairs | 1,000 per training runtime (seeded shuffle, seed ) |
| Qwen3-8B | Mistral-7B-v0.3 | Llama-3.1-8B | |
|---|---|---|---|
| Base checkpoint | Qwen/Qwen3-8B | mistralai/ | meta-llama/ |
| Mistral-7B-v0.3 | Llama-3.1-8B | ||
| Adaptation | QLoRA, 4-bit NF4, double quantization, bfloat16 compute | ||
| Rank / / dropout | / / | ||
| Modules | All attention and MLP projections ( ) | ||
| Epochs / optimizer / LR | / AdamW, cosine, peak , warmup , decay | ||
| Cap | Condition | Quality (95% CI) | Steps | Listing calls | Tokens | Cap-hit% | NameErr | Fin/turn/to |
|---|---|---|---|---|---|---|---|---|
| (matched) | 9.8 | 1.1 | 113k | 41 | 0.04 | 19/6/0 | ||
| (mismatch) | 35.2 | 30.8 | 498k | 71 | 5.44 | 2/23/0 | ||
| 18.6 | 1.0 | 288k | 36 | 0.00 | 6/16/3 | |||
| (matched) | 11.2 | 1.0 | 172k | 15 | 0.00 | 6/10/9 | ||
| 4.6 | 1.0 | 37k | 0 | 0.00 | 24/1/0 | |||
| 13.0 | 7.9 | 162k | 4 | 3.80 | 18/7/0 |
| Quantity | Definition |
|---|---|
| Cap hit | The logged step’s interpreter error reports the per-turn tool-call limit exceeded, and a cap-rejected call does not decrement the task inspection budget (App. D.1 ) |
| Missing binding ( NameErr ) | The logged step’s interpreter error contains NameError , the signature of a reset destroying a binding the policy assumed persisted |
| Post-cap restart | The next executed turn after a cap hit reissues the task’s index or listing operation ( list_items , neighbors ) before acquiring anything new. This is conditional on a cap hit, unlike the unconditional listing-call count in Table 10 |
| Termination | Exactly one of: finish() called, maximum turns reached, or episode wall-clock timeout |
| Exposure | The fraction of a condition’s slack-cap action blocks whose replayed call count exceeds (App. D.2 ) |
| Seed | Cap | |||||
| Primary evaluation, seed-0, | ||||||
| 0 | 25 | 0.662 | 0.075 | 0.115 | 0.262 | |
| 0 | 80 | 0.766 | 0.615 | 0.232 | 0.505 | |
| Sign-replication set, common task IDs | ||||||
| 0 | 25 | 0.722 | 0.039 | 0.166 | 0.109 | |
| 0 | 80 | 0.796 | 0.752 | 0.112 | 0.326 | |
| Cap | 10 | 20 | 25 | 30 | 40 | 50 | 80 | 100 |
|---|---|---|---|---|---|---|---|---|
| (mismatch) | 0.00 | 0.00 | 0.05 | 0.05 | 0.23 | 0.23 | 0.64 | 0.55 |
| (matched) | 0.40 | 0.54 | 0.60 | 0.57 | 0.60 | 0.73 | 0.64 | 0.61 |
| Setting | Inspect calls | Unique items | Replay frac. | Coverage | Decision | Post-cap restart |
|---|---|---|---|---|---|---|
| , (matched) | 89 | 36.8 | 0.59 | 0.83 | 0.80 | 0.00 |
| , (mismatch) | 681 | 25.7 | 0.96 | 0.71 | 0.09 | 0.84 |
| , | 660 | 38.2 | 0.94 | 0.81 | 0.33 | — |
| Setting | Tool organization | Restart | Restart | Interpretation | |
|---|---|---|---|---|---|
| Opaque Knapsack | Long batched inspection | 0.53 | 0.00 | 0.84 | Mismatch-specific failure |
| Navigation | Broad batched topology | 0.04 | Too few events | Too few events | Cap rarely exposes mismatch |
| Navigation | Narrow topology batches | 0.42 | 0.98 | 0.94 | Both runtimes deteriorate |
| Rule Diagnosis | Short adaptive probe cycles | 0.00 | — | — | No exposure |
| Task | Condition | Tokens @ | Tokens @ | ||
|---|---|---|---|---|---|
| Navigation | (matched) | 0.55 | 0.68 | 142k | 155k |
| (mismatch) | 0.41 | 0.38 | 352k | 366k | |
| 0.32 | 0.44 | 292k | 228k | ||
| (matched) | 0.53 | 0.33 | 200k | 256k | |
| Rule Diagnosis | (matched) | 0.70 | 0.69 | 102k | 61k |
| (mismatch) | 0.33 | 0.41 | 77k | 108k |
| Task | ||||||
|---|---|---|---|---|---|---|
| Navigation | ||||||
| Rule Diagnosis |
| Quantity | Carry | Carry (re-run) | Announced | ||
|---|---|---|---|---|---|
| Quality | 0.038 | 0.132 | 0.575 | 0.081 | 0.080 |
| NameError turns/ep | 9.6 | 1.3 | 0.1 | 6.0 | 5.0 |
| … of them on carried turns | 6.2 | 0.0 | 0.1 | 0.0 | 0.0 |
| Re-derives after a truncation | 0.76 | 0.76 | 0.00 | 0.86 | 0.31 |
| Distinct items | 24.2 | 28.2 | 34.1 | 28.0 | 29.6 |
| Decision achieved/OPT( ) | 0.08 | 0.23 | 0.72 | 0.11 | 0.11 |
| (matched) | |||
|---|---|---|---|
| (mismatch) | |||
| overflow | |||
| overflow | — | — |
| Cap | Condition | Attempted | Steps | Failed | Context | Rejected |
|---|---|---|---|---|---|---|
| (matched) | 13.2 | 9.8 | 85 | 85/85 | 0 | |
| (mismatch) | 37.3 | 35.2 | 52 | 52/52 | 0 | |
| 27.8 | 18.6 | 229 | 227/229 | 0 | ||
| (matched) | 21.6 | 11.2 | 260 | 260/260 | 0 | |
| 4.6 | 4.6 | 0 | 0/0 | 0 | ||
| 14.5 | 13.0 | 37 | 37/37 | 0 |
| Qwen3-8B | +2nd rollout | Mistral-7B-v0.3 | Llama-3.1-8B | |
|---|---|---|---|---|
| +0.59 [+0.46,+0.71] | +0.63 [+0.50,+0.75] | +0.64 [+0.50,+0.78] | +0.58 [+0.43,+0.72] | |
| +0.15 [+0.00,+0.32] | +0.08 [-0.06,+0.21] | +0.14 [-0.01,+0.28] | +0.18 [+0.01,+0.35] | |
| Cap amplification | +0.44 [+0.22,+0.65] | +0.55 [+0.38,+0.71] | +0.51 [+0.32,+0.71] | +0.40 [+0.16,+0.63] |
| +0.11 [-0.08,+0.29] | -0.02 [-0.15,+0.09] | -0.18 [-0.32,-0.04] | -0.23 [-0.42,-0.04] | |
| +0.31 [+0.04,+0.57] | +0.40 [+0.24,+0.55] | +0.41 [+0.09,+0.74] | +0.34 [+0.03,+0.65] |
| Artifact | Released | Contents |
|---|---|---|
| Code | Yes | Task generators, both runtimes, agent harness, training and serving scripts, every condition’s benchmark config, analysis scripts, and the verbatim prompts |
| Evaluation traces | Yes | Per-task rollouts of every reported condition: main evaluation, dense sweep, horizon control, cross-task controls, both interventions, replications |
| Opaque Knapsack adapters | Yes | 6 Qwen3-8B (persistent/stateless 3 seeds) 4 replication adapters, one card each |
| Control-task adapters | Yes | The 4 Navigation and Rule Diagnosis adapters, same recipe and card format |
| Teacher traces | Yes | The filtered, instance-paired SFT data of App. B , as fed to the fine-tuning script. The raw cached teacher responses it was built from are not released |
| Runtime contracts and conditions | |
|---|---|
| , | The persistent runtime, under which the variables an agent creates stay available on later turns, and the stateless runtime, under which each turn begins with a fresh set of them. Task and environment state, including the tool objects, survives under both (Sec. 3 ) |
| Runtime contract | The interpreter semantics alone: whether agent-created bindings survive the turn boundary (Sec. 3 ) |
| Runtime condition | The contract together with the prompt package that announces it: a mode instruction, a runtime-state banner and runtime-specific few-shot examples. Cross-runtime comparisons switch the whole package, not the semantics in isolation (Sec. 3 , App. A.3 ) |
| An -trained agent deployed on a runtime. and are the matched references, the main mismatch and the reverse transfer (Table 1 ) | |
| Condition | One of the four combinations, evaluated at one cap (Table 1 ) |
| Runtime transfer | Whether an agent trained under one runtime still solves the task when deployed under the other (Sec. 1 ) |
| Outcome and reported quantities | |
|---|---|
| Normalized optimality | The outcome: achieved value over the exact optimum on allowed-class items, clamped to on any capacity overflow (Sec. 3 , App. A.2 ) |
| Mean task quality for an adapter trained under runtime and evaluated under runtime at cap : normalized optimality for Opaque Knapsack, and each control family’s own score (Sec. 3 , App. E.1 ) | |
| Runtime gap: (Sec. 3 ) | |
| Train runtime interaction: (Sec. 3 ) | |
| Cap moderation: (Sec. 3 ) | |
| Cap amplification | The same tightening applied to the runtime gap itself: (Sec. 3 , Fig. 3 ) |
Tool-Using Agents
Tool-using agents plan and act through external tools, APIs, software interfaces, and environments to complete tasks beyond language generation.
See all 286 papers