agentstategraph-policy
Policy primitive for AgentStateGraph: authorization + procedures +
ratification lifecycle + cost-of-change gating. The crate ships the
PolicyStore API and the evaluator; signing, tenant filtering, and
external-evaluator dispatch all compose through this surface.
See the policy guide for the end-user overview.
Core types
| Type | Purpose |
|---|---|
Policy |
Unit of authorization + procedure (POLICY_V1.md §2.1) |
PolicyStore |
Repository-backed store; propose / ratify / supersede / evaluate |
Decision |
Result of evaluate — Allow / Deny / RequireApproval / NoPolicyMatch |
ChangeProposal |
Shape-of-change record evaluated via evaluate_change (POLICY_V1.md §22.2) |
Situation |
Flat HashMap<String, String> matched against Selector |
Selector |
Situation matcher: Always / Eq / AllOf / AnyOf |
FallbackAction |
What to do while approval is pending (POLICY_V1.md §22.3) |
Workflow
use Arc;
use Repository;
use MemoryStorage;
use ;
let repo = new;
repo.init?;
let store = new;
// 1. Propose (anyone can propose).
let policy = Policy ;
store.propose?;
// 2. Ratify (quorum / ratifier enforcement is the consumer's job).
store.ratify?;
// 3. Evaluate.
let decision = store.evaluate?;
Advanced features (0.7.5)
Signing
Opt-in via the sibling agentstategraph-policy-sign crate. Policies
carry an optional Policy.signature; the evaluator consults a
registered SignatureVerifier when require_signed_policies is set.
Unsigned policies keep working by default.
use ;
let verifier = new;
store.set_verifier;
store.set_require_signed;
Multi-tenant
Policy.tenant_id: Option<String> — None is a global policy; Some
restricts to callers that pass a matching tenant_filter into the
_scoped evaluator variants (active_scoped, evaluate_scoped,
evaluate_change_scoped, list_scoped,
policies_for_situation_scoped). None filter + Some tenant_id
still match — globals apply to every tenant.
let d = store.evaluate_scoped?;
External evaluators
Policy.external_evaluator: Option<ExternalEvaluatorRef> (Rego /
Cedar / Wasm variants) routes matching policies to a registered
runner. Install runners via
PolicyStore::with_external_evaluators(Arc<ExternalEvaluatorRegistry>).
Runner crates live under agentstategraph-policy-wasm / -rego /
-cedar; see docs/POLICY-EVALUATOR-ABI.md for the WASM ABI.
PolicyStore API — quick reference
// CRUD
propose // Evaluation
evaluate // 0.7.5 scoped variants (multi-tenant)
evaluate_scoped
evaluate_change_scoped
active_scoped
list_scoped
policies_for_situation_scoped
// 0.7.5 signing hooks
set_verifier
set_require_signed
set_signature // server-side, after canonicalize
// 0.7.5 external evaluators
with_external_evaluators
Storage layout
Policies live in the state tree under <prefix>/<path>/<version>. A
sibling <prefix>/<path>/_head points at the current version for
cheap latest-lookup. All writes are committed through the
Repository so the full blame / history stack works out of the box.
Where things live
| Feature | Crate |
|---|---|
| Core types + evaluator | agentstategraph-policy |
| Ed25519 signing | agentstategraph-policy-sign |
| WASM external evaluator | agentstategraph-policy-wasm |
| Rego external evaluator | agentstategraph-policy-rego |
| Cedar external evaluator | agentstategraph-policy-cedar |
| MCP tool surface | agentstategraph-mcp |
| C ABI (for non-Rust consumers) | agentstategraph-ffi |
Soft enforcement
ASG cannot physically stop a misbehaving agent; a Deny is a
machine-readable boundary, not a syscall interceptor. Pair with
OPA / Cedar / cloud IAM for hard enforcement at the infrastructure
layer.
License
Licensed under either of Apache License, Version 2.0 or MIT license, at your option.