create_agent API connects a
model to a set of tools and runs the agent loop until the model produces an
answer.
The langchain-neuraltrust middleware evaluates messages and tool activity
inside that loop. Because it runs in the application, it can block a tool call
before execution.
Integration capabilities
Pass the agent’s tool list to the middleware to include tool declarations in
the evaluation payload. This allows tool-poisoning rules to inspect tool names,
descriptions, and schemas.
Before you start
Create the policy in Observe mode. Observe records decisions in Activity without enforcing
them. Review the results, then switch the policy to Enforce. See
Policies.
1. Install
langchain-neuraltrust.
It does not require changes to the model provider configuration.
2. Add the middleware
3. Choose what gets evaluated
Four independent flags map to hooks in the agent loop:check_tool_results is skipped when check_input is also on because the
conversation payload already contains those tool messages. This avoids
evaluating the same text twice.
Enable check_tool_calls when a policy must stop a tool call before it runs.
It adds one evaluation round trip per tool call.
Both sync (invoke) and async (ainvoke) paths are implemented for every hook.
4. Verify
AIMessage. The model is not called, and on_violation prints the
trace_id. Use it to match the run to the finding in Activity.
Call close() after invoke, or await aclose() after ainvoke, when the
middleware owns its HTTP clients.
Reference
Coverage
Ask. The middleware does not implement an
ask flow. It treats ask as an
unknown verdict and fails closed, so the result is a block. Implement any
human approval step in the application.
Limits. The middleware inspects only the configured agent. A service that
calls the provider directly bypasses it. On streaming routes, output evaluation
occurs after delivery. See Streaming.
Detectors evaluate text and tool calls, but
non-text content parts are not stripped from the payload: a message whose
content is a list of blocks is forwarded to /v1/evaluate as-is, so the image
data available to the agent is also transmitted for evaluation. Non-text parts
cannot be rewritten.
Tool-call redaction requires check_tool_calls=True. A compatible transform
verdict replaces the pending tool arguments before dispatch; it does not rename
the tool.
Each guarded stage adds a round trip, and the hooks run on every pass through the
agent loop. With check_input, check_output, and check_tool_calls enabled, a
turn that calls two tools in parallel and then answers makes six evaluation
calls: input and output on each model pass, plus one per tool call. Sequential
tool calls add further evaluations. Set timeout to limit the effect of a
stalled request.
What is evaluated
Every stage calls
POST /v1/evaluate with the
collector key, and the policy’s detectors decide the verdict.
Verdicts
The middleware applies each verdict to agent state as follows:
At message stages, preserving the ID ensures that a transformed message replaces
the original in the thread instead of being appended to it.
exit_behavior decides what a block does:
These behaviors do not remove
SystemMessages. Under end and replace, the
middleware also keeps the thread structurally valid. It clears tool_calls from
a blocked AIMessage and converts a blocked ToolMessage so it does not leave
an orphaned tool response. Otherwise, the next model call would fail because the
thread contains a tool call without a corresponding response.
On the tool path a block returns a ToolMessage(status="error") and the tool is
never called. A transform dispatches the tool with the rewritten arguments.
on_violation is synchronous and fires from both invoke and ainvoke.
Exceptions from the callback propagate unchanged, so handle callback failures in
your application if they should not interrupt the agent.
Configuration
Every setting falls back to an environment variable:
When
session_id is unset, the middleware uses the LangGraph thread_id. This
groups turns in Activity by the same conversation identifier as the
application.
Fail-open or fail-closed. unreachable_fallback applies only when
TrustGuard cannot be reached because of a connection error, timeout, HTTP
502/504 response, or HTTP 429 response after
retries are exhausted. Those are retried with backoff, honoring Retry-After,
before the fallback applies.
The following cases fail closed even when
fail_open is configured:
- HTTP 401/403, and 503 entitlement failures
- any other 4xx/5xx
- a non-JSON
200, or an unknown verdict, includingask - a
transformed_payloadthat cannot be applied safely - TLS failures. An expired or untrusted certificate is a connect error, but
the middleware treats it as a configuration fault rather than an outage, so
fail_opennever covers it. A corporate MITM proxy without a trusted CA will therefore block every turn even withfail_openset.
Streaming
after_model runs on the assembled AIMessage, once the model call has
finished.
For preventive response enforcement, disable streaming or buffer the stream
until a verdict is available. Buffering increases time to first token. You can
also place TrustGate in front of the route to inspect
the stream at the gateway.
Attributes
session_id: the LangGraphthread_idunless you set itmodel_name: the runtime context model unless you set ittrace_id: included in every verdict and the matching finding in Activity
on_violation(verdict, stage) receives the stage name alongside the verdict, so
alerting can distinguish an input finding from a tool-call finding without
parsing the payload. Reconcile a run with the console on trace_id.
Troubleshooting
Related
- Policies: Gates: configure Block and Transform actions
- Evaluate API: request and response reference
- Agent and MCP security detectors: indirect prompt injection and tool poisoning
- Python SDK: protect calls outside an agent loop
- Coverage: compare available collectors
- TrustGate: apply policies at the gateway and monitor streamed responses
NeuralTrust/langchain-neuraltrust: source and issues- LangChain docs: LangChain reference