Harbor

Guardrails

Policy checks on every agent tool call, configured first, formally verified before they run, and enforced through the SDK or the gateway.

Guardrails put a boundary around what your agent can do. Every tool call the agent attempts (a transfer, an email, a database write) is checked against your policies before it executes. A call that violates a policy is blocked, and the blocking reason is returned to the agent in machine-readable form, so it adapts instead of retrying blindly.

Three properties define the layer:

  • Deterministic. The check is a computation over the call and the session's history. No model in the loop: the same call gets the same verdict, every time, and the verdict can be reproduced later, which is what makes it usable as evidence.
  • Fast. A check takes microseconds. Tool calls take seconds. The overhead is not measurable in practice.
  • Verified. The policy set is proven coherent before it is allowed to run. This is the part nobody else does.

Policies come first

You start by declaring what the agent is allowed to do, as typed policies. The catalogue is deliberately small and covers the shapes that matter in practice:

ConstraintWhat it capsExampletype:
Numeric boundA numeric argumentTransfers capped at 5,000Bounded
Value restrictionWhich values an argument may takeOnly approved instruments; recipients on an allowlist
OrderingWhich call has to come firstA balance check must precede any transferPrecedes
Session budgetA total across the whole sessionTotal spend, not just per-call amounts
Repetition capHow often a call may repeatAt most three payments per recipient; this tool never twiceMaxCalls
Tool allowlistWhich tools exist at allAnything not declared is blocked
Conditional activationWhen another policy appliesA tighter cap until a human approves; stricter rules once the agent has read untrusted contentWhen

You define policies in the Harbor platform: pick the type, scope it to a tool, set the bounds. The configuration is versioned, and it reads as YAML:

# illustrative
tools: [check_balance, transfer, read_email]

tiers:
  untrusted: [read_email]
  internal: [check_balance, transfer]

mode: observe            # flip to enforce, per policy, when ready

policies:
  - type: Bounded
    name: transfer_cap
    tool: transfer
    arg: amount
    lower: 0
    upper: 5000

  - type: Precedes
    name: balance_first
    first: check_balance
    second: transfer

  - type: When           # freeze transfers once untrusted content is read
    name: taint_freeze
    when: { trust_below: internal }
    policy: { type: MaxCalls, tool: transfer, max_calls: 0 }

Policies can also be drafted from a plain-language description and turned into typed policies you review. Either way, nothing activates without passing verification.

Verified before it runs

This is the part nobody else does

Every rule engine evaluates rules. Almost none of them check the rules themselves.

Rule sets accumulate contradictions: one policy requires an approval step that another policy makes impossible, or a new rule silently forecloses a path the workflow depends on. You find out in production, when the agent deadlocks or does something the rulebook was supposed to prevent.

Harbor verifies the entire policy set for coherence before it can be deployed. A contradictory set is rejected at configuration time, with a concrete explanation of which policies conflict and why. The verification is exhaustive over the policy language, a proof rather than a test suite, so a set that passes cannot contradict itself at runtime. We do not document the procedure itself here.

Changes are held to the same standard. When you edit a deployed policy set, the new set is checked against the old one: if the change would newly permit something that was blocked before, you are shown a concrete example call that demonstrates it, before the change goes live.

Configuration timeRuntime
Policy set proven coherentExhaustively, over the policy languageAlready guaranteed
Contradictory setRejected, naming the policies that conflictCannot occur
Edit to a deployed setDiffed against the old set, with a counter-example call
Individual tool callEvaluated in microseconds

Observe first, then enforce

Every policy runs in one of two modes, and you flip individual policies between them with no re-integration and no code change.

ObserveEnforce
Policy evaluated on every callYesYes
Verdict recordedYesYes
Violating call blockedNoYes
Risk to production trafficNoneThe blocked call

Observe mode shows you exactly what enforcement would have stopped. When the picture looks right, you promote the policies you trust.

Where it runs

The same engine and the same policies work at two integration points — the SDK inside your agent's process, and the gateway on the wire. They differ only in what they can see; the overview has the full comparison.

Through the SDK, wiring looks like this:

# illustrative
import harbor
from harbor.guardrails import guard_tools

harbor.init()

tools = guard_tools(tools, agent="payments-agent")
# every tool call is now checked against the policies
# configured for payments-agent in the Harbor platform

The SDK ships adapters for the common agent frameworks, so wiring stays a few lines whichever one you use. Through the gateway there is nothing to wire: guardrails are enabled per agent in the platform and enforced on the wire.

Start in observe mode on whichever is easier to adopt; move to the SDK where enforcement matters most.

On this page