Mistral Provider
Wrap your Mistral client with Shield for prompt hardening, injection detection in user messages and tool results, and output guarding on chat.complete and chat.stream.
The shieldMistral wrapper adds Shield to your Mistral client from @mistralai/mistralai. It intercepts every chat.complete and chat.stream call to harden system messages, detect injections in user messages and tool results, and redact prompt leaks, credentials, and exfiltration links from responses.
Usage
import { Mistral } from "@mistralai/mistralai";
import { shieldMistral } from "@zeroleaks/shield/mistral";
const client = shieldMistral(
new Mistral({ apiKey: process.env.MISTRAL_API_KEY }),
{ systemPrompt: "You are a support agent..." }
);
const response = await client.chat.complete({
model: "mistral-large-latest",
messages: [
{ role: "system", content: "You are a support agent..." },
{ role: "user", content: userInput },
],
});How it works
On every call to chat.complete or chat.stream, Shield:
- Copies the request parameters and each message so your objects are not modified.
- Hardens every message with
role: "system"(unlessharden: false), adding the canary if you set one. String content stays a string. In an array of chunks, Shield joins the text chunks with newlines, hardens them, and stores the combined text in the first text chunk. Thinking chunks retain their positions. - Runs detection on every
usermessage (unlessdetect: false) and everytoolmessage (unlessscanToolResults: false), including earlier turns. Text chunks are joined; image, document, file, and audio chunks are ignored. Assistant messages are not scanned. - Calls the original SDK method.
- For every choice, guards the text of
messageand of each entry inmessages: string content, or its text chunks joined, checked for prompt leaks (unlesssanitize: falseor there is no system prompt) and passed through the output guard (unlessoutput: false). Chunked text is written back over the same chunks: each keeps its original character count, and the last chunk receives the remaining text. Thinking chunks are unchanged. Each tool call'sfunction.argumentsis also guarded, as one text when it is a JSON string and string by string when it is an object.
The wrapper uses the SDK's camelCase field names: toolCalls, toolCallId, and finishReason.
For prompt leak checks, Shield uses systemPrompt if provided. Otherwise, it uses the text of the first system message before hardening, with its text chunks joined with newlines.
A secondaryDetector in the detect or scanToolResults options runs before a request is blocked, and detection results are reused for text already checked, as described under Shared behavior.
Options
shieldMistral takes the shared options. systemPrompt defaults to the text of the first system message, before hardening.
Streaming
chat.stream() resolves to the SDK's EventStream, whose events each carry a completion chunk in data. In "buffer" and "chunked" mode, the wrapper resolves to a stream of the same kind: a ReadableStream with the EventStream prototype, so both for await and getReader() work. See Streaming for the three streamingSanitize modes. Their behavior for this wrapper is:
| Mode | Behavior |
|---|---|
"buffer" (default) | The promise resolves once the whole stream has been read, and rejects if the stream fails or a leak or finding throws. Each choice's text across all events (delta.content, a string or text chunks) is guarded as one text and written back over the same deltas, each keeping its length and the last one taking the rest. Each tool call's argument strings, matched by index, are guarded the same way; object arguments are guarded delta by delta. You get every event the SDK sent, as the same objects and in order, with roles, finish reasons, and usage. |
"chunked" | Each choice's text is guarded every streamingChunkSize characters. Every event is kept, with its delta.content holding the text that is safe to send so far, which can be empty. Events are yielded one behind the stream, so the text still held back at the end goes into the last event, ahead of its finish reason and usage. Tool call arguments are guarded delta by delta, since Mistral sends a call's arguments in one delta. |
"passthrough" | Returns the SDK's stream unchanged, with no sanitization or output scanning. |
Unlike the OpenAI and Anthropic wrappers' "chunked" mode, nothing is dropped and every choice is guarded. In "chunked" mode, blockOnOutputFindings throws from your for await loop before any of the text with the finding is yielded, and a prompt leak or canary in the text throws LeakDetectedError with throwOnLeak after the last event. With either option, a finding in tool call arguments throws as soon as its event arrives.
What is not covered
- The wrapped client is a Proxy. The OpenAI, Anthropic, and Groq wrappers return a shallow copy;
shieldMistralreturns a Proxy over your client, withchatreplaced by a Proxy over the SDK'sChatin whichcompleteandstreamare guarded. Every other property reads from your client, and its methods are bound to it, because the SDK keeps its HTTP client in private fields that a copy can't use. Your client is not modified, but setting a property on the wrapped client sets it on yours. chat.parse()andchat.parseStream()work on the wrapped client but are not guarded: the SDK sends those requests itself rather than throughcompleteandstream. For guarded structured output, callchat.completewithresponseFormatand parse the JSON yourself.- Other resources, such as
client.agents.complete()andclient.agents.stream(),client.beta.conversations, andclient.fim, keep working but are not guarded. - Content that is not read: thinking chunks, in requests and responses, and image, document, file, and audio chunks, which are not fetched or decoded.
See What is not scanned for what no wrapper scans.
Google Gen AI Provider
Wrap your Google Gen AI SDK client with Shield for system instruction hardening, injection detection in user input, function responses, and inline documents, and output guarding on generateContent, generateContentStream, and chats.
LangChain.js
shieldChatModel and ShieldCallbackHandler for LangChain.js chat models, chains, and agents. Hardening, injection detection in human and tool messages, and output guarding on invoke, batch, stream, and streamEvents.