A tool-result sanitization gate sits between the tool call and the prompt assembly step. Its job is to decide what happens to each tool result before it becomes context for the model. Before writing a single fixture, write down the gate's decision surface: what inputs it reads, what it can return, and where its output goes. Most gates resolve to four outcomes: pass the result through, truncate it to a budget, drop it entirely, or replace it with an error placeholder. The tests you write are only meaningful if the gate exposes those outcomes in a form the test can observe.
That observability is not free. A gate that raises a generic exception gives the test no way to distinguish "dropped because it was hostile" from "crashed because of a bug." Define a small result type, a dict with a verdict field and a reason field, and make the gate return it for every input. Then the CI job asserts on verdict and can print reason when it fails. This mirrors the separation of responsibilities that mature tool-output tooling uses: one component decides whether to act, another decides how, and a third measures the input before the decision the Haystack compaction docs. That split is worth copying, because it lets you test the decision logic without standing up a real model.
Prompt injection is the reason this gate exists. OWASP classifies indirect prompt injection, where malicious instructions are hidden in external content the model processes, as a first-class risk, and notes that a payload does not need to be human-readable as long as the model parses it the OWASP Gen AI project. The same page lists segregate and identify external content as a mitigation, which is the architectural assumption your gate should be enforcing. If the gate cannot tell you, per tool result, whether the content was trusted, you cannot enforce that separation.
Your test suite should also acknowledge a hard limit. There is no general fix for prompt injection inside the model, because instructions and data arrive in the same channel the awesome-prompt-injection list. That is precisely why the gate is tested at the boundary and not at the model. The gate is deterministic code, deterministic code can be tested, and the fixtures in this article test exactly that.



