Skip to content
agentFast
The production layer

Guardrails

PII redacted before the model sees it, injection defence, limits.

In short: personal details — emails, card numbers, ID numbers — are stripped out before the AI provider ever sees them, and before anything reaches a log. Plus defences against people trying to manipulate your agent through the documents it reads.

Guardrails run on both sides of every model call and around every tool result. The ordering matters more than the individual checks: redaction happens before the provider sees the payload, not after.

PII redaction

Six kinds by default — email, card, SSN, phone, IP, secrets:

guardrails:
  pii_enabled: true
  pii_kinds: [email, card, ssn, phone, ip, secret]

Three properties worth understanding:

It runs before the model call. A customer's email is [EMAIL_1] by the time the request leaves your process. Not redacted in the log afterwards — never sent.

Placeholders are stable per run. The same value is [EMAIL_1] everywhere in that run, so the model can still reason about "the customer's email" coherently rather than seeing unrelated tokens.

Tool outputs are redacted too. Loop-owning adapters get this free, since results re-enter the message history. SDK-owned loops hand a tool's output straight back to the model, so their bridges call redact_tool_output explicitly — otherwise customer_lookup would leak PII into the model input even though the stored trace was clean.

TipHardened against obfuscation

Naive redaction is defeated by zero-width characters, homoglyphs and spacing tricks — a​lice@example.com passes a regex that alice@example.com fails. Input is normalised before matching. This was found by an adversarial review pass and is regression-tested.

Injection defence

guardrails:
  safety_enabled: true
  injection_action: flag    # flag | block | allow
  • flag — neutralise and record a guardrail step. The default: it keeps the run useful while making the attempt visible.
  • block — refuse the call outright.
  • allow — detect and record, change nothing. For measuring before enforcing.

Retrieved documents and tool outputs are treated as untrusted content, which is where injection actually arrives — a poisoned KB document is a far more likely vector than a user typing "ignore previous instructions".

Rate limits

Token-bucket, per tool and global, backed by Redis when configured:

redis_url: redis://localhost:6379
rate_limits:
  global: "100/minute"
  default_per_tool: "20/minute"

A limited call returns RATE_LIMITED with a retry hint rather than raising — so the model can back off or route around it, exactly like any other tool failure.

Without redis_url the limiter is in-process, which is correct for a single instance and wrong for several. Configure Redis before you scale horizontally.

Grounding

Retrieval-backed answers get a confidence score comparing the answer against what was actually retrieved. It surfaces on the run record and feeds the eval scorers, so "confidently wrong" becomes a number you can gate a release on rather than something a user reports.

What guardrails don't do

They don't stop an agent doing something expensive that it's allowed to do. A refund tool with risk: low will issue refunds all day, correctly, with the customer's PII redacted throughout. Deciding what needs a human is human-in-the-loop; guardrails are about what enters and leaves the model.