Strips Spectre control tokens from model output before it becomes a user-visible reply.
Prompts teach the model Spectre's routing and planning markup — <al>,
<intent>, <reply> wrappers, INTENT:/AL: control lines — and models
also emit reasoning wrappers (<think>, HTML comments). None of that may
reach the user, and without a core scrubber every host rewrites the same
cleanup. This sanitizer is the runtime default wherever LLM text becomes
reply_text; pass sanitize_reply: false to opt out. An action planner may
perform its own cleanup first, but its visible reply still crosses this
structural boundary unless sanitization is explicitly disabled.
Host-specific cleanup (localized model preambles, channel formatting) stays
in the host. It can be supplied through :reply_sanitizer as a module, or
{module, options}, implementing this module's callbacks. The configured
sanitizer is an additive layer: Spectre removes its own control tokens
first, then invokes the extension. This keeps the core security boundary in
place while allowing a package such as Pulse to own model-specific cleanup.
Streaming extensions must implement all three streaming callbacks as well
as sanitize/2. They receive only text already accepted by the core
incremental sanitizer. A sanitizer may suppress text but must not synthesize
or expand it. Its provisional output must also be monotonic with
sanitize/2: concatenated deltas must not contain text that the terminal
callback would remove.
Summary
Functions
Removes Spectre control tokens and reasoning wrappers, then trims.
Types
@type stream_state() :: term()
Callbacks
@callback finish_stream(stream_state()) :: {:ok, String.t()} | {:error, term()}
@callback init_stream(keyword()) :: {:ok, stream_state()} | {:error, term()}
@callback sanitize_chunk(String.t(), stream_state()) :: {:ok, String.t(), stream_state()} | {:error, term()}
Functions
Removes Spectre control tokens and reasoning wrappers, then trims.
iex> Spectre.Reply.Sanitizer.sanitize("<think>hmm</think>Hello <al>a1</al>there")
"Hello there"Honors sanitize_reply: false in opts by returning the text trimmed but
otherwise untouched. :reply_sanitizer accepts a callback module or
{module, options} for additional cleanup after Spectre's built-in pass.