Latest Results
fix(langchain): redact `PIIMiddleware` output before it streams or persists
With `apply_to_output=True` or `apply_to_tool_results=True`, `PIIMiddleware`
redacted in `after_model` and `before_model`, one step after the model or
tool node had already written the raw message. The raw text went out on the
`messages`, `updates`, `values`, `checkpoints` and `tools` stream modes and
stayed in a checkpoint, and the redacted copy never reached `messages`
because it keeps the message id, which that mode has already seen.
The middleware now also wraps the model and tool calls and redacts their
results before anything is written, including the `ToolMessage`s in a
`Command` or list that a tool returns. Model calls under the wrapper run
with the `nostream` tag, set on the callbacks of the surrounding config, so
it holds for any model runnable, for a model a later middleware swaps in,
and for a model bound with its own tags. Tools run as a copy tagged
`nostream`, because `ToolNode` passes them the config it captured before
the wrappers ran. `before_model` and `after_model` stay as backstops, and
the v3 stream transformer stays until v3 is removed.
`create_agent` registers wrap hooks per class, so every `PIIMiddleware`
registers them and input-only instances pass straight through. That gives
a tool-less agent a `tools` node, skips the unknown-tool check, and adds
wrapper spans; per-instance hook registration in `create_agent` would
remove that cost.
`strategy="block"` now raises inside the model or tool call, where retry
middleware listed before `PIIMiddleware` would retry it, so the default
retry predicate no longer retries a `PIIDetectionError`.
A protected model streams no tokens and its reply arrives as one message,
and protected tools no longer appear in the `tools` stream mode.eliornl/langchain/pii-before-stream Latest Branches
0%
langsmith-fleet/deps/security-locks-20261030 0%
hntrl/langchain/model-refusal 0%
eliornl/langchain/internal-calls-nostream © 2026 CodSpeed Technology