12 KiB
ACT (Agent Compact Token) — Medium Blog Post Series
Series Title: "Securing the Agentic Web"
Target audience: Backend/platform engineers, AI practitioners, security-minded architects building multi-agent systems.
Post 1: "Why OAuth Isn't Enough for AI Agents"
Hook: OAuth was built for humans clicking "Allow." Autonomous agents don't click buttons — they chain tasks, delegate to sub-agents, and need cryptographic proof of what they did, not just what they were allowed to do.
Key points:
- OAuth assumes a human in the loop (consent screens, redirect flows)
- Agents need machine-to-machine auth that works without an Authorization Server
- The missing piece: accountability — OAuth proves authorization, but not execution
- Agents operate across organizational boundaries; federated trust is essential
- Existing alternatives and their gaps:
- SPIFFE/SPIRE: Workload identity, but no capability scoping or execution records
- ZCAP-LD: Capability delegation, but JSON-LD complexity and no execution phase
- Macaroons: Contextual caveats, but no standardized structure for agent workflows
- OPA/Cedar: Policy engines, but no portable token format
Diagram idea: Side-by-side comparison — OAuth flow vs. ACT flow for an agent task
Call to action: Introduce ACT as "authorization + accountability in a single token"
Post 2: "One Token, Two Lives — The ACT Lifecycle"
Hook: What if your authorization token could grow up — transforming from a permission slip into a receipt?
Key points:
- Phase 1 — Authorization Mandate: Signed by the issuing agent
- "Agent A authorizes Agent B to do X, with these constraints, until time T"
- JOSE header:
typ: "act+jwt",alg: "EdDSA",kid - Claims:
iss,sub,aud,exp,jti(UUID v4),task,cap - The
taskobject: purpose, data sensitivity, created_by - The
caparray: fine-grained actions with constraints
- Phase 2 — Execution Record: Re-signed by the executing agent
- Same token, new claims added:
exec_act,par,exec_ts,status - Critical: header
kidswitches from issuer's key to executor's key - Optional:
inp_hashandout_hash(SHA-256 of actual I/O data) - The
errobject for failure cases
- Same token, new claims added:
Code example: Show a Phase 1 JWT payload, then the same payload with Phase 2 claims added
Why it matters: One token = complete audit trail. No separate logging system needed. The token is the evidence.
Analogy: A signed work order (Phase 1) that becomes a signed completion certificate (Phase 2)
Post 3: "Zero to PKI — ACT's Trust Tier Progression"
Hook: Most security specs start with "first, set up your PKI infrastructure." ACT starts with "first, share a key over Signal."
Key points:
- Tier 1 — Pre-Shared Keys (mandatory to implement)
- Ed25519 key pairs shared out-of-band
kidis just an opaque string both parties agree on- Zero infrastructure. Works on day one. Perfect for prototyping and internal agents
- Key registry: simple dict mapping
kid → public_key_bytes
- Tier 2 — PKI / X.509
kid= SHA-256 thumbprint of DER-encoded certificatex5cJOSE header carries the certificate chain- Standard X.509 chain validation against trusted CA store
- For enterprises with existing PKI
- Tier 3 — Decentralized Identifiers (DIDs)
did:key— self-contained, no resolution needed (Ed25519 public key in the DID itself)did:web— HTTP-resolvable, cacheable with TTL- For cross-organizational federation without shared CA
Diagram idea: Three-rung ladder — each tier adds infrastructure but also adds trust guarantees
Why it matters: You can start using ACT in 10 minutes with pre-shared keys, then upgrade to PKI or DIDs as your deployment matures. No rip-and-replace.
Post 4: "Delegation Without Escalation — How ACT Prevents Rogue Sub-Agents"
Hook: When Agent A delegates to Agent B who delegates to Agent C... how do you ensure C can't do more than A originally allowed?
Key points:
- The
delclaim:{ depth, max_depth, chain[] }chainis ordered root → immediate parent- Each entry:
{ delegator, jti, sig }
- Capability attenuation: child's
capMUST be a subset of parent'scap- Constraints can only get MORE restrictive, never less
- Example: parent allows
data.readwithmax_rows: 1000→ child can setmax_rows: 100but notmax_rows: 5000
- Chain verification:
sig = Sign(delegator.private_key, SHA-256(parent_act_compact_bytes))- Each chain entry verified against delegator's public key
- Rejection conditions (5 ways delegation fails):
depth > max_depthchain.length != depth- Any chain signature fails
capcontains actions not in parent'scap- Any constraint is less restrictive than parent's
Code example: Three-agent delegation chain with progressively narrower capabilities
Analogy: Power of attorney — you can give someone authority to act on your behalf, and they can sub-delegate, but each level can only narrow the scope, never widen it
Post 5: "Following the Thread — DAG-Based Execution Tracking"
Hook: In a world where agents spawn agents that spawn agents, how do you answer "what happened and in what order?"
Key points:
- Every Phase 2 ACT has a
par(parents) array — JTIs of predecessor tasks[]for root tasks (no parents)- Multiple parents = fan-in (joining parallel branches)
- The
jtiitself serves as the task ID
- DAG validation rules:
jtiuniqueness withinwid(workflow) scope- Every parent
jtimust exist as a verified Phase 2 ACT in the ledger - Temporal ordering:
parent.exec_ts < child.exec_ts + 30s(clock skew tolerance) - Acyclicity: max 10,000-node traversal limit
exec_actmust match one of thecap[].actionvalues
- Workflow grouping: Optional
wid(workflow ID) groups related ACTs
Diagram idea: A DAG of 6-8 tasks showing fan-out (parallel dispatch) and fan-in (result aggregation)
Real-world example: ML pipeline — data fetch → preprocess (fan-out to 3 shards) → train (fan-in) → evaluate → deploy
Why it matters: Compliance, debugging, incident response. "Show me every action taken in workflow X, in causal order, with cryptographic proof."
Post 6: "Humans in the Loop — ACT's Oversight Mechanism"
Hook: Full autonomy is terrifying. Full control is impractical. ACT's oversight mechanism is the middle ground.
Key points:
- The
oversightclaim:requires_approval_for: array of action strings that need human sign-offapproval_ref: reference to the approval record
- How it works in practice:
- Agent receives mandate with
oversight.requires_approval_for: ["data.delete"] - Before executing
data.delete, agent must obtain approval - Approval reference stored in
oversight.approval_ref
- Agent receives mandate with
- Selective oversight: Only specific high-risk actions require approval, not everything
- Composable with delegation: oversight requirements propagate down the chain
Why it matters: Regulatory compliance (GDPR right-to-delete, financial transactions), enterprise risk management, building trust in agent systems incrementally
Post 7: "Threat Model Deep Dive — What ACT Defends Against"
Hook: Every security spec claims to be secure. Here's exactly what ACT protects against — and what it doesn't.
Key points:
- Defended threats:
- Token forgery (Ed25519 signatures, no symmetric algs, no "alg: none")
- Privilege escalation (capability attenuation in delegation chains)
- Replay attacks (jti uniqueness, exp enforcement, clock skew tolerance ≤300s)
- Execution fabrication (Phase 2 re-signature by sub's key, not iss's key)
- Audit trail tampering (hash-chained append-only ledger)
- Man-in-the-middle on delegation (chain signatures bind to parent token bytes)
- Security constraints in implementation:
- Algorithm allowlist: EdDSA (Ed25519), ES256 only. No HS*, no "none"
- Key material zeroed on deletion
- iat must not be unreasonably future (≤30s)
- aud verification mandatory
- Out of scope (honest about limitations):
- Token revocation (not in v00 — mentioned as future work)
- Confidentiality of token contents (JWS, not JWE)
- Compromised agent keys (standard key management applies)
Table: Threat → ACT mitigation → Residual risk
Post 8: "ACT Meets the IETF — Why Standardization Matters for Agent Interop"
Hook: Your agents and my agents need to talk. Without a standard, we're back to building custom integrations for every partner.
Key points:
- The IETF process: Internet-Draft → RFC pathway
draft-nennemann-act-00is the first submission- Building on existing standards: RFC 7519 (JWT), RFC 7515 (JWS), RFC 7518 (JWA)
- ABNF notation for action names, formal CDDL-style structures
- Why an IETF RFC vs. a blog post or GitHub repo:
- Interoperability testing with multiple implementations
- Formal security review
- Stable reference for contracts and regulations
- Media type registration:
application/act+jwt
- Interoperability requirements:
- MUST implement Tier 1 (pre-shared keys)
- MUST support EdDSA (Ed25519)
- MUST verify delegation chains
- MUST enforce DAG validation
- Comparison with other agent-related standards efforts
Why it matters: As AI agents become infrastructure, we need the same rigor we applied to HTTP, TLS, and OAuth
Post 9: "Building Your First ACT Agent — A Hands-On Tutorial"
Hook: Enough theory. Let's build two agents that authorize, execute, and audit a task using ACT.
Key points (step-by-step tutorial):
- Install the
actPython package - Generate Ed25519 key pairs for two agents
- Create a Phase 1 mandate (Agent A → Agent B: "read customer data")
- Agent B validates the mandate
- Agent B executes and creates Phase 2 record (with inp_hash/out_hash)
- Append to audit ledger
- Verify the complete chain
- Add delegation: Agent B delegates subset to Agent C
- Verify Agent C's execution in the DAG
Code examples: Complete working Python code for each step, using the reference implementation
Real-world scenario: E-commerce — order service authorizes inventory agent to check stock, inventory agent delegates to warehouse-specific sub-agents
Post 10: "The Road Ahead — ACT's Evolution and the Agentic Future"
Hook: ACT v00 is a foundation. Here's what's coming and how you can shape it.
Key points:
- Future work mentioned in the draft:
- Token revocation mechanisms
- Formal capability algebra (lattice-based constraint reasoning)
- Performance benchmarks across implementations
- Integration patterns with existing auth infrastructure
- Privacy-preserving execution records (selective disclosure)
- Community and contribution:
- Reference implementation as the interoperability baseline
- Test vectors (Appendix B) as the conformance suite
- How to write a second implementation (in Rust, Go, etc.)
- The bigger picture:
- Agent-to-agent economy needs trust primitives
- ACT as one layer in the agentic stack
- Composability with other standards (OpenID for agents, SCIM, etc.)
Cross-Series Themes
- Progressive complexity: Each post builds on the previous, but each can stand alone
- Code-first: Every concept illustrated with real Python snippets from the reference implementation
- Honest trade-offs: Acknowledge what ACT doesn't solve (yet)
- Standards matter: Thread the IETF standardization story throughout
- Real-world grounding: Each post connects to concrete use cases
Publication Strategy
- Cadence: 1 post per week, 10-week series
- Length: 1,500-2,500 words per post (8-12 min read)
- Tags: AI, Security, Authentication, Distributed Systems, IETF
- Series landing page: Link all posts, provide a "start here" guide
- Code repo: Link to the reference implementation throughout
- Post 9 can be published on dev.to / Hashnode in addition to Medium for developer reach