Instrument your agent

The existing plugins are worked examples, not special cases. Any agent framework connects to OGR the same way. If your framework exposes a tool/exec lifecycle, you can secure it.

pip install openguardrails        # or: npm install @openguardrails/core

The four steps

1. Find your interception points

Map your framework's hooks to OGR altitudes. You want, in priority order:

  • a pre-tool / pre-exec hook that can blockinvocation altitude
  • the exec chokepoint where commands actually run → execution altitude
  • (optional) the LLM request/response boundary → conversation altitude
  • (optional) a post-tool hook to taint provenance from web/MCP results

Most agent frameworks have at least the first two. Hermes exposed all four as plugin hooks, so no forking was needed.

2. Emit a GuardEvent at each point

Translate the hook's arguments into a GuardEvent. Mint a guard_id at the first altitude and propagate it (a guard-context) to the exec point so they correlate.

from openguardrails import GuardEvent

ev = GuardEvent(
    kind="tool_call", observation_point="invocation",
    sensor={"id": "my-framework-hook", "class": "in_process"},
    subject={"agent_id": "my-agent", "agent_type": "custom"},
    payload={"name": tool_name, "arguments": args},
    provenance=current_session_provenance(),   # trusted by default; untrusted if tainted
    event_id=new_event_id(), guard_id=guard_id,
    timestamp=now_rfc3339(), session_id=session_id,
)

3. Evaluate with the SDK RuntimeClient

Don't hand-roll HTTP — the SDK client wraps the Runtime API (auth, signing, wire mapping, errors):

from openguardrails import RuntimeClient, RuntimeAPIError

client = RuntimeClient()          # OGR_RUNTIME_URL + OGR_API_KEY

try:
    verdict = client.evaluate(ev)             # POST /v1/evaluate
except (RuntimeAPIError, OSError):
    verdict = apply_on_unreachable(ev)        # cached GET /v1/config policy —
                                              # never fail open on security.*

Cache the degraded-mode config at startup so the except branch has a policy to apply. For purely local evaluation (no hosted runtime), the SDK also ships an in-process Runtime you can build from a policy and detectors — same evaluate(event) → Verdict shape.

4. Enforce the verdict

if verdict.decision in ("block", "require_approval"):
    return block(reason=verdict.reasons)   # your framework's "don't run this" path
if verdict.decision in ("modify", "redact"):
    apply(verdict.modifications)           # transform, then proceed

For require_approval you can instead suspend and poll GET /v1/approvals until a human decides. At the execution altitude, "enforce" can also mean run the command under a real sandbox (srt / OpenShell) compiled from the same policy — so a rephrased command can't bypass the intent check.

Also report what you observe but don't gate — transcript, tool results — through /v1/ingest (BatchingIngestor makes it fire-and-forget), and enroll a key so your events carry a verifiable identity.

Reference implementation

The Hermes plugin is ~250 lines and demonstrates all four steps:

  • bridge.py — hook callbacks ↔ GuardEvent, provenance/taint, guard-context.
  • sandbox_guard.py — wrap the exec chokepoint; run under srt when configured.
  • __init__.py — bind the four hooks.

Graceful degradation

If your framework has no sandbox, you still get the invocation altitude — OGR enforces on intent, and records that the adversary-proof layer was unavailable. Add a sandbox later without changing your policy.

Start from Policy and adapt the bridge to your framework's hooks.