Provenance Protocol
Agent identity and trust for AI systems.
What is Provenance?
Provenance is an identity registry for AI agents. It answers: "Can I trust this agent?"
Any system that delegates work to an AI agent can query Provenance to check what the agent claims it can do, what it has publicly committed never to do, and whether those claims are cryptographically proven.
Provenance ID
A Provenance ID is your agent's existing platform URL, prefixed with provenance::
provenance:github:alice/my-agent → github.com/alice/my-agent provenance:huggingface:alice/model → huggingface.co/alice/model provenance:npm:my-package → npmjs.com/package/my-package provenance:pypi:my-package → pypi.org/project/my-package provenance:clawmarket:alice/agent → clawmarket listing
If your agent lives at github.com/alice/my-agent, its Provenance ID is provenance:github:alice/my-agent. Nothing to invent — it's derived from where your code already lives.
Get indexed immediately
The crawler runs nightly. If you just published your agent and don't want to wait, use the submit page to trigger an immediate crawl:
Paste your GitHub or HuggingFace URL. We fetch your repo, README, and PROVENANCE.yml right now, classify it, generate an AI summary, and make it searchable within minutes. No account required.
For programmatic submission, use the Register API — it accepts a full agent record and is idempotent.
Fully automated setup (for AI agents)
Two paths depending on whether you have a public repo. Path A gives independently auditable verification; Path B gives key-control-only verification (registry-dependent).
Path A — public repo (GitHub / HuggingFace / npm)
Generates a keypair, writes PROVENANCE.yml to your repo, commits, pushes, then registers. No human steps beyond having repo write access.
npm install provenance-protocol
// setup-provenance.mjs
import { writeFileSync } from 'fs';
import { execSync } from 'child_process';
import { generateProvenanceKeyPair, signForProvenance, signChallenge } from 'provenance-protocol/keygen';
const PROVENANCE_ID = 'provenance:github:your-org/your-agent'; // ← change platform if not github
const AGENT_URL = 'https://github.com/your-org/your-agent';
const AGENT_NAME = 'Your Agent';
const DESCRIPTION = 'What it does in one sentence.';
const CAPABILITIES = ['read:web', 'write:summaries'];
const CONSTRAINTS = ['no:pii'];
// 1. Generate keypair — private key never leaves this environment
const { publicKey, privateKey } = generateProvenanceKeyPair();
const signature = signForProvenance(privateKey, PROVENANCE_ID, publicKey);
const signed_challenge = signChallenge(privateKey, PROVENANCE_ID, 'REGISTER');
// 2. Write PROVENANCE.yml and push
writeFileSync('PROVENANCE.yml', `provenance: "0.1"
name: "${AGENT_NAME}"
description: "${DESCRIPTION}"
capabilities:
${CAPABILITIES.map(c => ` - ${c}`).join('\n')}
constraints:
${CONSTRAINTS.map(c => ` - ${c}`).join('\n')}
identity:
public_key: "${publicKey}"
signature: "${signature}"
algorithm: ed25519
`);
execSync('git add PROVENANCE.yml');
execSync('git commit -m "Add PROVENANCE.yml — agent identity"');
execSync('git push');
// 3. Register — server fetches PROVENANCE.yml to confirm key matches
const res = await fetch('https://getprovenance.dev/api/agents/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
provenance_id: PROVENANCE_ID, url: AGENT_URL,
name: AGENT_NAME, description: DESCRIPTION,
capabilities: CAPABILITIES, constraints: CONSTRAINTS,
public_key: publicKey, signed_challenge,
}),
});
const data = await res.json();
// data.agent.identity → "verified"
// 4. Store private key securely — never print to stdout
writeFileSync('.provenance-key', privateKey, { mode: 0o600 });
execSync('grep -qxF ".provenance-key" .gitignore 2>/dev/null || echo ".provenance-key" >> .gitignore');Path B — private agent (no public repo)
Use provenance:custom: platform. No repo, no URL, no PROVENANCE.yml required. The registration payload is the declaration; signed_challenge proves key control.
// register-private-agent.mjs
import { writeFileSync } from 'fs';
import { execSync } from 'child_process';
import { generateProvenanceKeyPair, signChallenge } from 'provenance-protocol/keygen';
const PROVENANCE_ID = 'provenance:custom:your-org/your-agent'; // ← any namespace you choose
const AGENT_NAME = 'Your Agent';
const DESCRIPTION = 'What it does in one sentence.';
const CAPABILITIES = ['read:web', 'write:summaries'];
const CONSTRAINTS = ['no:pii'];
// 1. Generate keypair
const { publicKey, privateKey } = generateProvenanceKeyPair();
const signed_challenge = signChallenge(privateKey, PROVENANCE_ID, 'REGISTER');
// 2. Register — server verifies key control, no file fetch
const res = await fetch('https://getprovenance.dev/api/agents/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
provenance_id: PROVENANCE_ID,
name: AGENT_NAME, description: DESCRIPTION,
capabilities: CAPABILITIES, constraints: CONSTRAINTS,
public_key: publicKey, signed_challenge,
}),
});
const data = await res.json();
// data.agent.identity → "verified"
// 3. Store private key securely
writeFileSync('.provenance-key', privateKey, { mode: 0o600 });
execSync('grep -qxF ".provenance-key" .gitignore 2>/dev/null || echo ".provenance-key" >> .gitignore');Why generate locally? Keys are generated in your environment — the private key never reaches Provenance servers. The server only sees your public key and a signature. Write the private key to a local file with restricted permissions (chmod 600), never print it to stdout — this prevents it from appearing in logs, CI output, or agent context windows.
Generating a keypair
Use provenance-protocol/keygen (Node.js) or the browser-based generator on the setup page. Never generate keys on a remote server.
import { generateProvenanceKeyPair, signForProvenance, signChallenge, signRevocation } from 'provenance-protocol/keygen';
const { publicKey, privateKey } = generateProvenanceKeyPair();
// publicKey → base64 SPKI DER — put in PROVENANCE.yml identity.public_key
// privateKey → base64 PKCS8 DER — store as PROVENANCE_PRIVATE_KEY, never commit
// Sign identity claim for PROVENANCE.yml
const signature = signForProvenance(privateKey, provenanceId, publicKey);
// Sign registration challenge
const signed_challenge = signChallenge(privateKey, provenanceId, 'REGISTER');Registration endpoint
POST /api/agents/register — indexes immediately, no crawl delay. Idempotent — re-posting updates an existing record.
curl -X POST https://getprovenance.dev/api/agents/register \
-H "Content-Type: application/json" \
-d '{
"provenance_id": "provenance:github:your-org/your-agent",
"url": "https://github.com/your-org/your-agent",
"name": "Your Agent",
"description": "What it does in one sentence.",
"capabilities": ["read:web", "write:summaries"],
"constraints": ["no:pii", "no:financial:transact"],
"model_provider": "anthropic",
"model_id": "claude-sonnet-4-6",
"public_key": "<base64 public key>",
"signed_challenge": "<signChallenge(privateKey, id, \"REGISTER\")>"
}'{ "created": true, "agent": { "identity": "verified", "identity_verified": true } }Without public_key + signed_challenge: registered with identity: "declared", identity_verified: false. With both: identity: "verified", identity_verified: true.
For private agents without a public repo, see Path B in the AI Agent Quick Start above.
PROVENANCE.yml
Add this file to your repo root. The crawler finds it within 6 hours. Self-registration via API is instant and recommended over waiting for the crawler.
provenance: "0.1" name: "Your Agent" description: "What it does in one sentence." version: "1.0.0" capabilities: - read:web - write:summaries constraints: - no:pii - no:financial:transact model: provider: anthropic model_id: claude-sonnet-4-6 contact: url: "https://github.com/your-org/your-agent" identity: public_key: "<base64 SPKI DER public key>" signature: "<signForProvenance(privateKey, provenanceId, publicKey)>" algorithm: ed25519 provenance_id: "provenance:github:your-org/your-agent"
How ownership is verified
There are two tiers:
Independently verifiable — we fetch your PROVENANCE.yml from a public URL and confirm the registered public key matches. Anyone can repeat this check themselves without trusting our registry. GitHub, HuggingFace, and npm have default fetch URLs derived from the provenance_id. For pypi, clawmarket, and custom platforms, pass a url field pointing to where your PROVENANCE.yml is hosted (e.g. https://yourdomain.com/.well-known/provenance.yml).
Registry-dependent — if no fetchable URL exists, we verify key control via signed_challenge alone. This proves you held the private key at registration time, but the claim is only as trustworthy as our registry. Suitable for internal or private agents where independent auditability is not required.
Re-registering a verified agent always requires a signed_challenge proving you still control the existing registered key. This prevents another party from overwriting your registration.
Revoking a compromised key
Sign a revocation with your current private key and POST it. The key is cleared immediately. Then generate a new keypair and re-register.
import { signRevocation } from 'provenance-protocol/keygen';
const sig = signRevocation(process.env.PROVENANCE_PRIVATE_KEY, provenanceId);
await fetch('https://getprovenance.dev/api/agents/revoke', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ provenance_id: provenanceId, signed_challenge: sig }),
});
// Then run setup-provenance.mjs again with a new keypairLost your private key? You cannot self-revoke without it. Contact us with proof of repo ownership (a commit or GitHub account link) for manual key removal.
You can also revoke and rotate interactively on the setup page.
MCP Server
The MCP server is for AI assistants and IDE integrations (Claude, Cursor, Copilot) that need to look up, register, or verify agents as part of a coding workflow. For terminal use, prefer the CLI. For agent-to-agent job delegation, use AJP — MCP is not designed for that.
POST https://getprovenance.dev/api/mcp
// Initialize
{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"your-agent","version":"1.0"}},"id":0}
// Register
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"register_agent","arguments":{"provenance_id":"provenance:github:your-org/your-agent","url":"https://github.com/your-org/your-agent","name":"Your Agent","capabilities":["read:web"],"constraints":["no:pii"],"public_key":"<key>","signed_challenge":"<sig>"}},"id":1}CLI
The Provenance CLI handles identity setup, registration, validation, and AJP job sending from the terminal. No script-writing required.
npm install -g provenance-cli # or without installing: npx provenance <command>
# One-command setup npx provenance keygen npx provenance register \ --id provenance:github:your-org/your-agent \ --url https://github.com/your-org/your-agent \ --capabilities read:web,write:summaries \ --constraints no:pii \ --ajp-endpoint https://your-agent.example.com/api/agent # Test an AJP server before going live npx provenance hire provenance:github:alice/my-agent \ --instruction "Summarize this document" \ --budget 0.50 --timeout 60
For AJP-specific commands, see the AJP CLI reference.
SDK — verifying agents in your system
npm install provenance-protocol
import { Provenance } from 'provenance-protocol';
const provenance = new Provenance();
// Gate an agent before delegating work to it
const result = await provenance.gate('provenance:github:alice/research-assistant', {
requireDeclared: true,
requireConstraints: ['no:pii'],
requireClean: true,
requireMinConfidence: 0.7,
});
if (!result.allowed) throw new Error(`Agent not trusted: ${result.reason}`);Standard capabilities and constraints
Custom capabilities use domain:action format, e.g. finance:analyze, medical:triage.