Skip to main content
guard.decorate wraps a completions function. It is called with the arguments it would have received, so you keep using the provider SDK directly and no base URL is rewritten.
The request is inspected first. The guard then refuses the call, redacts the body and forwards it, or forwards it untouched, according to onMatch. A sync function gets a sync wrapper and a coroutine function gets an async one, so an AsyncOpenAI client stays async.

Streaming

A stream is teed, not buffered. Each chunk reaches you before it is recorded, so decoration adds no latency.

Sanitise in place

With onMatch: "sanitise" the body is rewritten before it is sent. Provider parameters survive untouched and only matched spans change.

Anthropic

The same decorator wraps the Anthropic SDK. messages.create and messages.stream both work. The request layout understands the Messages API: a top-level system parameter (a string or a list of text blocks), and content blocks that nest text inside tool_result and tool_use.
Tool results and replayed tool calls are scanned too, because they are first-class indirect injection surfaces. Image and document payloads are not: base64 is neither text nor a plausible carrier for an instruction.

Options