The two arms
The raw arm is the glue people write first, and it is a control rather than a
straw man. The endpoint list in each of its tool descriptions is derived from
the Charter pack’s own tools, so nobody hand-picked what it could reach, and the
same derivation compiles the guard that enforces it. Same model, same settings,
same system prompt, same task text, same credentials, same endpoint set, same
limits. Only the tool surface differs.
Two deliberate concessions to the raw arm, both of which a careful engineer would
also make: a response over 100,000 bytes is cut there rather than ending the run
on a context error, and a non-2xx is raised so the model can read the status and
body.
Task success
A run is one scenario-epoch. Success means the scenario’s judge accepted the state read back from the live accounts after the agent finished. The transcript is never consulted for the verdict — no LLM judge reads the reasoning, and no partial credit is given for a plausible-looking trajectory.
Two-proportion z-test on the combined figures: z = 2.32, two-sided p = 0.020.
Neither campaign clears the bar on its own: breadth alone is z = 1.92
(p = 0.055) and depth alone is z = 1.34 (p = 0.18). Only pooled do they reach
p < 0.05, and pooling two campaigns after seeing both is exactly the move a
sceptical reader should discount. Treat this as one result at p ≈ 0.02, not as
two independent confirmations.
The gap is one scenario
This is the caveat that matters most, and it is not a small one. Rolled up across both campaigns, all ten raw-arm failures are the same scenario:
On fifteen of sixteen scenarios a generic HTTP tool did the job perfectly. Remove
doc_to_gmail_draft and the comparison reverses: raw 252/252 against Charter
248/250, whose two failures are both inbox_to_sheet.
So the honest claim is narrower and sharper than the average suggests. This is not
“a declared boundary lifts every task by three points”. It is: for straightforward
REST work against these APIs, a model driving a raw HTTP tool was reliable — and
on the one task requiring a wire format the model has to construct (an RFC 2822
document, base64url-encoded, wrapped under raw), it failed ten times in
seventeen while the declared version never failed.
That is the case the library was built from, which cuts both ways: it is the
strongest possible demonstration of the thesis, and it is also the scenario most
likely to have been selected because the thesis predicts it. Sixteen scenarios is
not enough to say how much of real work looks like that one.
Context
Bytes of tool output handed to the model, summed over a run, and what came off the wire to produce it:
The first numeric column is the one that makes this a measurement rather than an
anecdote: both arms pulled essentially the same volume off the wire. Nothing was
fetched less. It was forwarded less,
by the packs’ own response handlers, with nothing configured.
The ratio held between 4.2 and 4.3 across both campaigns, which makes it the
steadiest number here. It is not a constant of the library, though: it is a
property of which endpoints a workload touches. On the earlier scenario set used
in phases 1–3 the same measurement sat closer to 2×, because those scenarios lean
on endpoints whose responses were already small. What generalises is the
direction and the mechanism, not the multiplier.
The rest of the record
Tool errors on the Charter arm include calls rejected locally by schema
validation, which never reached an API. The raw arm’s count is API failures only,
so the comparison understates the gap in calls that actually went wrong.
Guard rejections are attempts to reach an endpoint outside the agreed set. Zero
against ten is a property of the mechanism rather than of the model: a Charter
tool has nowhere to put a path the pack does not declare.
Wall time is not a result and is
listed only so it is not omitted. It went in opposite directions in the two
campaigns.
The column that was thrown out
Total tokens per run was measured, and is not reported, because it was measuring the harness. The Charter arm flattened$ref/$defs before handing a tool to the eval
framework, whose schema type has no reference fields. Real SDK users are handed
the compact $defs form that to_json_schema() emits; the arm was benchmarking
a flattened surface no consumer of the library ever sees. On a cyclic schema that
expansion is multiplicative — linear.teams_list reached 3.8 KB at depth 2,
72 KB at 4, 1.9 MB at 6 and 115 MB at depth 12.
Both campaigns ran before that was found and fixed, so every token figure in
them is void, and so is every token figure the harness produced since
7 September 2026.
Two consequences, and the second is the interesting one:
- Context bytes are unaffected. They measure tool output, not schemas.
- The bug handicapped the arm that won. The inflated schemas were on the Charter side. Whatever the correct token comparison turns out to be, the success figures above were obtained while the Charter arm was carrying schemas far larger than the library ships.
What this does not show
- One model. Both campaigns ran on
glm-5p3-flash. Earlier campaigns onnemotron-3-ultraandminimax-m3point the same way on both success and context, at smaller n and on an earlier scenario set, but no third model was run to completion here. - One scenario family. Sixteen templates, all of them multi-step cross-provider office automation. Nothing here says anything about code execution, retrieval, or long-horizon planning.
- Not an ablation. The Charter arm differs from raw in several ways at once — declared schemas, deferral, response trimming, wire assembly. This compares two whole surfaces. It does not apportion the credit between them.
- Harness errors excluded. Four runs (three Charter, one raw) failed to seed — two GitHub 409s and two dropped connections. The agent never had a fair task, so they are listed in the campaign report and counted for no one.
Reproducing it
The campaigns live inharness/, run against your own accounts, and write their
own report. Check the wiring first — it makes one cheap call per provider and
creates nothing it does not also delete:
harness/results/FINAL-breadth/summary.json and
harness/results/FINAL-depth/summary.json, beside the per-scenario tables and
the judge’s stated reason for each of the twelve failures.
Related
- Context window — the mechanism behind the 4×, in both directions
- Conformance — what every pack is held to mechanically
- What this can’t express — the edges of the contract