Scoped, time-limited authorization infrastructure for AI agents.
In the Iliad, Achilles delegated his armor and authority to Patroclus with explicit scope: drive the Trojans from the ships, then return. Patroclus exceeded his scope, pursued too far, and the consequences were catastrophic. Patroclus (the project) ensures that never happens to your AI agents.
Patroclus is a self-hostable authorization control plane for AI agents. It sits between agents and the resources they need to access — APIs, MCP servers, databases, cloud services — and enforces scoped, time-limited, revocable permissions with human-in-the-loop approval workflows.
Agents today are handed static API keys and long-lived tokens. Patroclus replaces that with just-in-time access: an agent requests access to a specific resource for a specific action, policies are evaluated in real-time, and either a short-lived scoped credential is issued or a human approval is triggered.
- Just-in-time token issuance — agents get scoped, short-lived JWTs (5–15 min) only when policy allows it. No standing permissions.
- Default-deny — no matching policy means deny, always
- Per-call policy evaluation — every action checked against policy in real-time
- Hot-reloadable policies — create/update policies without server restart
- Human delegation — humans delegate scoped permissions to agents with constraints (max spend, time windows, etc.)
- Multi-agent delegation — agents sub-delegate with monotonic attenuation (scopes can only narrow, never widen)
- Delegation depth limits — configurable max chain depth
- Cascade revocation — revoking a parent grant atomically invalidates all children and issued tokens
- Human-in-the-loop — sensitive actions trigger approval requests routed to resource owners or admins
- Single-use approval tokens — approved requests get one-time, action-scoped tokens
- Approval lifecycle — pending → approved/denied, with expiry and status lookup
- YAML rules with pattern matching (
dev-*,api:*,*) - Rate limiting — per agent/action/resource sliding window
- Budget caps — deny after cumulative spend exceeds limit
- Progressive trust decay — auto-tighten permissions after idle time
- Workflow sequencing — require prior action in session trajectory
- Max actions per session — cap total actions in a session
- Pluggable backends — OPA/Rego and Cedar ready (interface defined)
- Per-session trajectory — tracks all actions in a session (capped at 1000)
- Kill switch — emergency agent termination kills all sessions + revokes tokens
- Spend tracking — record and accumulate spend per session
- Trust level — starts at 1.0, decays after configurable idle threshold
- AES-256-GCM encryption at rest for upstream provider credentials
- OAuth provider integrations — GitHub, Google, Slack refresh token exchange
- Token vending — agents get scoped access tokens, never see raw secrets
- Per-principal isolation — each principal's credentials stored separately
- JWT RS256 with agent-specific claims (
sub,act,scope,aud,jti) - Audience binding (RFC 8707) — tokens bound to specific resources
- Replay protection — JTI tracking with in-memory revocation store
- Token revocation — by JTI, with DB persistence
- DPoP ready — proof-of-possession support (interface defined)
- Hash-chained audit log — SHA-256 chain, tamper-evident
- Chain verifier —
patroclus verify-chainrecomputes the chain and reports the first broken link (exit code 1 on tamper,--jsonfor machines) - Every decision logged — allow, deny, require_approval with full context; dry-run
/v1/agent/checkdecisions audited with adry_runflag - Attribution-complete — every action traces to human or system authority
- Delegation chain in log — full chain captured, not reconstructed
- Relay integration — Relay MCP gateway calls Patroclus before every tool dispatch
- Per-tool authorization — each MCP
tools/callchecked against policy - Fail-closed — if Patroclus is unreachable, tool calls are denied
- OIDC integration — Okta, Azure AD, Google Workspace, Auth0, any OIDC provider
- Group-based policy mapping — IdP groups map to Patroclus policies (e.g., "Engineering" group → dev access policy)
- Token exchange — RFC 8693 token exchange from IdP token → Patroclus delegation token
- Auto-provisioning — principals auto-created on first IdP login
- Forge integration — Forge verifies agent signatures, generates SBOMs, scans for vulnerabilities, and calculates trust scores
- Trust-based policies — Patroclus policies can reference Forge trust scores (min_trust_score)
- Blocking — agents with critical vulnerabilities are blocked from registration
- Non-blocking SQLite access — all database calls run on tokio's blocking
pool (
spawn_blocking) with WAL +busy_timeouttuning; optional r2d2 read pool via[database] read_pool_size— see docs/DATABASE_CONCURRENCY.md - Prometheus metrics —
/metricsexposes authz decision counters, request latency histograms, session/approval-depth gauges and token issuance — see docs/METRICS.md
┌─────────────────────────────────────────────────────────────────────┐
│ PATROCLUS │
│ │
│ ┌──────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────┐ │
│ │ Agent │──▶│ Request │──▶│ Policy │──▶│ Decision │ │
│ │ Runtime │ │ Gateway │ │ Engine │ │ Router │ │
│ └──────────┘ └──────────────┘ └─────────────┘ └─────┬────┘ │
│ │ │ │
│ │ ┌────────────┐ ┌─────▼────┐ │
│ │ │ Approval │ │ Token │ │
│ │ │ Service │◀──│ Issuer │ │
│ │ └──────┬─────┘ └─────┬────┘ │
│ │ │ │ │
│ ┌──────────┐ ┌────▼─────┐ ┌───────────┴──┐ ┌───────▼────┐ │
│ │ Human │◀───│ Notify │ │ Audit Log │ │ Credential│ │
│ │ Approver│───▶│ Service │ │ (Hash-chain) │ │ Vault │ │
│ └──────────┘ └──────────┘ └──────────────┘ └────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Policy Store (YAML) │ Session Store │ Resource Registry│ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
# Build
cargo build --release
# Initialize config
./target/release/patroclus init
# Generate RSA keys for token signing
./target/release/patroclus generate-keys -o keys
# Start the server
./target/release/patroclus serve --config config.toml
# Verify the audit hash chain (tamper detection)
./target/release/patroclus verify-chain --db patroclus.dbConfiguration lives in config.toml (see patroclus init) and can be
overridden by environment variables. Layering: file < environment — an
environment variable always wins over the file value.
Every config field can be overridden with PATROCLUS_<SECTION>__<FIELD>
(double underscore as the nesting separator, case-insensitive). Values are
parsed as TOML scalars (numbers, booleans, and [...] arrays); anything else
is taken as a literal string. Unknown variables are ignored with a warning.
This is the supported channel for injecting secrets (key paths, IdP client
secrets) in container deployments without baking them into the file.
| Variable | Overrides | Example |
|---|---|---|
PATROCLUS_SERVER__HOST |
server.host |
0.0.0.0 |
PATROCLUS_SERVER__PORT |
server.port |
8484 |
PATROCLUS_SERVER__CORS_ALLOWED_ORIGINS |
server.cors_allowed_origins |
["https://console.example.com"] |
PATROCLUS_DATABASE__PATH |
database.path |
/var/lib/patroclus/patroclus.db |
PATROCLUS_DATABASE__READ_POOL_SIZE |
database.read_pool_size |
4 |
PATROCLUS_TOKEN__ISSUER |
token.issuer |
https://patroclus.example.com |
PATROCLUS_TOKEN__PRIVATE_KEY_PATH |
token.private_key_path |
/run/secrets/private.pem |
PATROCLUS_TOKEN__PUBLIC_KEY_PATH |
token.public_key_path |
/run/secrets/public.pem |
PATROCLUS_TOKEN__DEFAULT_TTL_SECONDS |
token.default_ttl_seconds |
900 |
PATROCLUS_TOKEN__MAX_TTL_SECONDS |
token.max_ttl_seconds |
3600 |
PATROCLUS_POLICY__ENGINE |
policy.engine |
yaml |
PATROCLUS_POLICY__DEFAULT_DECISION |
policy.default_decision |
deny |
PATROCLUS_POLICY__MAX_DELEGATION_DEPTH |
policy.max_delegation_depth |
3 |
PATROCLUS_VAULT__ENCRYPTION_KEY_PATH |
vault.encryption_key_path |
/run/secrets/vault.key |
Related (non-config) variables used by other subsystems:
| Variable | Purpose |
|---|---|
PATROCLUS_ADMIN_TOKEN |
Static admin bearer token for /v1/admin/* (required in release builds) |
PATROCLUS_INSECURE_DEV |
1 permits unauthenticated admin routes / insecure dev keys (never production) |
PATROCLUS_LOG_FORMAT |
json switches logs to JSON |
Example:
PATROCLUS_SERVER__PORT=9000 \
PATROCLUS_DATABASE__PATH=/data/patroclus.db \
PATROCLUS_ADMIN_TOKEN="$(openssl rand -hex 32)" \
./target/release/patroclus serve --config config.tomlpip install -e sdk/pythonfrom patroclus_sdk import PatroclusClient, authorized_action
client = PatroclusClient("http://localhost:8484")
# Register agent
agent = client.register_agent("my-agent", owner_id=principal["id"])
# Create policy
client.create_policy("dev-access", """
- name: allow-dev-reads
actions: ["read"]
resources: ["dev-*"]
scopes: ["*"]
decision: allow
reason: Dev read access permitted
""")
# Check access
result = client.request_access(agent["id"], "read", "dev-db", ["db:read"])
if result.allowed:
print(f"Token: {result.token}") # JWT with 15-min TTL
# Or use the decorator
@authorized_action(client, action="read", resource="dev-db", scopes=["db:read"])
def fetch_users(agent_id, patroclus_token=None):
return call_database(patroclus_token)# Start Patroclus
./target/release/patroclus serve
# Run the agent (requires OPENROUTER_API_KEY)
OPENROUTER_API_KEY=your-key python examples/agent.pyThe agent:
- Registers itself with Patroclus
- Creates a policy
- Asks the LLM (via OpenRouter) what actions to take
- Before each action, checks with Patroclus for authorization
- If allowed, gets a scoped JWT token
- If denied, reports the reason (rate limit, policy deny, etc.)
- If approval required, creates an approval request
| Category | Endpoints |
|---|---|
| Agent-facing | POST /v1/agent/request-access, POST /v1/agent/check, POST /v1/agent/delegate |
| Principal-facing | POST /v1/principal/delegate, GET /v1/principal/approvals, POST /v1/principal/approvals/{id}/approve |
| Admin | POST /v1/admin/agents, POST /v1/admin/policies, GET /v1/admin/audit |
| Sessions | GET /v1/sessions, POST /v1/sessions/{id}/kill, POST /v1/admin/agents/{id}/kill |
| Vault | POST /v1/vault/credentials, POST /v1/vault/vend |
| Health | GET /health |
See docs/LLD.md for the full API specification.
{
"iss": "https://patroclus.example.com",
"sub": "user:alice@example.com",
"act": { "sub": "agent:agent_001", "delegation_depth": 0 },
"scope": "db:read:prod-db/users",
"aud": "resource:prod-db",
"exp": 1723643820,
"jti": "01J5Q3Z...",
"constraints": { "max_rows": 1000 }
}- name: allow-dev-reads
actions: ["read", "query"]
resources: ["dev-*", "test-*"]
scopes: ["*"]
decision: allow
reason: Dev read access permitted
- name: rate-limited-api
actions: ["call"]
resources: ["api-*"]
scopes: ["*"]
decision: allow
reason: API access permitted
rate_limit_per_minute: 5
- name: budget-capped-deploy
actions: ["deploy"]
resources: ["cloud-*"]
decision: allow
max_spend: 100.0
- name: require-approval-prod
actions: ["write", "deploy"]
resources: ["prod-*"]
decision: require_approval
reason: Production operations require human approval
- name: workflow-sequenced
actions: ["execute_trade"]
resources: ["trading-*"]
decision: allow
require_prior_action: "load_profile"| Suite | Tests | Status |
|---|---|---|
| Rust unit (session) | 10 | ✅ |
| Rust integration (Phase 1–4) | 40 | ✅ |
| Rust integration (Phase 5) | 14 | ✅ |
| Python SDK | 17 | ✅ |
| Total | 81 | All passing |
# Run all Rust tests
cargo test
# Run Python SDK tests (requires running server)
cd sdk/python && python -m pytest tests/Patroclus is part of the AI governance ecosystem governed through Governance Hub:
| Project | Role |
|---|---|
| Hive | Agent runtime & orchestration — which agent does the work |
| Patroclus | Authorization infrastructure — is the agent allowed to do this |
| Relay | MCP gateway & tool proxy — route the agent's tool calls |
| Miser | Cost optimization — which model is cheapest for this |
| Sentiel | Observability, DLP & compliance — what are agents doing? |
| Aegis | Network egress & attestation — is the agent's network safe? |
| Forge | Agent supply chain security — is the agent code trusted? |
| Argus | Human/agent OIDC identity provider — who is calling? |
| Governance Hub | Unified admin console and sole product UI |
See docs/ECOSYSTEM_PLAN.md for the full integration plan.
- High-Level Design — system overview, principles, components
- Low-Level Design — module architecture, DB schema, API spec
- E2E Architecture — complete flow diagrams and scenarios
- Ecosystem Plan — Hive + Patroclus + Relay + Miser integration
- Project Plan — original planning document with landscape review
- OPA/Rego policy backend
- Cedar policy backend
- PostgreSQL backend (production database)
- Redis for distributed session state and rate limiting
- Signed revocation feed (offline verification without callback)
- DPoP proof-of-possession (RFC 9449)
- TypeScript/Node SDK
- Go SDK
- Admin dashboard (React/Next.js)
- CLI tool for policy management
- Helm chart for Kubernetes deployment
- OAuth 2.1 well-known endpoints (
/.well-known/oauth-authorization-server) - Dynamic client registration (RFC 7591)
- Temporal policies (trajectory-aware, like Amazon Bedrock AgentCore)
- Anomaly detection (behavioral baseline deviation)
- W3C Verifiable Credentials support
- Multi-tenancy (tenant isolation)
- SPIFFE/SPIRE workload identity integration
- Enterprise IdP federation (Okta, Azure AD, Google)
- Agent-to-agent trust protocol (IATP)
- Compliance framework mapping (EU AI Act, SOC2, HIPAA)
- SDK for LangChain, CrewAI, OpenAI Agents SDK, Google ADK
| Component | Technology |
|---|---|
| Language | Rust (edition 2024) |
| Web framework | Axum 0.8 |
| Database | SQLite (rusqlite, bundled) |
| Token format | JWT RS256 (jsonwebtoken) |
| Encryption | AES-256-GCM (aes-gcm) |
| Policy engine | YAML rules (OPA/Cedar ready) |
| Python SDK | httpx |
MIT