Skip to content

Shared-prefix tool failure analysis

This is the public-safe projection of the protected offline review. It uses the exact preflight source at dc576b25083d7cfdab1554db89379feee82346b5 and makes no root-cause claim.

Finding

The preflight result is a valid miss against the frozen harness's tool_choice: "auto" reliability expectation, not an evidence-counting or response-validation bug. It is not a terminal candidate judgment and does not establish an Ignis engine/model defect. Four of five named checks passed, but the shared-prefix tools check passed only 3/4 requests. The failed request returned assistant prose, finish_reason: "stop", and no tool_calls. The frozen validator correctly reported response did not include tool_calls.

This is not proof of an OpenAI-protocol violation. The request used tool_choice: "auto", which permits the model to choose whether to call a tool. It is nevertheless a real failure of the declared reliability gate: the user message explicitly said Use the tool, and the batch required every response to contain a schema-valid get_weather call with a non-empty string city argument.

Exact request construction

Each of the four batch requests used the non-streaming Chat Completions path, the same 400-line system prefix, and the user message What's the weather in Oakland? Use the tool.. The tools array declared one function, get_weather(city: string), with city required. The body included tool_choice: "auto", max_tokens: 4608, and temperature: 0.6. Thinking mode was default, so neither chat_template_kwargs nor reasoning_effort was sent. The timeout was 60 seconds and retries were zero.

The body builder is at anvil_serving/preflight.py@dc576b25:43-60; the tool schema, prompt, choice, and validator are at lines 354-409; and the four calls are submitted concurrently in one phase at lines 413-426.

Engine correlation

Prompt, completion, and cache-token counts uniquely map the failed harness observation to engine request ID 5: 5,521 prompt tokens, 13 completion tokens, and 5,519 reused prompt tokens. The other three batch members map to request IDs 3, 4, and 6. Two of those successful requests also reused 5,519 prompt tokens, so the evidence does not support a cache-only explanation.

The engine records internal finish_reason: "stop" for all nine done events, including requests that the API represented as successful tool_calls. Therefore the internal field cannot explain the prose response and is not treated as the API finish reason.

Every native observation has a corresponding admitted, first-token, and done engine event. The artifacts do not share a request ID, but the token-count mapping is unique in this run. Neither artifact retains an explicit HTTP status code, so this review does not relabel the evidence as literal HTTP 200 proof.

Request-count correction

The execution made nine HTTP requests in six sequential phases: one smoke, one JSON, four concurrent tools, one streaming-tools, one tool-result initial, and one tool-result continuation request. The earlier six-request statement counted phases rather than calls. The command itself did not change.

Disposition and later follow-up

The separately frozen phase-two work retained this result unchanged and used official Ignis 0.8 tool/template/thinking guidance to test the supported mandatory-tool policy. The same runtime/model/profile passed required with default thinking across the mechanism cell, full five-check preflight, and a different-seed four-call repeat. That follow-up appears in tool-choice-followup.json.

The phase-one auto miss is therefore neither a terminal candidate rejection nor an engine/model defect. The candidate remains unpromoted. Further causal diagnosis of the stochastic automatic-choice miss would need separately authorized evidence that joins the exact request body, API response, and engine request identity; this review makes no hypothesis about the cause.