agent-guard
v0.2.0 · Cedar 4.x · AuthZEN-compatible PDP

Authorization for AI agents you can verify.

Cedar-powered policy evaluation for every tool call. Tamper-evident audit, scoped delegation, JWS-signed tokens. Drop in a CLI, mount a sidecar, or embed the engine in-process — the same decisions, the same chain.

Apache-2.0 · Rust 1.89+ · Node.js 20.9+ · Zero proprietary protocols
agentguard · authz.evaluate
live
Request
principalAgent::"research"
actionToolCall::send_email
resourceMailbox::"alice@acme"
context{"session":{"mfa":true},"args":{"to":"bob@acme.dev"}}
hash-chained · append-only

Standards-native · interop-first

Cedar 4.x OpenID AuthZEN OpenTelemetry RFC 7519 / 8725 RFC 9449 · DPoP RFC 8693 W3C Trace Context SPIFFE
The agent-permission gap

The hard part of agents isn't the model.

Once an agent can call tools, every call is a decision. Who made it. What was allowed. With what context. Whether the policy the security team wrote yesterday still applies today.

Most stacks answer those questions with imperative code, scattered logs, and vendor-specific protocols. By the time an incident lands, the chain is broken and the audit is unreadable.

agent-guard moves authorization out of the application and into a verifiable, standards-native engine — one chain for every decision, every surface, every agent.

How it works

Three steps. One chain.

Every tool call flows through the same pipeline, regardless of surface.

01

Intercept

Every tool call passes through one of four surfaces — TypeScript SDK, AuthZEN HTTP, CLI, or the admin console — bound to a short-lived identity (JWT, DPoP, SPIFFE, API key).

              principal: Agent::"research"
action:    ToolCall::send_email
resource:  Mailbox::"alice@acme"
            
02

Evaluate

The Cedar engine resolves entities against a typed schema, walks the policy bundle, and produces an explicit Allow or Deny. Hot-reloaded, versioned, blast-radius-checked.

              policy 20_agents.cedar (v7)
forbid(principal, action, resource)
when { principal.scope excludes resource }
            
03

Record

Every decision is appended to a hash-chained log with a JWS-signed envelope. Verify the chain end-to-end; export to ECS, CEF, LEEF, or JSONL for your SIEM.

              decision_id: 0x9f4a
prev_hash:    0x71c2
hash:         0xa3b8…  (HMAC-SHA-256)
            
.agentguard/policies/20_agents.cedar
// forbid a sub-agent from sending email outside its delegated scope
forbid(
  principal in Agent::"research",
  action    == Action::"send_email",
  resource  in Mailbox::"*"
)
when { principal.scope.mailboxes excludes resource };
Product

Six primitives. Zero guesswork.

Everything you need to put a verifiable authorization boundary around an agent — no bespoke plumbing.

Per-call authorization

Every tool call is an explicit Cedar decision — principal, action, resource, context. Allow runs the tool, deny raises AuthorizationDenied back to the model.

Tamper-evident audit

Every decision is appended to a hash-chained log. Verify the chain end-to-end, export to CEF, LEEF, ECS, or JSONL for your SIEM.

Scoped delegation

A parent agent gives a sub-agent a scoped subset of permissions, time-boxed, sender-constrained (DPoP), and revocable.

Schema-validated Cedar

Security teams write Cedar policies, not imperative code. Validated at authoring time against a typed schema of entities, actions, and context shapes.

Standards-native authn

JWT, OIDC, API keys, DPoP, SPIFFE — RFC 8725 BCP crypto, RFC 8693 token exchange, no proprietary protocols.

Hot reload + blast radius

Push policies without downtime. See what would break before you push, roll back instantly, observe decisions as OTel spans.

One engine, every surface

Same decision, same chain.

The TypeScript SDK, the AuthZEN HTTP PDP, the CLI subprocess, and the admin console all converge on the same Cedar engine. Authorize from anywhere — the audit doesn't know the difference.

agent.ts
20 lines
import { Client, Principal, Action } from "agentguard";

const client = new Client({ store: ".agentguard" });

const decision = client.check(
  Principal.user("alice"),
  Action.tool("send_email"),
  { entity_type: "Mailbox", uid: "alice@acme" },
  { args: { to: "bob@acme.dev" }, session: { ip: "10.0.0.1", mfa: true } },
);
// → Allow

// Scoped delegation (RFC 8693, JWS-signed, time-boxed):
await client.delegate(
  'Agent::"research"',
  'Agent::"summarizer"',
  ["ToolCall::send_email"],
  ["Mailbox::*"],
  300, // seconds
);
Tamper-evident audit

Every decision, chained.

Append-only, HMAC-linked, JWS-enveloped. Verify the chain at any time. Export to your SIEM in the format it already speaks.

.audit/decisions.jsonl
append-only
0x9f4aprincipal=Agent::"research" action=send_emailallow0xa3b8
0x9f4bprincipal=Agent::"summarizer" action=read_docallow0x71c2
0x9f4cprincipal=Agent::"untrusted" action=delete_dbdeny0x4e8f
0x9f4dprincipal=User::"alice" action=send_emailallow0x8d12
0x9f4eprincipal=Agent::"research" action=searchallow0x33aa
5 records · chain head 0xa3b8…HMAC-SHA-256
Verify the chain
agentguard audit verify \
  --audit .audit/decisions.jsonl \
  --secret-file .chain-secret
# ✓ chain integrity verified
#   12,481 records · head 0xa3b8…
Export
ECS
Elastic Common Schema
CEF
ArcSight Common Event Format
LEEF
IBM QRadar Log Event Extended Format
JSONL
Line-delimited, custom schemas
Architecture

One engine, every surface.

SDKs, the HTTP PDP, the CLI, and the admin console all converge on the same Cedar core and the same hash-chained audit.

TypeScript SDK in-process AuthZEN HTTP PDP sidecar / gateway CLI subprocess Admin Console Next.js · OIDC agentguard-core Cedar 4.x engine decision cache · hot reload Audit log hash-chained · JSONL OTel / OTLP spans · metrics Decision Allow · Deny · StepUpRequired
Inputs

Principal · action · resource · context. Short-lived identity (JWT, DPoP, SPIFFE, API key).

Engine

Typed Cedar schema. Versioned policy bundles. Hot reload with blast-radius check.

Outputs

Allow · Deny · StepUpRequired. OTel span with authz.* attributes. Append to hash-chained log.

Standards

Built on the specs you already trust.

No proprietary wire protocols. Every piece is the RFC, the working-group draft, or the maintained open-source implementation.

Adoption

Run it your way.

Open-source under Apache-2.0. Three patterns that cover almost every deployment shape we've seen.

01 open-source

Self-host

Open-source under Apache-2.0. Drop the CLI into your agent, ship a sidecar, or embed the Cedar engine in-process. Files in .agentguard/ are the source of truth.

$ cargo install --path crates/agentguard-cli
Read the docs
02 open-source

Run as a sidecar

agentguard serve speaks OpenID AuthZEN over HTTP and gRPC. Use it with any language, any gateway, any federation tool that speaks AuthZEN.

$ agentguard serve --listen tcp://0.0.0.0:8443
Read the docs
03 open-source

Embedded in-process

Mount the agentguard-server router inside your existing axum app. The same Cedar engine, the same audit chain — without an extra hop on the data path.

$ use agentguard_server::build_router
Read the docs

Ship it

Put a verifiable boundary around your agent.

Apache-2.0, no proprietary protocols, no vendor lock-in. Drop in the CLI, run the sidecar, or embed the engine — the chain stays the same.