abom-cli
The reference implementation of ABOM — the Agent Bill of Materials.
Every agent action becomes a signed, hash-chained record a third party can
verify without trusting you: scan a repo into a signed Composition Manifest,
run MCP traffic through the gateway for per-call attestation, settle disputes
from commitments — and opt into inline blocking (--enforce) when evidence
alone isn't enough.
pip install abom-cli # (until published: pip install -e .)
abom scan . # → abom.json (signed with ed25519)
abom verify abom.json # check signature
abom verify abom.json --policy policy.json # + enforce a policy (exit 1 on violations)
abom gate abom.json --tool wire_transfer # ALLOW/DENY one action (deny-by-default)
abom broker abom.json --upstream https://mcp.internal/rpc # mediate an agent's tool calls
abom gateway run policy.json --upstream https://mcp.internal/rpc # policy + signed provenance per call
Commands
| Command | What it does |
|---|---|
abom scan [PATH] |
Detect agent components (models, prompts, tools, MCP servers, frameworks, vector stores, guardrails) and emit a signed Composition Manifest. -o - writes to stdout. |
abom verify [FILE] |
Verify the ed25519 signature; with --policy, enforce model allowlist / residency / egress / approval rules. Non-zero exit on findings (CI-friendly). --trusted-key pins the authorized signer. |
abom gate FILE --tool T |
Decide ALLOW/DENY for one action against the signed manifest, deny-by-default, notarized. --trusted-key refuses a manifest it can't authenticate. Exit 1 = DENY. |
abom broker FILE --upstream URL |
Run the MCP broker: mediate every tools/call against the signed manifest before forwarding to an upstream MCP server. Denied calls return a notarized JSON-RPC error and never reach upstream. --log for a durable decision log. |
abom gateway run POLICY --upstream URL |
Run the MCP gateway (ABOM v0.2): one signed, hash-chained Action Provenance Record per tools/call — written and fsync'd before forwarding, fail-closed. Default is inspect-only (violations recorded as would_deny, forwarded); --enforce blocks. --floor layers an org minimum no template can weaken; --manifest binds records to a composition. |
abom gateway verify LOG... |
The auditor's check: recompute the hash chain, every ed25519 signature, and — across rotated files — the epoch continuity links. --trusted-key pins the signer. Exit 1 at the exact file and seq. |
abom witness LOG.mlog |
Cosign a durable transparency log with an independent witness key; refuses a rewrite across runs. Run on a second party's machine for genuine non-equivocation. |
abom anchor LOG.mlog |
RFC 3161-timestamp the log root via a TSA (--tsa, default freetsa.org) — a third-party existence proof (eIDAS Art. 41 with a qualified TSA). |
abom witness-verify COSIG.json |
The auditor's check: verify a witness cosignature with no trust in the operator. |
abom keygen |
Show (or create) the local ed25519 signing key (~/.abom/signing_key.pem, override with ABOM_KEY). |
abom version |
Print the tool and spec versions. |
All commands accept -v (info) / -vv (debug) / -q (errors only) / --json-logs (NDJSON for CI) — logs go to stderr, so the ABOM on stdout stays clean.
Example
$ abom scan .
ABOM · my-agent @ 1.2.0
models 3 gpt-4o-mini, claude-3-5-sonnet, OpenAI (SDK)
frameworks 2 LangChain, LangGraph
MCP servers 2 filesystem, github
tools 1 lookup_customer
prompts 1 prompts/system.txt
signed: ed25519 · key 5846eabc738b3542
→ wrote abom.json
How detection works
abom scan is a static scanner (pure stdlib + cryptography):
- Dependencies (
requirements*.txt,pyproject.toml,package.json) → frameworks, model SDKs, vector stores, guardrails. - Source → concrete model names (
gpt-4o,claude-*, …) and@tool-decorated functions. - Prompt files (
*.prompt,prompts/*.txt|md) → hashed. - MCP configs (
mcp.json,claude_desktop_config.json, …) → MCP servers.
Each component records detected_from so the manifest is auditable. The output
validates against spec/abom-0.1.schema.json (shipped in the sdist).
Signing
abom scan signs with ed25519 (cryptography). The key lives at
~/.abom/signing_key.pem (override with ABOM_KEY); the public key + a short
key_id are embedded so abom verify is self-contained. Pin the trusted signer
with --trusted-key <key_id> on verify / gate / broker: a manifest
re-signed by any other key is then refused, so "signed" authenticates who — not
just integrity. LocalSigner is dev/CI; a KMSSigner seam keeps the private key
in a KMS/HSM for production.
Dev
make install # pip install -e ".[dev]"
make test # pytest (audit chain, scanner, signing)
make scan && make verify
make build # wheel + sdist + twine check
python demo/demo.py # generate → verify → tamper-evidence walkthrough
The MCP broker
abom broker moves enforcement out of the agent's process. The agent points
its MCP client at the broker instead of the MCP server; the broker checks every
tools/call against the signed manifest and only forwards allowed ones. A denied
call is answered with a notarized JSON-RPC error and never reaches the upstream
server — deny-by-default becomes structural for brokered tools rather than
cooperative. It does not stop out-of-band calls (raw HTTP / subprocess) the
agent makes without transiting the broker; pair it with network egress
containment for that.
The optional [mcp] extra (pip install 'abom-cli[mcp]') pulls in httpx for
the broker's upstream transport and for abom scan --mcp.
The MCP gateway (ABOM v0.2)
abom gateway is the broker's v0.2 evolution (spec draft; the full draft and
ADRs 0001–0008 ship in the sdist under spec/ and docs/adr/).
Same choke-point position — agent ⇄ gateway ⇄ upstream MCP server — but the
product is the evidence: every tools/call (allowed, denied, and
would-deny) becomes a signed, hash-chained Action Provenance Record, fsync'd
to an append-only log before the call is forwarded. A call the log cannot
record is never forwarded, so a forwarded-but-unrecorded call cannot exist.
Arguments enter the log as salted-HMAC commitments plus a de-identified
shape — never content — and verify_argument_claim settles disputes about
what a call contained. Log files open with a signed epoch, link across
rotations, and refuse a second writer; degradations are recorded as signed
events, not gaps.
The default mode is inspect-only — the signed would_deny log is the
deliverable. --enforce turns the same policy into inline blocking; --floor
layers an org-scoped minimum that no project template can weaken (a
contradicting template is refused with a signed conformance-violation record).
abom gateway run examples/policies/gateway-baseline.json -u https://mcp.internal/rpc \
--floor examples/policies/org-floor.json # inspect-only by default
abom gateway verify gateway.apr.jsonl # chain + signatures (+ rotation links)
python demo/gateway_demo.py # live end-to-end demo (make gateway-demo)
Already running Google's Model Armor? Keep it — and make it auditable:
--model-armor-template projects/<p>/locations/<l>/templates/<t> screens each
call via the sanitize API and seals the verdicts into every signed record's
detectors[] (token via ABOM_MODEL_ARMOR_TOKEN). The screen never gates —
policy decides; the screen's word becomes third-party-verifiable evidence.
They decide, you prove.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file abom_cli-0.2.0.tar.gz.
File metadata
- Download URL: abom_cli-0.2.0.tar.gz
- Upload date:
- Size: 155.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e25b01b5c9e360fb50300db133d6f3fafd33e47743a4c8dcbacbe865449dcf17
|
|
| MD5 |
d34cb0401ff82e15d2823d23910cd9df
|
|
| BLAKE2b-256 |
95896c46f172b8c533b1ceea1ae6147456c96cf7b5fd162506c8561d15277e6b
|
Provenance
The following attestation bundles were made for abom_cli-0.2.0.tar.gz:
Publisher:
release.yml on josephassiga/abom-dev
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
abom_cli-0.2.0.tar.gz -
Subject digest:
e25b01b5c9e360fb50300db133d6f3fafd33e47743a4c8dcbacbe865449dcf17 - Sigstore transparency entry: 2218548125
- Sigstore integration time:
-
Permalink:
josephassiga/abom-dev@8e83359adc4978e6960617709db9c63ca6ea4b6c -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/josephassiga
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8e83359adc4978e6960617709db9c63ca6ea4b6c -
Trigger Event:
push
-
Statement type:
File details
Details for the file abom_cli-0.2.0-py3-none-any.whl.
File metadata
- Download URL: abom_cli-0.2.0-py3-none-any.whl
- Upload date:
- Size: 85.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1e448c87d5788597ae85ed4256ac721be0060abc66591c95b67bb72f89bdb50
|
|
| MD5 |
d42792f4c181c5e667230e2be6ab40ec
|
|
| BLAKE2b-256 |
40815ea45b26c7db2ed1e66f33c91d0aeea8e0700650b2f9651397ca74ebabd1
|
Provenance
The following attestation bundles were made for abom_cli-0.2.0-py3-none-any.whl:
Publisher:
release.yml on josephassiga/abom-dev
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
abom_cli-0.2.0-py3-none-any.whl -
Subject digest:
c1e448c87d5788597ae85ed4256ac721be0060abc66591c95b67bb72f89bdb50 - Sigstore transparency entry: 2218548158
- Sigstore integration time:
-
Permalink:
josephassiga/abom-dev@8e83359adc4978e6960617709db9c63ca6ea4b6c -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/josephassiga
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8e83359adc4978e6960617709db9c63ca6ea4b6c -
Trigger Event:
push
-
Statement type: