Everything below runs against the live gateway serving this page — or your own, one command away. Machine-readable version: /llms.txt. Wire format: CW1 specification.
Zero-install: this page's gateway doubles as a public playground. Mint a tightly-capped warrant ($50 demo scope, 1-hour expiry) and enforce against it right now:
curl -s -X POST https://liceat.com/demo/issue -H 'content-type: application/json' -d '{}'
# → { "token": "CW1~…", "jti": "…" } then use it on /call below
Or run your own:
# 1. run a gateway (dashboard + inspector + audit chain included)
npx liceat serve # http://localhost:3000
# 2. issue a warrant: $50 total, payments only, one hour
liceat issue --principal org:acme --agent agent:booker \
--resource 'pay:*' --action pay --spend USD:5000 --ttl 3600
# → { "token": "CW1~…", "attenuationKey": {…}, "jti": "…" }
# 3. make an enforced call
liceat call --token CW1~… --resource pay:stripe/charge --action pay \
--amount 2000 --currency USD
# 4. watch the cap enforce (cumulative: $20 spent + $40 > $50 → denied)
liceat call --token CW1~… --resource pay:stripe/charge --action pay \
--amount 4000 --currency USD
# → { "error": "denied", "reasons": ["spend limit exceeded: 2000+4000 > 5000 USD"] }
A warrant is a chain of signed blocks. Block 0 (the authority block) names the principal, the agent, and the issuer key; every block carries caveats — restrictions. Authorization is the AND of every caveat in every block, so appending a block (attenuation) can only narrow authority. Removing, reordering, or editing a block breaks the signature chain. Verification needs only the issuer's public key (published here) — it works offline, anywhere.
Amounts are integer minor units (cents). Timestamps are unix seconds.
Tokens look like CW1~… and are safe to pass through URLs, headers, and env vars.
| Endpoint | What it does |
|---|---|
| POST /issue | Mint a root warrant. Body {principal, agent, caveats[]} → {token, attenuationKey, jti}. Admin. |
| POST /attenuate | Narrow a warrant for a sub-agent. Body {token, attenuationKey, caveats[]} → new {token, attenuationKey}. |
| POST /verify | Dry-run a request against a warrant. No side effects. → {ok, reasons[]} |
| POST /call | Enforced + audited action. Header Authorization: Warrant <token>, body {resource, action, amount?, currency?, args?, pop?}. Forwards to the upstream on allow; 403 {error:"denied", reasons[]} on deny. |
| POST /authorize | Same enforcement + audit, no forwarding — for sidecars that execute the action themselves. → {allow, reasons[], jti} |
| POST /inspect | Decode + structurally verify a token → chain validity, meta, per-block caveats, revocation. |
| POST /revoke | {jti, reason?} — kills the warrant and every sub-delegation. Admin. |
| GET /audit | The hash-chained decision ledger + integrity proof. |
| GET /.well-known/liceat-jwks | Issuer public keys for offline verification. |
| GET /sentinel | Latest adversarial self-check report. |
| GET /stats · /health | Dashboard summary · liveness. |
Unknown caveat types fail closed. All caveats AND together across all blocks.
| Caveat | Semantics |
|---|---|
| {type:"resource", patterns:["mcp:github/*"]} | Request resource must glob-match at least one pattern (* matches any run of characters). |
| {type:"action", actions:["read","pay"]} | Request action must be in the list. |
| {type:"expires", at:1750003600} | Invalid after at (unix seconds). Pair with not_before for windows. |
| {type:"spend_limit", currency:"USD", max:5000} | Stateful. Cumulative allowed spend under this warrant id (all calls, all sub-delegations) + this request ≤ max. |
| {type:"rate_limit", max:10, per:60} | Stateful. At most max allowed calls per per seconds, sliding window. |
| {type:"pop", key:"<agent pubkey>"} | Holder-binding: presenter must sign a per-request challenge with the pinned key. See below. |
| {type:"assert", key:"env", value:"prod"} | Request facts must carry the exact value. |
npm install liceat # zero runtime dependencies
import { issue, attenuate, verifyWarrant, generateKeypair } from 'liceat';
const root = generateKeypair();
const { warrant, attenuationKey } = issue(root.sec, 'root-1', {
principal: 'org:acme', agent: 'agent:booker',
caveats: [
{ type: 'resource', patterns: ['pay:*'] },
{ type: 'action', actions: ['pay', 'read'] },
{ type: 'spend_limit', currency: 'USD', max: 5000 },
],
});
// delegate a strictly narrower warrant to a sub-agent — no server round-trip
const sub = attenuate(warrant, attenuationKey, [{ type: 'action', actions: ['read'] }]);
// verify anywhere, offline
const res = verifyWarrant(warrant,
{ resource: 'pay:stripe/charge', action: 'pay', amount: 2000, currency: 'USD' },
{ resolveRootKey: (kid) => root.pub });
pip install liceat # depends only on `cryptography`
from liceat import generate_keypair, issue, attenuate, verify_warrant
sec, pub = generate_keypair()
warrant, atk = issue(sec, "root-1", "org:acme", "agent:booker", [
{"type": "resource", "patterns": ["pay:*"]},
{"type": "action", "actions": ["pay"]},
{"type": "spend_limit", "currency": "USD", "max": 5000},
])
sub, _ = attenuate(warrant, atk, [{"type": "action", "actions": ["read"]}])
result = verify_warrant(warrant, {"resource": "pay:x", "action": "pay",
"amount": 100, "currency": "USD"},
resolve_root_key=lambda kid: pub)
Both SDKs verify the same frozen conformance vectors — a warrant issued in one language verifies identically in the other.
Wrap any MCP server — no modification, no cooperation from the server author. Every
tools/call is verified, caveat-checked, revocation-checked, and audited before it
reaches the tool. Denials return structured JSON-RPC errors. If the gateway is unreachable,
calls are denied (fail-closed).
liceat-mcp --gateway https://your-gateway --token CW1~… --label github \
-- npx -y @modelcontextprotocol/server-github
Tools are authorized as resources mcp:<label>/<tool> with action
call — so a warrant with patterns: ["mcp:github/get_*"] allows reads and
denies mutations, whatever the agent asks for.
Add {type:"pop", key: agentPubKey} at issue time (generate with
liceat keygen). The agent signs a challenge binding the timestamp and the exact
request; the gateway verifies it against the pinned key, enforces ±120s freshness, and rejects
replayed signatures. A stolen token without the agent's private key authorizes nothing.
challenge = "LICEAT-POP\n" + ts + "\n" + resource + "\n" + action + "\n" + amount + "\n" + currency
pop = { sig: ed25519_sign(agentKey, challenge), ts } // send as `pop` in /call
Every decision is appended to a hash-chained ledger:
h(i) = sha256(h(i−1) ‖ entry). Fetch it and re-verify the whole
history yourself — one altered byte breaks the chain at that exact index. Revocation is by the
root warrant id (jti) and cascades instantly to every sub-delegation. Received a
warrant from someone? Inspect it.
Fully self-serve, for humans and agents. Pricing: 10,000 free decisions on signup, then $0.0001 per authorization decision ($10 per 100k), metered per warrant you issue.
# 1. instant account — the API key is returned exactly once
curl -s -X POST https://liceat.com/signup -H 'content-type: application/json' \
-d '{"email":"[email protected]"}'
# → { "tenantId": "tn_…", "apiKey": "lk_…", "credits": 10000 }
# 2. issue production warrants with YOUR key (replaces the admin-gated /issue)
curl -s -X POST https://liceat.com/t/issue -H 'authorization: Bearer lk_…' \
-H 'content-type: application/json' \
-d '{"principal":"org:you","agent":"agent:worker","caveats":[{"type":"action","actions":["read"]}]}'
# 3. check balance and usage any time
curl -s https://liceat.com/t/me -H 'authorization: Bearer lk_…'
# 4a. top up with USDC on Base — send the EXACT quoted amount; settles automatically
curl -s -X POST https://liceat.com/billing/usdc/invoice -H 'authorization: Bearer lk_…' \
-H 'content-type: application/json' -d '{"credits":100000}'
# → { "payExactly": "10.003217", "payTo": "0x…", "network": "base", "status": "…" }
# 4b. or by card (Stripe checkout)
curl -s -X POST https://liceat.com/billing/checkout -H 'authorization: Bearer lk_…' \
-H 'content-type: application/json' -d '{"credits":100000}' # → { "url": "https://checkout.stripe.com/…" }
402 payment_required with an x402-style accepts array
(scheme exact, network base, the USDC contract, and the payTo address) plus
a portal link — everything a wallet-holding agent needs to restore its own authority budget without a
human in the loop. The unique invoice amount is the payment reference; no memo field required.
Prefer the human path? Everything above has buttons at the portal.Liceat is its own verifiable log. Every entry — authorization decisions, agent identities,
attestations — is a leaf in one append-only Merkle tree. The signed tree head
(GET /transparency/sth) is the root + size, Ed25519-signed by the key at
/.well-known/liceat-jwks. From it anyone proves, offline:
# prove a record is in the log
GET /transparency/inclusion?seq=42 → { leafData, proof[], treeSize }
# prove the log only ever grew (append-only) between two signed heads
GET /transparency/consistency?first=100&second=250 → { proof[] }
Verify with the SDK — you never trust our server, only our published key:
import { verifyInclusion, verifyConsistency, leafHash } from 'liceat';
verifyInclusion(seq, treeSize, leafHash(leafData), proof, rootHash); // → true
/audit), and each tenant can read only their own entries (/t/audit).This is the Certificate-Transparency / Sigstore model: tamper-evidence and non-repudiation without a blockchain, gas, or waiting. Try it in-browser at /transparency.
Beyond tamper-evidence, Liceat is non-equivocating: the operator cannot show two different
histories. Checkpoints (GET /transparency/checkpoint, C2SP signed-note format) are
co-signed by independent witnesses that only endorse an advance after verifying a consistency
proof — so no honest witness can sign a fork. Run your own witness and submit cosignatures:
import { Witness, checkpointBody } from 'liceat';
const w = new Witness('me/witness', sec, pub);
// fetch /transparency/checkpoint + a consistency proof from your last size, then:
const res = w.witness({ origin, size, rootHash }, consistencyProof); // cosignature | rejected
// POST /transparency/cosign { name, publicKey, signature }
Attestations are emitted as W3C Verifiable Credentials (JWT-VC, EdDSA) at
GET /attestations/vc?seq=N, and the issuer keys are published as a
did:web document at /.well-known/did.json — so AP2 / A2A agents and any
standards-compliant VC verifier ingest Liceat natively, with no Liceat-specific code. Each credential
carries its transparency-log coordinates so a verifier can also demand an inclusion proof.
Register agents and issue revocable attestations natively — the ERC-8004 / EAS surface, recorded on the Liceat log (gasless, instant). Each record is transparency-logged, so a relying party verifies it by checking the STH signature plus an inclusion proof.
# register an agent identity (resolvable card)
curl -X POST https://liceat.com/agents/register -H 'authorization: Bearer lk_…' \
-H 'content-type: application/json' -d '{"card":{"name":"Booker","url":"https://…"}}'
# → { "card": { "id": "ag_…" }, "seq": 128, "inclusion": "https://liceat.com/transparency/inclusion?seq=128" }
# attest reputation / validation about a subject agent
curl -X POST https://liceat.com/attest -H 'authorization: Bearer lk_…' \
-H 'content-type: application/json' \
-d '{"subject":"ag_…","schema":"liceat.reputation","data":{"score":5,"comment":"completed 1k tasks"}}'
# resolve an agent: card + live attestations + aggregate reputation
curl https://liceat.com/agents/ag_…
# revoke your attestation
curl -X POST https://liceat.com/attest/revoke -H 'authorization: Bearer lk_…' -d '{"attId":"att_…"}'
The hosted gateway at liceat.com is fully self-serve — no sales calls, no invoices by email. Get a key, issue warrants, and each authorization decision under your warrants costs $0.0001 (10,000 free to start).
# 1. sign up — returns your API key (shown once) + 10,000 free decisions
curl -s -X POST https://liceat.com/signup -H 'content-type: application/json' \
-d '{"email":"[email protected]"}'
# 2. issue warrants with your key (no admin token; metered to your account)
curl -s -X POST https://liceat.com/t/issue -H 'authorization: Bearer lk_…' \
-H 'content-type: application/json' \
-d '{"agent":"agent:worker","caveats":[{"type":"action","actions":["read"]}]}'
# 3. check balance
curl -s https://liceat.com/t/me -H 'authorization: Bearer lk_…'
Request an invoice for a credit pack; you get a unique exact USDC amount to send on Base. The amount itself is the invoice id, so no memo is needed — settlement is automatic within ~2 minutes of confirmation. No wallet connection, no signup with a card processor.
curl -s -X POST https://liceat.com/billing/usdc/invoice -H 'authorization: Bearer lk_…' \
-H 'content-type: application/json' -d '{"credits":100000}'
# → { "payExactly": "10.003217", "asset": "USDC", "network": "base",
# "payTo": "0x…", "status": "https://liceat.com/billing/invoice/inv_…" }
Liceat speaks x402 (v1, exact
scheme, USDC on Base). When a metered account is out of credits, POST /call returns a
spec-exact 402:
HTTP/1.1 402 Payment Required
{ "x402Version": 1, "error": "X-PAYMENT header is required",
"accepts": [{ "scheme": "exact", "network": "base",
"maxAmountRequired": "10000000", "asset": "0x833589fCD6…2913",
"payTo": "0x…", "maxTimeoutSeconds": 60,
"extra": { "name": "USD Coin", "version": "2" } }] }
Any off-the-shelf x402 client signs an EIP-3009 transferWithAuthorization and re-sends
the request with an X-PAYMENT header. Liceat verifies and settles it through an x402
facilitator, tops the account up, serves the call, and returns an X-PAYMENT-RESPONSE
header with the settlement tx — no waiting for a transaction, no gas for the buyer, zero custom
code. Enable inline settlement by pointing at a facilitator
(LICEAT_X402_FACILITATOR); without one, the async USDC invoice above still works.
LICEAT_ADMIN_TOKEN=<strong secret> # required in production: gates /issue, /revoke, /rotate
LICEAT_DATA_DIR=/var/lib/liceat # durable keystore, ledger, revocations
PORT=3000
npx liceat serve
LICEAT_RATE_MAX / LICEAT_RATE_WINDOW_MS (per-IP rate limits),
PUBLIC_URL (canonical URL in denial messages and billing links),
LICEAT_BILLING=0 (disable self-serve accounts entirely),
LICEAT_USDC_ADDRESS (receive USDC at a wallet you control instead of the
auto-generated one), LICEAT_BASE_RPC (Base JSON-RPC endpoint),
LICEAT_X402_FACILITATOR (+ optional LICEAT_X402_FACILITATOR_KEY) to
enable inline x402 settlement, and
LICEAT_STRIPE_SECRET_KEY + LICEAT_STRIPE_WEBHOOK_SECRET (enable card
payments). The built-in sentinel (liceat sentinel) attacks the core invariants and
probes your deployment — this site runs it every ten minutes: live report.An OpenAPI 3.1 contract is served at /openapi.json. A Prometheus exposition is at /metrics (scraper-gated). And Liceat ships as a native MCP server (liceat-mcp-server) so any agent host can verify warrants, resolve agent reputation, and read the log as first-class tools — LICEAT_GATEWAY selects the gateway.
Every deployment includes /admin — a granular business + operations console (revenue by rail, signups, decisions/day, top tenants, treasury address, audit-chain and sentinel status). It is gated by your admin token and served over the same HTTPS the gateway uses.
Questions → [email protected]