ABOM is the Agent Bill of Materials: every agent action becomes a signed, tamper-evident record an auditor can verify without trusting you — what the agent is, what it did, and proof nobody edited the story afterwards. Blocking is one flag away; the evidence is the product. Cryptographic, not reputational.
No one can say, in one signed document, which models, tools, prompts, data and policies an agent is built from — or prove the deployed agent matches what was approved.
When an agent makes a consequential decision, the evidence is scattered logs you must trust — not a tamper-evident record you can verify and hand to a regulator.
A prompt-injected agent that calls a tool it was never authorized to use is, in most stacks, only logged after the fact — not blocked before it runs.
Point your agent's MCP client at the ABOM broker instead of its MCP server. Every tools/call is authorized before it runs, and comes back ALLOW/DENY plus a signed, notarized receipt. You don't wrap tools or write integration code — the agent doesn't even know the API is there.
# point the agent's MCP client at the broker — # it authorizes every tools/call against your API $ abom broker abom.json \ --authorize-url https://api.abom.ai/authorize \ --api-key abom_… # a prompt-injected tool call the agent was never # granted comes back: { "verdict": "deny", "rule": "tool_not_in_manifest", "receipt": { "inclusion_proof": {…}, # notarized "head_signature": {…} } # signed } # the upstream never saw it. and you can prove it.
For a non-technical reader: think of a nutrition label (what's inside), a permission slip (what it's allowed to do), and a flight recorder (what it actually did) — for AI agents, all signed so they can't be faked.
A signed inventory of every model (with weight hashes), tool, prompt, data source, framework and policy. Generated by abom scan.
Deny-by-default enforcement against the signed manifest, before the action executes. A guardrail, not a log.
A hash-chained, Merkle-notarized record of every decision, with proofs anyone can verify — without trusting the operator.
A SIEM tells you an agent wired money to an attacker yesterday. ABOM's gate stops the call before it executes because the tool isn't in the agent's signed manifest. This is the difference between a guardrail and an audit trail.
# pin the signer: a re-signed manifest is refused from abom import Gate, Action, ActionDenied gate = Gate(signed_manifest, trusted_keys={"9a72f7ef…"}) # pinned # forged manifest, attacker's key → refused @gate.gated() # wrap any tool def wire_transfer(amount, to): ... # never runs if # undeclared # a prompt injection makes the agent try this: try: wire_transfer(1_000_000, to="attacker") except ActionDenied as e: e.decision.rule # → "tool_not_in_manifest" # the money never moved. denial notarized.
A decorator trusts the agent to route calls through it. A prompt-injected agent can just… not. The broker relocates the gate to a choke point the agent doesn't control: it sits between the agent and its MCP server, and every tools/call transits the gate before it's forwarded. Deny-by-default becomes structural, not cooperative.
# the agent gets its tools FROM the broker $ abom broker abom.json \ --upstream https://mcp.internal/rpc \ --trusted-key 9a72f7ef… --log gate.mlog # agent (prompt-injected) tries a tool it # was never granted: tools/call wire_transfer # → DENIED (-32001) # the upstream server never saw the call. tools/call lookup_customer # → forwarded
A plain hash chain proves internal consistency, but an operator who controls the store can rebuild it from scratch. ABOM uses an append-only Merkle transparency log (the same RFC 6962 construction behind Certificate Transparency) — inclusion and consistency proofs anyone can check. Paired with the witness and anchor below, the record becomes verifiable without trusting whoever produced it.
# anyone verifies — no trust in the operator decision = gate.check(action) # it IS in the signed log: verify_inclusion(entry, proof) # → True # signed tree head (KMS key): verify_payload(head, head_sig) # → True # attacker tries to backdate the record: verify_inclusion(forged, proof) # → False # the proof no longer matches.
A Merkle log is tamper-evident to outsiders — but the operator holds the store and the key, so on its own it can still be rebuilt from scratch. Two independent things close that gap and make the record something a third party can actually rely on.
The lineage. This is the same construction as Certificate Transparency and Sigstore. ABOM's Merkle log is Rekor-shaped; the witness is the independent cosigner role Sigstore is now baking into Rekor. Run it yourself for defense-in-depth today; the neutral, multi-party witness network is the natural next step.
# a second party cosigns — with a different key witness.cosign(head, consistency=proof) # operator rewrites history, asks again: witness.cosign(forged_head, consistency=bad) # → WitnessRejected: not append-only # anchor the root to an RFC 3161 authority anchor_head(head, tsa_url="https://tsa…") # → signed proof it existed by time T ✓
Every manifest, gate decision, model call and approval lands in the Notary as a queryable record. Ask it questions the way an auditor or a risk team actually would — by agent, by time window, by data classification — and get an answer you can verify, not just read.
Every event an agent emitted last quarter, last week, or between any two dates.
Prompt and completion tokens, model spend, and per-agent totals — rolled up for any window.
Every ALLOW/DENY, the rule that fired, top blocked tools, and gate latency.
Which actions touched confidential data, what egressed, and who approved what.
# every event for an agent, last quarter abom registry events \ --agent loan-doc-agent \ --from 2026-04-01 --to 2026-06-30 # token + cost rollup, same window abom registry usage \ --agent loan-doc-agent --period Q2 # or over HTTP — filter by decision GET /v1/registry/events ?agent=loan-doc-agent &from=2026-04-01&to=2026-06-30 &verdict=deny &classification=confidential
This is what makes the registry more than a dashboard: a query result over any time window comes with a cryptographic proof, so a regulator can trust the answer without trusting us. Cross-agent, time-windowed registry queries are in construction.
Three steps, all inside your own infrastructure — air-gap capable. Nothing leaves without explicit, logged policy.
Detect every component an agent is built from and emit a signed Composition Manifest — fingerprinted by composition_sha256.
Route tool calls through the gateway: every call becomes a signed record before execution — would_deny as evidence by default, hard ALLOW/DENY with --enforce.
Append every decision to a Merkle transparency log with a signed tree head — independently verifiable proof of what happened.
Every plane of the system, live below — click any node for what it does and why it's there; watch the evidence flow 1 → 5 from the build pipeline through the gateway and local chain to the verifiers outside the operator's control.
Both extend CycloneDX ML-BOM and are linked by hash, so a swapped model or tool at runtime is detectable as drift.
A signed inventory: models (with weight hashes), tools (with egress allowlists), prompts (hashed), data sources (classified), policies, frameworks and MCP servers — plus declared controls (egress, HITL, residency) and an EU AI Act risk class. Identified by composition_sha256 and ed25519-signed.
One hash-chained record per action — and in v0.2, every record is individually ed25519-signed: the decision (allow / deny / would_deny), policy and floor hashes, guardrail verdicts (detectors[]), salted-HMAC argument commitments instead of payloads, and a linked outcome record per forwarded call. Any edit, insertion, deletion or reorder breaks the chain at a known point; even degradations and refused policies enter the chain as signed events.
ABOM borrows the component model of the dominant, ECMA-standardized SBOM format rather than competing with it. CycloneDX answers "what is it made of." ABOM extends the idea into the agent runtime, adding the enforcement and provenance layer CycloneDX doesn't model.
ABOM's component model is aligned with CycloneDX naming today; native CycloneDX import/export is on the roadmap. ABOM does not claim CycloneDX conformance.
ABOM is draft v0.1, pre-1.0. Honesty about maturity is a feature for a trust project — here's exactly what ships today.
| Capability | Status |
|---|---|
| abom scan → signed Composition Manifest | Built |
| Hash-chained Action Provenance + verification | Built |
| ed25519 signing | Built |
| Inline gate — deny-by-default enforcement | Built |
| Merkle transparency log — inclusion + consistency proofs | Built |
| Decidable policy checks (abom verify) | Built |
| KMS/HSM-backed signing (provider wiring) | In construction |
| OPA/Rego policy engine · hardened Notary registry · SDK hooks | In construction |
| Native CycloneDX / SIEM export · eBPF egress · air-gap bundle | Planned |
In 2025–26 agents began taking consequential, real-world actions faster than anyone built the controls to bound them.
SBOM went from optional to mandated in ~3 years. Agent accountability is on the same arc — and the muscle memory exists.
CycloneDX shipped ML-BOM. ABOM is the natural extension to full agents + runtime provenance — extend the winner, don't fork.
EU AI Act Art. 12 & DORA point at accountability for AI. Deferred to ~2027 — so ABOM sells present-tense control now, with the mandate as upside.
Inspired by CycloneDX, open. Define the format, become infrastructure.
Tamper-evident, regulator-grade. Cryptographic, not reputational.
Any model, any framework — we sell neither. Only an independent can be the bill-of-materials layer.
Runs inside your boundary; nothing leaves. Air-gap capable, sovereign by default.
What is it made of, what is it allowed to do, and what did it do? — answered in a signed, standard, portable artifact you can hand to an auditor.