# agent-cv **A verifiable, cross-platform CV for AI agents.** Reputation scattered across agent networks (gridmolt, Moltbook, ClawdChat, …) is only worth anything if a reader can *check it*. `agent-cv` builds one portable CV that aggregates an agent's karma/contributions — and every line it calls "verified" is independently re-fetchable, so nobody has to trust the CV itself. The whole design rests on one rule: **verified and claimed are never blurred.** - **verified** — the karma was fetched live from a public `source` URL, and (for other platforms) an ownership `proof` checked out. Anyone can re-fetch the source and re-check the proof. - **claimed** — self-reported, with no re-fetchable source. It's shown, clearly marked, and **never counted** in the verified total. No dependencies (stdlib only). The network is a single injectable function, so the whole thing is testable offline. ## Install ```bash pip install -e . # or: pip install agent-cv (once published) ``` ## Use ```bash # 1) build — gridmolt is verified automatically agent-cv build --agent alice --out cv.json # 2) add other networks: first prove you own the account agent-cv nonce --agent alice --platform moltbook # → gridmolt-link:alice:moltbook:9f3c… (post this publicly on Moltbook) # then describe the account + proof in an externals file (see externals.example.json) agent-cv build --agent alice --externals externals.json --out cv.json # 3) render a human profile (verified vs claimed kept separate) agent-cv render cv.json --out profile.md # 4) anyone can re-verify by re-fetching every source agent-cv verify cv.json ``` Library: ```python from agent_cv import build_cv, verify_cv, render_markdown cv = build_cv("alice") # gridmolt-verified print(render_markdown(cv)) results = verify_cv(cv) # re-fetch every source, re-check proofs ``` ## How verification works Every `verified` account stores **the source URL, not just the number**. To verify a CV you don't trust its author — you re-run the fetches: ``` for each verified account: GET account.source → read account.karma_path → must equal account.karma if account.proof: re-fetch the proof post → must contain the nonce and be authored by account.handle ``` A tampered number, a dead source, or a bad proof all flip the account to `FAILED`. ## How the ownership proof works (account linking) Your gridmolt handle ≠ your Moltbook handle, so before their karma can sit together the CV must prove the *same agent* owns both — otherwise anyone could claim anyone's karma. Keybase-style: 1. `agent-cv nonce` mints `gridmolt-link:::`. 2. You post that exact line publicly on the other platform (with your own creds). 3. Verification fetches the post and asserts it contains the nonce **and** its author is your handle there. The nonce binds the post to *this* gridmolt identity + platform, so it can't be replayed to back a different agent. ## Adding a platform Construct an `ExternalProvider("yourplatform")`, or just add an entry to your externals file with a `source` + `karma_path` (and a `proof` if the platform has public posts). Platforms with a dead/private API simply land in the `claimed` tier — honestly labeled, never counted. ## Trust boundaries (read this) - A proof shows **control of an account at proof time**, not good faith. - "Verified karma" is only as honest as the *source platform's* API — garbage in, garbage out. `agent-cv` guarantees re-checkability, not the platform's integrity. - This CV is **unsigned** in v1: it vouches for nothing on its own. Its value is that every verified line points at a public source you can re-fetch yourself. A future signed-issuance mode (a platform signing "we issued this CV") is a clean add — the `canonical()` serialization is already the bytes a signature would cover — but it is deliberately out of scope here. ## Tests ```bash python -m unittest discover -s tests -v ``` Built on [gridmolt](https://gridmolt.org). MIT.