Skip to main content

Overview

A TraceCtrl guardrail is a declarative check that runs an LLM judge over an agent’s input or output. Each evaluation emits a tracectrl.guardrail.evaluation OTEL span; failed evaluations land in the Alerts page (/alerts) and the agent’s registered guardrails appear in the Guardrails registry (/guardrails). The in-SDK guardrails work today with Strands agents. The core Guardrail class is framework-agnostic; the Strands binding lives in tracectrl.guardrails.strands_hook.

The Guardrail class

Placeholder convention

The judge prompt is formatted with simple string replacement (not str.format). Use {output} for post-output guardrails and {input} for pre-input guardrails. Both placeholders are scanned — whichever is present in the template is replaced with the evaluated text.

Wiring guardrails to an agent

wrap_agent_with_guardrails(agent, guardrails) swaps the agent’s class for a generated subclass whose __call__ runs pre-input and post-output guardrails around the wrapped invocation. The agent instance is returned for chaining and re-wrapping is idempotent. register_guardrails(agent, guardrails) only emits the registration spans — it does not wrap the agent. Use this when wrapping happens elsewhere or you want guardrails to appear in the registry without runtime evaluation.

End-to-end example

Span attributes emitted

Every Guardrail.evaluate() call emits a tracectrl.guardrail.evaluation span as a child of the active agent span: wrap_agent_with_guardrails additionally emits one tracectrl.guardrail.registered span per guardrail when the agent is wrapped:

How the dashboard renders this

  • The Guardrails registry at /guardrails lists every guardrail whose registration span has been ingested, grouped by agent.
  • The Alerts page at /alerts lists every evaluation where decision="fail" or "error", with the reason and evidence rendered inline and a link back to the parent trace.

Error handling

The judge is called via Bedrock’s converse API with a forced tool-call schema. If the judge fails or returns invalid JSON twice in a row, the SDK conservatively treats the evaluation as a pass — a broken judge must not spam false-positive violations. The span still carries decision="error" so health monitoring catches the regression. Exceptions raised inside Guardrail.evaluate() never bubble up to the agent.