Ligis
Portable on-chain identity and verifiable credentials for AI agents. Live on Pharos + Casper Testnet. Autonomous steward loop + x402 payments + CROO CAP commerce working end-to-end.
Active hackathon submissions
| Hackathon | Track | Demo | Submission doc |
|---|---|---|---|
| Casper Agentic Buildathon 2026 | Casper Innovation / Agentic AI / RWA | 1:35 Casper walkthrough | docs/casper-buidl.md |
| CROO Agent Hackathon 2026 | Data & Verification + Open A2A | CROO demo (upload before deadline) | docs/croo-hackathon-submission.md |
One product, two proofs: Casper contracts are the on-chain source of truth; CROO is how other agents pay for verification before A2A commerce. Same CredentialRegistry backs both demos.
Demo videos
Casper Agentic Buildathon (on-chain identity + x402)
Watch the 1:35 walkthrough (MP4, 5.6 MB) — also viewable on the release page.
CROO Agent Hackathon (CAP commerce + verification)
Watch the CROO walkthrough
— CAP negotiate → pay → deliver, with Casper on-chain proof. Source: videos/ligis-croo-hackathon/.
The Casper video is composed in videos/ligis-buildathon-2026/ using
HyperFrames with live terminal
captures of casper-e2e-demo.ts and casper-x402-demo.ts, real cspr.live
transaction screenshots, and a 9-segment TTS voiceover.
A chain-agnostic agent identity runtime: one ChainAdapter interface, two
implementations (EVM/Pharos live, Casper/Odra live), and a Trust
Steward that runs the same loop on either chain. Credentials are chain-neutral
by design — capabilityHash("kyc.basic") produces the same 32-byte hash on
every chain, which is what makes cross-chain credential portability possible.
The full autonomous loop on Casper:
- BOOT — Agent mints its own identity (
AgentId.mint_self) on Casper Testnet - REASON — 0G Compute (or local fallback) maps the goal to required capabilities
- GATE — Checks
CredentialRegistry.is_capablefor each capability - ACT — Issues missing credentials via signed EIP-712
issuecalls - RECORD — Anchors evidence manifest to 0G Storage + Casper (
set_token_uri)
Then the agent pays for premium RWA data via x402:
- Agent requests
GET /premium→ 402 Payment Required (credential verified, payment needed) - Agent signs
TransferWithAuthorization(EIP-712 with Casper domain) - Agent resubmits with
X-PAYMENTheader → 200 OK with tokenized real-estate market data - Settlement on Casper Testnet (on-chain tx)
41 Foundry tests + 12 Odra tests + 47 TypeScript tests passing. 4 on-chain Skills + 2 helpers
- Trust Steward Agent. CLI. MCP server. x402 Trust Gate. MIT.
What this is
Ligis gives every AI agent a portable, revocable on-chain identity (PharosAgentID ERC-721 on EVM, AgentId Odra contract on Casper) and EIP-712 capability credentials (CredentialRegistry). Credentials are signed off-chain with secp256k1; the EVM contracts verify signatures on-chain, and the Casper port now recovers the issuer address on-chain for both issue and revoke using the pure-Rust k256 crate. Any contract can gate access in one line: require(creds.isCapable(subject, keccak256("agent.commerce.escrow")), "not allowed").
It ships live on Pharos — the identity layer the Pharos agent economy composes on today (Aegis, Pact, FaroLink, Maestro, x402). The Casper adapter (@ligis/adapter-casper) is fully implemented and live on Casper Testnet — all 8 ChainAdapter operations talk to Odra contracts via casper-client, the WASM contracts are deployed, and the smoke test passes end-to-end (mint → sign → submit → verify → revoke). The web frontend is chain-aware on all pages (?chain=casper-testnet is live). See docs/casper-buildathon.md for the submission plan.
Skills
| Skill | What it does |
|---|---|
ligis-issue |
Mint an Agent ID NFT; issue an EIP-712 capability credential |
ligis-verify |
Read-only: does a subject hold a valid credential? |
ligis-revoke |
Issuer revokes a credential (permanent) |
ligis-rotate |
Move Agent ID to a new controller key (recovery) |
ligis-hash |
Helper: keccak256 a capability name |
ligis-sign |
Helper: build + sign an EIP-712 credential off-chain |
ligis agent run |
Trust Steward: boot → reason (0G Compute) → gate → act → record (0G Storage) |
Deployed contracts
First deployment is live on Pharos Atlantic testnet (chainId 688689):
| Contract | Address |
|---|---|
PharosAgentID |
0xbd163Be6882CF6DE54bA10d726F4f619Bdc28a89 |
CredentialRegistry |
0x9E6eC93200E185c11423eb3A5150449D49d3473A |
Web frontend
A Next.js app (web/) deployed on Vercel provides a live Steward interface
with SSE streaming of the full boot → reason → gate → act → record loop.
Three modes:
- Simulated — no env vars needed, uses realistic timing + fake tx hashes
- Live reads — real
isCapableMulticalls against Pharos Atlantic - Live writes — real
mintSelf,issue(EIP-712),setTokenURIon-chain
When ZEROG_PRIVATE_KEY is set, the REASON phase calls 0G Compute (Qwen 2.5 7B,
TEE-verified LLM) and the RECORD phase uploads evidence manifests to 0G Storage.
Write transactions bypass eth_sendTransaction (unsupported by the default
Pharos RPC) by signing locally and sending via eth_sendRawTransaction.
Agent profile pages (/agent/<address>) show capability history from
AgentCapabilityChanged events with clickable PharosScan links.
See docs/setup.md for Vercel env var configuration.
Chain support
Ligis is chain-agnostic by design. Every chain implements the same
ChainAdapter interface from @ligis/core; the Trust Steward, CLI, and
MCP server consume the interface, not the implementation.
| Chain | Adapter | Contracts | Status |
|---|---|---|---|
| Pharos Atlantic (EVM) | @ligis/adapter-evm |
packages/contracts-evm (Solidity) |
Live — deployed, tested, steward running |
| Casper Testnet | @ligis/adapter-casper |
packages/contracts-casper (Odra) |
Live — contracts deployed, smoke test passing, web UI live |
Why this works across chains:
- Capabilities are chain-neutral:
capabilityHash("kyc.basic")produces the same0x...32on every chain because@ligis/corecomputes keccak256 off-chain and passes it to each adapter. The hash is the canonical id. - Agent identity uses DIDs:
did:ligis:<chain-id>:<chain-native-id>. - EIP-712 domain separation is per-chain: the domain separator binds the chain name + contract package hash, so a credential signed for one chain cannot be replayed on another.
- The same secp256k1 key can sign credentials for both chains — the off-chain EIP-712 signature verifies against the same issuer address on either chain.
To bring up another chain: implement ChainAdapter, add the chain branch
to getAdapter() in the CLI and MCP server, and (optionally) create
packages/contracts-<chain>. See MONOREPO_STRUCTURE.md
for the full architecture.
Quick start
pnpm install
# Mint an Agent ID on Pharos (default chain)
PRIVATE_KEY=0x... pnpm start -- issue --token-uri "ipfs://bafy.../meta"
# Verify a credential (read-only)
pnpm start -- verify --subject 0x... --capability "agent.commerce.escrow"
# Run the Trust Steward Agent
PRIVATE_KEY=0x... ZEROG_PRIVATE_KEY=0x... \
pnpm start -- agent run --goal "open an escrow with counterparty X"
# Casper (contracts deployed on Testnet — see docs/setup.md)
pnpm setup:casper # generate 3 testnet wallets
# → fund deployer at https://testnet.cspr.live/tools/faucet
# → transfer CSPR to agent + issuer
source .env.d/casper.env
pnpm deploy:casper # install WASM contracts to Casper Testnet
pnpm start -- --chain casper info
pnpm start -- --chain casper verify --subject <account-hash> --capability kyc.basic
npx tsx scripts/casper-smoke-test.ts # end-to-end credential lifecycle test
Demo: Autonomous Agent + x402 Payment on Casper
# 1. Run the Trust Steward loop (boot → reason → gate → act → record)
source .env.d/casper.env
source .env.d/zerog.env
export PRIVATE_KEY=$LIGIS_CASPER_DEPLOYER_PRIVATE_KEY
export LIGIS_CASPER_PUBLIC_KEY=$LIGIS_CASPER_DEPLOYER_PUBKEY
npx tsx scripts/casper-e2e-demo.ts
# 2. Start the x402 Trust Gate server
export LIGIS_GATE_PAY_TO="00<your-account-hash>"
export LIGIS_GATE_CAPABILITY="data.premium"
npx tsx packages/x402-server/src/index.ts &
# 3. Run the x402 payment demo (402 → sign → pay → 200 + RWA data)
npx tsx scripts/casper-x402-demo.ts
The steward loop produces 3-4 on-chain transactions on Casper Testnet:
mint_self— Agent mints its own identityissue— Self-issues each missing capability credentialset_token_uri— Anchors evidence manifest to 0G Storage
The x402 flow produces 1 additional on-chain transaction (a direct CSPR transfer in the demo's local-settlement fallback). Local settlement verifies the X-PAYMENT payload shape; full CEP-18 transfer_with_authorization settlement via the CSPR.cloud facilitator is wired but requires CSPR_CLOUD_TOKEN.
Browser-side Casper wallet (no relayer, user-funded)
There is now a browser-native Casper Testnet wallet wired into the web
steward. Every transaction — mint_self, issue, set_token_uri — is
signed locally in the browser and submitted through a stateless CORS-proxy
(/api/casper-rpc) to the public testnet RPC. No signing relayer. The
user funds their own gas.
How it works:
- Visit
?chain=casper-testneton the web app. The wallet tree (ConditionalProviders→WalletTree) lazy-mounts only on Casper pages; Pharos pages never loadcasper-js-sdk. - Click Connect Wallet → generate a 32-byte secp256k1 secp256k1 scalar
in the browser via
@noble/curves/utils.randomSecretKey(), derive the Casper public key + account hash + EVM-style issuer address, and copy the key to your clipboard / paste it back later. - Fund at https://testnet.cspr.live/tools/faucet (one-time per account, 100 CSPR from the faucet).
- Click Run Steward → the
web/lib/casper-browser/steward.tsloop runsmint_self → verifyCapability → signCredential + submitCredential → anchorEvidence, each one signed in-browser via@noble/curves/secp256k1.sign(digest, scalar). The off-chain EIP-712 credential digest is byte-identical to the server adapter's (both use@casper-ecosystem/casper-eip-712'shashTypedData, both sign with secp256k1), so on-chain signature recovery round-trips to the same EVM address the server's signer would produce.
Two smoke tests live in web/scripts/ for pre-judging validation:
pnpm --filter @ligis/web exec tsx web/scripts/smoke-wallet-crypto.ts
# → asserts @noble/curves r,s,v parity with ethers.Wallet (EVM addr roundtrips)
pnpm --filter @ligis/web exec tsx web/scripts/smoke-wallet-tx.ts
# → builds a CSSPR-2.0 mint_self TransactionV1 and asserts `mint_self` is on
# the wire bytes (does NOT submit; uses a placeholder package hash)
No new Vercel env vars required. The wallet UI reuses the existing
server-side LIGIS_CASPER_AGENT_ID + LIGIS_CASPER_CREDENTIAL_REGISTRY
(already set on Vercel for Casper reads) through /api/casper-config,
a tiny server route that strips the contract-package- prefix and
serves the bare hex hashes to the browser. Writes go through
/api/casper-rpc, a stateless CORS byte-proxy. The proxy holds no keys
and signs nothing — it's safe to expose publicly. So a wallet click
that round-trips to testnet needs zero new env vars beyond what the
chain-switching section already lists.
Files in web/lib/casper-browser/{keypair,eip712,operations,rpc,store,steward}.ts(x)
compose the wallet.
CROO Agent Protocol (CAP) integration
Ligis is listed as a callable agent on the CROO Agent Store.
Before one agent pays another, it can hire Ligis to run a counterparty risk
check and receive a pass/warn/fail verdict plus a 0–100 risk score. The
provider runs 24/7 in production (pm2-managed), so judges only need a
requester — no need to run a provider yourself.
Judge repro (CROO Hackathon):
# Hire Ligis via CAP (hits the live provider)
set -a && source .env.d/casper.env && source .env.d/croo.env && set +a && pnpm demo:croo
source file.envalone only sets shell-local variables — it does not export them to thenode/pnpmchild process.set -a(allexport) makes everything sourced after it exported automatically;set +aturns that back off. Without it,pnpm croofails immediately withMissing required environment variable: CROO_SDK_KEY.
| Service | Price | What you get | Input |
|---|---|---|---|
ligis.risk |
$0.75 | Counterparty risk check — pass/warn/fail + 0–100 score | { subject, capabilities, issuer?, minTtlSeconds? } |
ligis.verify |
$0.50 | On-chain credential verification | { subject, capability, issuer? } |
ligis.issue |
$1.00 | Signed capability credential issuance; optionally imports EAS provenance before issuing | { subject, capability, expiresInSeconds?, externalAttestation? } |
All three services are live and tested end-to-end: issue → verify (capable: true) → risk check (warn, maturing to pass after 7 days).
See docs/croo-integration.md, docs/attestation-integrations.md, docs/strategy.md, and packages/croo-adapter/.
Documentation
| Doc | What's in it |
|---|---|
| Strategy | Product strategy, competitive landscape, differentiation, roadmap, business model |
| Architecture | Contract design, module structure, repository layout |
| Attestation integrations | Self Protocol and EAS provenance, privacy boundaries, and rollout |
| Monorepo structure | Package layout, dependency graph, ChainAdapter interface, adding a new chain |
| CROO Integration | CAP adapter, Agent Store listing, provider/requester usage |
| API Reference | Service schemas, input/output examples, capability names, chains |
| CROO Hackathon submission | BUIDL copy, judge repro, track alignment |
| Casper Buildathon | Submission plan, product story, day-by-day roadmap, demo storyboard |
| Trust Steward Agent | The autonomous loop, 0G integration, build phases |
| Security | Non-custodial design, EIP-712 replay protection |
| Setup | From-scratch install, env vars, 0G wallet, Casper wallet, x402 server, deploy, verify |
| SKILL.md | Director entry point for AI agents |
| References | Per-skill command specs (issue, verify, revoke, rotate, hash, sign, composability) |
License
MIT — see LICENSE.
No comments yet
Be the first to share your take.