Shadow failure case

ChatCompletionCache omits tool_choice from the cache key, so 'must call a tool' and 'must not' share one entry

Artifact chatcompletioncache-omits-tool-choice-from-the-cache-196e2ed072 · generated 2026-10-08T21:30:51.251590+00:00 · source: microsoft/autogen #8211

This is the automatic first artifact from a falsification-bounty submission. It is redacted and public-safe by default; the next step is to turn the failure into a reusable proof, guardrail, or diagnosis.
Request private audit Follow the failure feed

Observed agent action

ChatCompletionCache._check_cache builds its cache key from messages, tools, json_output, and extra_create_args while silently omitting the tool_choice parameter that create() and create_stream() both accept and forward to the underlying client.

Expected boundary

The cache key must incorporate every parameter that create()/create_stream() forward to the underlying client and that can change the model's response, including tool_choice in all three of its forms (Tool, 'auto'/'required'/'none').

Runtime context

autogen-ext ChatCompletionCache wrapping a ChatCompletionClient, used to deduplicate LLM calls across repeated create()/create_stream() invocations with varying tool-selection policy.

Evidence supplied

The reproduction shows three distinct tool_choice values ('required', 'none', and a forced Tool) all returning the cached answer for 'required' with the underlying client called only once instead of three times, and zero warnings were captured despite the module already using the warnings mechanism elsewhere.

Evidence needed next

Commercial routing

Use the public artifact for broadly useful redacted failures; use the private audit path when the evidence is sensitive or the operator needs a concrete fix, guardrail, or receipt proof.

Next proof step

Convert the submitted failure into the smallest reusable control: a deterministic guardrail, receipt proof, public autopsy entry, or private diagnosis if evidence is sensitive.