strands-neuraltrust package connects its
agent lifecycle to TrustGuard, evaluating prompts, conversation history, model
responses, tool arguments, and tool results.
Use GuardedAgent when your application needs a complete, checked text response.
Use TrustGuardIntervention when you manage the Strands agent and its callbacks,
telemetry, and execution settings yourself.
Integration capabilities
Tool arguments are evaluated before execution. Completed tool results are
evaluated before the next model call. A result check cannot undo effects the
tool has already produced.
Before you start
Start with an Observe policy to review findings in Activity, then verify
the intended outcomes in Enforce mode. An
allow or report response does
not prove that a detector matched or that an enforcing rule was enabled. See
Policies.1. Install
strands_neuraltrust.
2. Configure credentials and tracing
Load the collector API key and deployment URL from your environment or secret store. Set trace redaction before the process creates any Strands agent or tracer:TrustGuardConfig does not
discover environment variables, select a default endpoint, or select a model
provider. base_url is the deployment root, optionally with a path prefix; the
client appends /v1/evaluate.
3. Create a guarded agent
Pass your configured, stateless StrandsModel to this function. The evaluator
stays open for the invocation and closes when the context exits:
GuardedResult.text contains the accepted final text. decisions is a tuple of
content-free DecisionRecord(stage, status) values, and stop_reason identifies
the accepted completion reason. The result does not expose raw findings, model
events, SDK history, or the underlying AgentResult.
For a synchronous application, use agent.invoke(prompt) inside a
with TrustGuardClient(config) context. Do not call the synchronous invocation
from an already running event loop.
Keep the agent and evaluator alive together to continue a conversation. Reuse
the same agent only after successful calls, and use separate agents for concurrent
conversations. After any failed or cancelled invocation, create a new agent.
Add tools
Pass registered Strands tools throughtools:
4. Handle decisions
The guarded agent and intervention enforce the following behavior:
Catch
TrustGuardBlocked when your application needs to display its own refusal
message. Treat other TrustGuardError subclasses as terminal protection
failures, and return an application-controlled error rather than retrying the
same agent. asyncio.CancelledError remains cancellation.
Coverage
GuardedAgent returns complete checked text, so it can block or transform
supported output before delivery. A native agent with only
TrustGuardIntervention can expose raw streamed output before its completed
output check. Transformations preserve supported text/JSON structure and refuse
changes to tool schemas, names, routing identities, and other immutable metadata.
See Supported content and transformations.
Coverage applies to the configured agent path. Tool-result checks cannot undo
completed tool effects. Models, tools, and application instrumentation remain
trusted application components.
What gets evaluated
Every boundary normally makes two evaluations: a structured payload followed
by a text assessment of its supported content. The second assessment presents
history, tool content, and the values inside supported JSON as text. This lets
text-oriented detectors inspect content that they may not extract from every
structured field. Both assessments must pass before staged changes are applied.
The second request uses the same collector, direction, session, and consumer.
It adds service latency, quota usage, and ordinary evaluation records, and may
affect stateful detector counters. It remains subject to all request, time, and
invocation budgets. Logical decision records summarize both responses:
transform takes precedence over report, then allow.
An accepted text-only GuardedAgent invocation normally makes eight evaluation
requests. A native agent with the intervention normally makes six. Tool calls
and additional model turns add more; a block or failure can stop earlier. There
is no policy-decision cache.
Set text_assessment=False only after independently qualifying your collector’s
structured assessment for every required history, tool, and metadata surface.
This option removes the additional text coverage and is not equivalent
protection with a collector that scans only the latest message.
Configuration
Collector client
TrustGuardConfig is immutable. Its representation omits the API key, and
constructing it performs no evaluation.
URLs containing credentials, query strings, fragments, encoded path segments,
dot segments, or malformed hosts are rejected. Owned transports verify TLS,
ignore environment proxy configuration, disable redirects, and request
uncompressed JSON. The response must be HTTP 200,
application/json, and
identity encoding. The client performs no retries and fails closed on transport
or protocol errors.
Requests use protocol="llm" and an explicit direction. The direct client also
accepts session_id, consumer_id, and JSON attributes on each evaluation;
see the Evaluate API. These are evaluation routing
fields and do not create Strands sessions.
Guarded agent
The caller owns model and evaluator lifetimes. Provider-managed conversation
state cannot be inspected as local history, so use a fresh, stateless model
instance with application-controlled settings. The facade accepts no arbitrary
agent construction options, custom middleware, sessions, plugins, or executor
configuration.
HTTP client ownership and cancellation
HTTP client ownership and cancellation
Owned synchronous transports reuse a serialized connection pool. Owned async
evaluations create and close a client on the current loop for each request. This
supports repeated synchronous guarded invocations that create distinct event
loops, at the cost of async connection reuse.
TrustGuardClient(config, http_client=..., async_http_client=...) accepts caller
HTTPX clients. You own their transport, TLS, proxy, event-hook configuration,
and lifetime. The adapter overrides request authentication and redirect
behavior but cannot control arbitrary custom transport code. An injected async
client binds to its first evaluation loop and refuses another loop. A sync
HTTPX injection is not used by async evaluation; use owned transports for
repeated synchronous guarded-agent calls.Close the adapter with close() / aclose() or its context managers. Closing it
prevents new evaluations and never closes injected clients. Finish or cancel
outstanding calls before closing shared resources. Async cancellation propagates
and owned per-request resources are closed.Python cancellation is cooperative. Blocking user code cannot be forcibly
interrupted by an async deadline. The sync elapsed bound can be exceeded by an
in-flight HTTP phase. Limits bound accepted content sizes, not every allocation
inside provider or tool implementations.Supported content and transformations
Supported content is user/assistant text, model tool calls, and tool results containing text or JSON blocks. Other content fails closed. Images, audio, video, documents, binary attachments, reasoning/signatures, citations, cache points, and unknown message structures are unsupported. Transformations preserve message count, order, roles, block kinds, tool names, result success/error state, system instructions, and tool declarations. JSON transformations preserve object keys, array lengths, and scalar categories. Arguments must validate against the registered tool schema before execution. An invalid, partial, or ambiguous replacement stops the invocation. Tool schemas use reference-free JSON Schema 2020-12, or omit$schema and use
that draft’s semantics. $ref, $dynamicRef, and $recursiveRef are rejected,
including local references. Output schemas and extra provider-specific tool
declaration fields are unsupported. Tool annotations are not policy input;
keep authorization data in supported assessed content.
How content and routing identities are preserved
How content and routing identities are preserved
The evaluator receives normalized Anthropic-style messages. JSON tool results
become individual text blocks for evaluation and are restored to their original
JSON block types after validation.Opaque tool-call IDs are replaced with consistent, nonnumeric aliases for each
structured assessment. Original IDs remain local, and are restored only after
the returned aliases are validated unchanged. This prevents generic PII detection
from treating SDK routing IDs as phone numbers. Unknown, swapped, added, or
modified aliases are refused. Tool names, arguments, results, schemas, and
system instructions remain subject to assessment. The direct advisory client
sends caller-supplied payloads as given.The additional text assessment uses an immutable prefix and an ordered mapping
to the original content locations. JSON values appear as individual units;
repeated equal text does not replace unrelated fields. Changes remain staged
until both decisions and all structural/schema checks succeed. A changed prefix,
role, block count, or immutable metadata is refused.Encoded JSON objects, arrays, and quoted strings are decoded for text assessment.
Unchanged encoded text keeps its original formatting. Bare numeric-looking,
boolean-looking, and null-looking SDK strings remain strings; typed JSON values
keep their categories. Traversal is bounded to 64 levels and 100,000 nodes,
including encoded layers. Recognizable JSON that violates duplicate-key,
nonfinite-number, or resource checks is refused.A full-message evaluation requires a matching structured replacement. A generic
{"input": "replacement"} is not a valid rewrite of a multi-message payload.
Message metadata and tracking IDs stay local and are omitted from evaluator
payloads as non-provider content.Streaming and telemetry
GuardedAgent returns complete accepted text and offers no token stream. Its
internal callback validates and bounds raw model/tool events before the SDK
consumes them. It refuses malformed or truncated streams and malformed tool
argument JSON instead of allowing the SDK to repair it into an empty object.
The supported model event protocol is the sequential Bedrock-style protocol;
provider-specific fields and alternate tool-identity-in-delta protocols are
refused.
The lower-level intervention sees completed model output. Raw SDK streams
and callbacks can expose tokens before a later output block. Setting
callback_handler=None disables default printing, but does not make raw
streaming preventive. Use the complete-result interface when response content
must be checked before delivery.
The guarded facade wraps the model through the public Strands Model interface
and converts provider stream exceptions to content-free errors before SDK error
instrumentation. The application still owns the provider lifetime. Local token
estimation uses the base model heuristic rather than an optional remote token
counting method.
Trace redaction checks the supported SDK tracer fields at construction and on
invocation. An absent or changed field refuses construction. The integration
does not mutate global telemetry settings. Preflight keeps blocked system/tool
context out of agent invocation; allowed system text can still appear in the
separate system_prompt span attribute.
Configure third-party spans, exception exporters, Python logging handlers,
tool-owned stdout/stderr, HTTPX logging, callbacks, and provider instrumentation
separately. Avoid recording prompts, tool results, request bodies, credentials,
and raw exceptions. The supported return value and trace redaction do not imply
that arbitrary application code cannot disclose data.
Using a native Strands agent
UseTrustGuardIntervention when your application owns the native agent:
session_id, consumer_id, max_evaluations=128, and
text_assessment=True. A shared intervention keeps separate failure and decision
state for each agent. decisions(agent) returns bounded stage/status records.
Failed agents cannot continue. Direct native tool calls share the agent’s
evaluation counter until a normal invocation begins.
Its async assess(payload, direction, stage) method performs a bounded
standalone assessment with a fresh per-call budget. It does not authorize a
later unassessed execution.
Errors
All protection errors inherit fromTrustGuardError. Messages are content-free;
raw upstream bodies and finding evidence are not exposed.
Unknown statuses, duplicate JSON keys, nonfinite numbers, invalid Unicode,
malformed transforms, and inconsistent finding-action precedence are refused.
Transport fail-closed behavior cannot turn an
allow from an unmatched,
Observe, or fail-open server policy into a verified enforcing decision.
Verify your integration
- Use a dedicated test collector and synthetic content with known matching rules. Confirm Input and Output directions and the selected policy mode.
- Confirm an accepted prompt returns a complete response and stage/status
decisions. Reconcile the conversation in Activity using your
session_id. - Trigger an input block and confirm the model is never called. Trigger an output block and confirm no response text reaches the application caller.
- Trigger a tool-argument block and confirm the tool performs no effect. Trigger a tool-result block and confirm the next model turn does not run.
- Test transformations in prompts, history, output, tool arguments, and results. Confirm only the accepted replacement continues and unsupported replacements fail closed. Include older history and nested JSON in your cases.
- Test unavailable service, invalid authentication, malformed decisions, resource limits, and cancellation. Confirm failed conversations refuse reuse.
- Review application logs and telemetry using synthetic markers. Verify the configured provider’s stream protocol separately before deployment.
NeuralTrust/strands-neuraltrust.
For endpoint semantics, see the Evaluate API. For
gateway enforcement across applications and clients, see
TrustGate.
Development and security reporting
Development and security reporting
Install the locked development environment in the package checkout and run the
standard checks:Default tests disable network sockets and use synthetic data. Keep live service
credentials and test evidence out of contributions. Add behavior-focused
regressions for transport, enforcement, transformation, cancellation, and
caller-visible results. Dependency updates require lifecycle, streaming,
telemetry, cancellation, and failed-conversation checks. New content types
require lossless reconstruction and schema/identity preservation.Report vulnerabilities privately to NeuralTrust maintainers through your
existing project contact. Do not open a public issue containing exploit
details, credentials, production prompts, service responses, or unredacted
traces. Include the package, Strands, and Python versions; the affected
lifecycle boundary; a synthetic reproduction; expected and observed behavior;
and the relevant collector policy mode.