raxit
Capabilities

Agent identity & attestation

How raxit binds every decision to an attested agent identity.

If the identity an agent presents doesn't match anything in security.yaml, every call it makes denies — not because a rule blocked it, but because no rule could ever reference that principal:

security.yaml: deny.principal_mismatch
hint: The attested principal matches no permit rule's agent, so no rule can ever match it; run
raxit without --agent to auto-derive the agent id, or set agent: <presented-principal> in
security.yaml.

This is the single most common first-run stall — see Common issues for the fix. The reason it happens at all is the point of this page: raxit never lets an agent assert its own identity as a bare string.

The mental model: identity is attested, not asserted

agent: in security.yaml becomes the Cedar principal (Agent::"<value>"). Every decision is bound to a verified identity — a token that was cryptographically checked against a trusted issuer — never a name the agent process simply hands over. An unidentifiable call cannot be permitted, full stop.

What binds identity in practice

For local development, raxit ships a dev HMAC identity: a symmetric LocalTokenVerifier (method idp_local) that signs a token as "<id>|<method>|<hex-hmac(id|method)>" using a shared key (RAXIT_IDENTITY_KEY). raxit run generates a fresh ephemeral dev key per run rather than reusing a static shared default. This is explicitly dev/demo-grade — infra-free, zero-setup, and not attested in the cryptographic sense; it's what makes raxit run -- python agent.py work with no external identity provider on day one.

For production, attested methods bind the principal instead:

  • SPIFFE/SPIRE JWT-SVID — workload identity from a SPIRE agent.
  • Cloud workload identity — AWS IRSA, GCP workload identity, Azure managed identity.
  • OIDC / GitHub OIDC — algorithm-confusion-proof (alg:none tokens are rejected outright).
  • X.509-SVID — mTLS peer authentication, but scoped to the multi-node state server, not agent-principal binding itself.

Whichever method verifies the token, the identity that comes out becomes the Cedar principal and scopes budgets, rate limits, rule matching, and delegation for every subsequent call in the session.

Matching methods to policy

A verified identity still needs its method allowlisted, separately from the identity itself being valid — a verified token using a method not on the allowlist denies with deny.principal_untrusted_method, distinct from an unverified token (deny.identity_unverified) and distinct from a verified-but-unreferenced principal (deny.principal_mismatch, above). All three are identity-stage failures but mean different things:

Reason codeWhat actually happened
deny.identity_unverifiedthe token is missing, malformed, or fails cryptographic verification
deny.principal_untrusted_methodthe token verifies, but its method isn't allowlisted
deny.principal_mismatchthe token verifies and its method is trusted, but no rules[] entry references this principal at all

agent: in security.yaml must equal the identity the agent actually presents at runtime — either the --agent flag on raxit run, or RAXIT_AGENT_ID in the environment/SDK. This is the pairing that principal_mismatch exists to catch when it drifts.

On this page