REPORT · OpenAI · August 29, 2026
GPT-5.5 to GPT-5.6-sol
GPT-5.6-sol rejected every tool call shell_gpt made, and one endpoint-routing line brought all 14 cases back. The same pipeline on our own 38-case booking agent could not repair four regressions, and returned STAY PINNED.
gpt-5.5gpt-5.6-sol
14 / 14
shell_gpt cases on GPT-5.5
0 / 70
reps on GPT-5.6-sol
14 / 14
restored by one line
32 / 36
booking-agent regressions repaired
$12.87
of API spend across both runs
What broke
On shell_gpt the API rejected the request outright: Function tools with reasoning_effort are not supported for gpt-5.6-sol in /v1/chat/completions. All 14 cases regressed, 0 of 70 reps passed, and the unpatched candidate run cost $0.00 because rejected requests bill nothing. The booking agent hit the same 400 on 36 of its 38 cases.
What fixed it
For shell_gpt, route-to-responses: a one-line change of endpoint from chat_completions to responses, accepted as candidate 1 of 6, 14 / 14 restored at 10 / 10 combined reps with nothing broken. The booking agent needed three stacked repairs (endpoint routing, an execute-don't-interrogate prompt block, reasoning_effort: high) and still left four cases broken, which is why its verdict is STAY PINNED.
Verdict
Limitations
- One agent, one tool, 14 cases on the shell_gpt run. A single-tool surface cannot show wrong-tool selection at all.
- The eval cases are ours, not the maintainers'. They are kept to behaviors shell_gpt's own README advertises, but a maintainer might weight things differently.
- Tool execution is sandboxed Linux/bash in a network-isolated container, not the user's own machine and shell.
- Adapted agents run through Upshift's loop, not their own: no streaming, a six-turn cap, tool results JSON-wrapped. None of that changes whether the API accepts a request.
- Two of the booking agent's four unrestored cases were vetoed on a confirmed tradeoff, one is a brittle-assertion artifact, and one is a stubborn interrogation. The headline number for that run is 88.9 percent, not 100.
Evidence
Method
shell_gpt at upstream commit a082bd5, adapted through the ADAPTER.md contract with its prompt and tool schema generated from its own code; 14 eval cases grounded in its README examples; deterministic checks with no LLM judge; N=5 reps per case per model on the real OpenAI API, flex tier. The booking agent is our own 38-case internal suite run through the identical pipeline.
Statistical details
One-sided Fisher exact per case on baseline versus candidate passes: p is approximately 0.004 for each of the 14 shell_gpt cases, and p=0.00397 for the 36 booking-agent cases that went 5/5 to 0/5. Wilson 95 percent intervals on suite rates: the booking agent's 36 / 38 baseline is 94.7 percent, CI 82.7-98.5 percent. One test per case, p not adjusted for multiple comparisons. Contested case statuses were adjudicated on 2N reps at unchanged thresholds.
A pass is a rate of at least 0.8 of N, a fail is 0.4 or below, and anything between the two is flaky. Read a single significant p as a pointer into a transcript, never as a result on its own.
Full report
The markdown below is the committed report, verbatim. Read it at the source ↗
This is upshift’s first proof run on an agent we didn’t write:
shell_gpt (12,263 stars, ~16.5k PyPI downloads/month,
MIT), adapted through the ADAPTER.md contract. Every claim below is backed
by committed run records under runs/ with the shellgpt-56sol prefix.
Why shell_gpt#
Its default-role agent calls /v1/chat/completions with one function tool
(execute_shell_command), OPENAI_USE_FUNCTIONS=true by default — and it has no escape
hatch from the documented gpt-5.6-family break (function tools rejected on
chat/completions unless reasoning_effort is "none" or the call moves to
/v1/responses): there is no reasoning_effort config key (the PR proposing one was
closed unmerged), no responses routing, and its optional litellm dependency is pinned
fourteen minor versions before litellm’s fix. A user who bumps DEFAULT_MODEL from
gpt-5.5 to gpt-5.6-sol — a documented one-line config change — gets a hard 400 on every
tool call. As of this run, no issue for this is filed on the shell_gpt repo.
What we adapted, and exactly how honest it is#
The prompt and tool schema were generated from shell_gpt’s own code at upstream commit
a082bd5 (not transcribed): Function.openai_schema() executed as-is, the role template
rendered through shell_gpt’s own OS_NAME/SHELL_NAME config mechanism as Linux/bash.
Full provenance in agents/shell_gpt/ATTRIBUTION.md.
Tool execution runs shell_gpt’s command in a network-isolated Docker container
(--network none, pinned mtimes, TZ=UTC, no jq, 30s timeout) over per-case fixture
trees, with the same Exit code: N, Output: envelope shell_gpt’s tool returns. Known
deltas from the real runtime, all deliberate: our agent loop JSON-wraps the tool string
(identical bytes inside), responses are not streamed, turns cap at 6 (upstream recurses
unbounded), and tool_choice/parallel_tool_calls are not sent. None of these affect
whether the API accepts the request or which commands the model runs.
The 14 eval cases are grounded in shell_gpt’s own README usage examples: 8 read-only queries, 2 file-writing tasks, 2 identifier-fidelity cases, and 2 over-acting guards (a messy directory described, not a cleanup requested — the check is that nothing gets deleted). Numeric answers are asserted as standalone tokens with a build-time guard that the expected number appears in no filename, file body, or file size — a case a model could pass by pasting a directory listing would be a lie.
Baseline: gpt-5.5#
All 14 cases PASS: 69 of 70 reps passed (13 cases at 5/5, read_json_email_field at 4/5 —
above the 0.8 threshold). shell_gpt on gpt-5.5 does what its README says it does.
Records: runs/shellgpt-56sol-baseline/.
The break: gpt-5.6-sol, unpatched#
0 of 70 reps passed. All 14 cases regressed (one-sided Fisher exact p ≈ 0.004 per case), every one with the same failure signature: the API rejects the request outright —
Function tools with reasoning_effort are not supported for gpt-5.6-sol in /v1/chat/completions. To use function tools, use /v1/responses or set reasoning_effort to ‘none’.
shell_gpt never sets reasoning_effort; the 400 fires anyway on the 5.6 family. For a
shell_gpt user this is total loss of function-calling — and since rejected requests bill
zero tokens, the entire unpatched candidate run cost $0.00.
Records: runs/shellgpt-56sol-candidate/.
The repair loop#
Candidate 1 of 6, route-to-responses — a one-line change of endpoint from
chat_completions to responses in agent.json:
- Screen on the 14 broken cases: 14/14 restored.
- Full-suite verification: 14/14 cases at 5/5.
- Combined evidence per restored case: 10/10 reps (screen + verify, upshift’s 2N acceptance criterion — a lucky single-run pass never counts as restored).
Accepted. No further candidates needed. Zero previously-passing cases broken, zero relapses, zero flaky degradations. The behavioral regressions we braced for from the booking-agent experiment (interrogation, identifier reformatting, over-acting) did not materialize on this suite once the endpoint was routed: the two identifier-fidelity cases and both over-acting guards passed every rep on patched 5.6-sol. Patched 5.6-sol was 140/140 on reps where 5.5 was 69/70 — we note that without claiming it means 5.6 is better; at this sample size it doesn’t.
Verdict#
SAFE WITH PATCH. The patch is runs/shellgpt-56sol/upgrade.patch
— apply with git apply. In shell_gpt’s own codebase the equivalent fix is moving
sgpt/handlers/handler.py from client.chat.completions.create to the Responses API
(its openai >= 2.0 dependency already supports it). Filed upstream with these records:
TheR1D/shell_gpt#801 (2026-09-01); the
literal sgpt reproduction against PyPI release 1.5.1 was confirmed before filing.
This is the same machinery that returned STAY PINNED on our 38-case booking agent (32/36 restored, two repairs vetoed on confirmed collateral damage). The verdict is not a cheerleader: it says SAFE WITH PATCH when everything is provably restored, and STAY PINNED when it isn’t.
What this cost#
$0.56 of OpenAI API spend, total, on the flex tier: $0.27 baseline, $0.00 unpatched
candidate (all requests rejected, rejected requests are free), $0.29 screen + verify.
108k input / 27k output tokens across 210 recorded episodes. upshift cost reproduces
these numbers from the committed records.
Limits of this run#
- One agent, one tool, 14 cases. The single-tool surface means regressions show up as command quality, interrogation, and over-acting — not wrong-tool selection.
- The eval cases are ours, not the maintainer’s; we kept them to behaviors the README itself advertises, but a maintainer might weight things differently.
- Sandboxed Linux/bash execution, not the user’s own machine and shell.
Booking agent stress run#
The shell_gpt run above is one half of this migration. The other half is the 38-case booking agent Upshift was built against: an internal agent with an internal eval suite, run on the same two models with the same pipeline, and the run where the verdict came back no.
- Baseline, gpt-5.5: 36 of 38 cases pass (94.7%, Wilson CI 82.7-98.5%). One case is flaky at 3/5, one is a stable failure at 0/5.
- Candidate, gpt-5.6-sol, unpatched: 0 of 38. 36 cases regressed at Fisher
p = 0.00397, every one on the same
api_error_tools_reasoningsignature: the documented 400 for function tools on chat/completions. - Repairs: six candidates budgeted, three accepted after full-suite verification.
Routing to
/v1/responsesrestored 26 cases; an execute-don’t-interrogate prompt block restored 5 more;reasoning_effort: highrestored 1. Two candidates were rejected because full-suite verification found an earlier-restored case had relapsed, confirmed on a second adjudication round rather than on a single sample. - Result: 32 of 36 restored, zero previously-passing cases broken. Four cases stayed
broken:
edge_book_unknown_flight,edge_impatient_duplicate_phrasing,exact_city_names_to_iata, andexact_date_written_out.
Verdict: STAY PINNED. The bar is every regression repaired, and four were not. That is the difference between this run and the shell_gpt run above, and it is the reason the verdict exists at all.
Full accounting, with per-case statistics and the complete repair log.
Raw evidence
Every number on this page is recomputed from committed run records: inputs, outputs, model ids, parameters and per-rep transcripts, one directory per run.