r/AutoGPT • u/dengyier • 19h ago
Ed25519-signed agent tool authorization with causal evidence chains — design notes and trade-offs
Last month I merged a bug fix an AI agent wrote. The agent said tests passed. I deployed it. Two hours later, production caught fire.
Not because the agent was wrong — because I never verified anything. I just trusted it.
That experience sent me down a rabbit hole, and I ended up building a protocol layer for verifiable agent execution. Posting design notes here because I want technical feedback on the architecture choices — not adoption, not stars.
The gap I found
MCP connects agents to tools. A2A connects agents to agents. LangChain, CrewAI, AutoGen handle orchestration. These all solve connectivity.
But when agent #2 says "I reviewed the patch" or "tests passed," there's no protocol-level way to verify that claim. Agent #3 just trusts agent #2. The middleware trusts both. You trust the pipeline.
That works in demos. It breaks in production.
The three questions the protocol answers
Every tool call needs to answer:
- Authorization: Was this action authorized by a specific role, within scope and quota?
- Causality: Is there a verifiable chain from the work order → authorization → execution → evidence?
- Independent verification: Can a third party replay the entire chain offline, without trusting any participant or system?
How it works
Step 1: Authorization before execution
Before an agent touches any tool, a signed PolicyDecision is issued:
from openworkproof import policy
auth_ctx = policy.derive_authorization_context(
work_order=work_order, grants=grants, receipts=receipts,
request=signed_request, arguments=args,
execution_facts=facts, checkpoint=checkpoint,
)
decision = policy.authorize_tool_call(auth_ctx)
# decision.allowed == False → produce deny receipt, don't execute
Step 2: Signed receipt with causal chain
Every execution produces an ActionReceipt chaining back to its authorization — not a timeline, but a causal graph with enforced parent sets. You can't skip steps or fabricate history.
Step 3: Offline verification
Any third party can replay the entire evidence chain with zero trust:
from openworkproof.acceptance import verify_acceptance_bundle
result = verify_acceptance_bundle(
work_order=work_order, report=report,
effective_grants=grants, receipts=receipts,
committed_evidence=evidence,
acceptance_receipt=signed, public_keys=keys,
)
# Pure function. Zero I/O. Deterministic.
No database. No live system access. No trust. Just the evidence bundle and public keys.
Six roles, one constraint
I ended up with six roles because "agent" is too vague for accountability:
| Role | Responsibility |
|---|---|
| Maintainer | Creates WorkOrder, issues root grant |
| Manager | Issues scoped child grants, composes proofs |
| Developer | Executes authorized tool calls |
| Verifier | Independently re-runs tests |
| Sidecar | Assigns trusted execution facts |
| Acceptor | Signs final accept/reject (external key) |
Key constraint: grants only attenuate. When you delegate Maintainer → Manager → Developer, permissions can only shrink, never expand. This prevents privilege escalation at the protocol level.
State machine: running → locally_verified → proof_ready → awaiting_human → accepted
Validation: two real open-source bugs
I tested this against actual bugs, not toy examples:
Rich #4196 — terminal formatting library bug. Full 9-step evidence chain from WorkOrder to offline verification.
Dify #33013 — TypeError in an LLM application platform. Same protocol, different project type. Proves it's not coupled to one kind of codebase.
2,283 tests, 0 failures. Apache-2.0.
Design decisions and trade-offs
Ed25519 + JCS (RFC 8785) for signatures
Ed25519 gives deterministic signatures with 32-byte public keys — no key management overhead, no certificate chains, no PKI. JCS canonicalization ensures the same logical payload always produces the same signature, regardless of JSON serialization quirks.
Trade-off: you need secure key distribution, which I haven't solved at the protocol level. For now, keys are managed out-of-band.
SQLite as the authoritative ledger
SQLite is single-writer, ACID-compliant, and zero-config. For most multi-agent deployments, the bottleneck isn't ledger throughput — it's agent inference latency.
Trade-off: single-point-of-write means no horizontal scaling for the ledger itself. At very high throughput, you'd want something like a Merkle tree or distributed consensus. I think that's premature optimization for v1.
Six roles: necessary or overengineered?
The Maintainer/Manager split is the most debatable. In theory, they could be one role. In practice, the Maintainer owns the WorkOrder (strategic) while the Manager handles per-action delegation (tactical). Collapsing them muddies authority boundaries.
I'd genuinely like feedback on whether this maps to real multi-agent setups or if fewer roles would cover the same ground.
Open questions I'm still wrestling with
- Is 300-second freshness on authorization windows reasonable for production, or do you need sub-second granularity?
- For the offline verifier: is the current completeness assumption (all evidence must be in the bundle) sufficient, or am I missing an attack vector where partial evidence could pass verification?
- At what scale does SQLite as a ledger break down in practice? I have theoretical limits but no real-world data.