@kleros/agentkit
v0.3.0
Published
Agent-first CLI/MCP/HTTP toolkit for Kleros dispute resolution
Readme
@kleros/agentkit
A CLI and toolkit for AI agents and humans to interact with the Kleros decentralized arbitration protocol.
Built with incur — the CLI framework for agents and humans — and viem for on-chain interactions.
Status
0.3.0 — current release. Read-only command surface: courts, disputes, evidence, dispute/court policy, arbitrable classification, composite dispute brief, and juror stake/leaderboard queries across Ethereum, Gnosis, Arbitrum One (v2 beta), and Arbitrum Sepolia (v2 testnet). The Arbitrum Sepolia devnet stays fully usable under arbitrum-sepolia-devnet, but is no longer advertised. Pre-1.0 — the API may change between minor versions. Write operations (staking, voting, dispute creation, appeals) are not yet available — see Roadmap.
Upgrading from 0.2.x? This release is breaking. The bare arbitrum-sepolia chain slug is retired — it no longer resolves anywhere and is rejected by name on every surface, because two Kleros v2 deployments run on Arbitrum Sepolia and the bare name never identified one of them. Pass arbitrum-sepolia-testnet or arbitrum-sepolia-devnet instead, and re-run kleros config set chain once if the old value was persisted. The environment overrides derived from that slug are renamed with it and, unlike the slug, fail silently: KLEROS_RPC_URL_ARBITRUM_SEPOLIA and its two matching subgraph variables are read by nothing if left at the old spelling. Two further breaks: a chain value that does not resolve is now a CHAIN_NOT_SUPPORTED error where it previously returned a successful three-chain fan-out, and the config commands no longer report an ethereum default for chain — config list now reads value: "fan-out" with source: "unset". Read 0.3.0 for the full migration.
Coming from 0.2.0 or earlier? 0.2.1 also changed behaviour you did not ask to change: the default Ethereum RPC is now https://eth.drpc.org (the previous default served no historical logs at all), dispute get gains always-present unresolvedFields/unresolvedReason fields, and a transport failure on the first-generation Meta-Evidence path now returns RPC_ERROR where it previously returned META_EVIDENCE_NOT_FOUND — an error-code change an integration branching on the old code will observe. Read Changed — consumer-visible behaviour before upgrading, and Known limitations on what a free public RPC can and cannot serve.
Use >=0.2.1: on 0.2.0, first-generation Ethereum policy resolution fails out of the box on a clean install because the shipped default Ethereum RPC serves no historical logs, --format md silently drops nested values, and text submitted to a dispute can forge markdown table rows and columns. 0.1.0 is deprecated (broken on fresh installs due to a transitive dependency resolution issue), and 0.1.1 fails npm install on default-configured npm >=11 (allow-git=none rejects a git-URL transitive dependency, removed in 0.1.2).
A programmatic import/require API is also exported from this package (see exports in package.json), but it is undocumented and unstable pre-1.0 — the CLI/MCP surface documented here is the supported interface, with no semver stability guarantees on internals.
Quickstart
No installation required — run directly with npx:
npx -y @kleros/agentkit court list --chain ethereum
npx -y @kleros/agentkit dispute get 797 --chain gnosis --format jsonFor repeated use, install globally instead:
npm i -g @kleros/agentkit
kleros court list --chain ethereumWhat is this?
Kleros is a decentralized dispute resolution protocol deployed on Arbitrum, Gnosis, and Ethereum. @kleros/agentkit gives agents and developers a single, token-efficient interface to:
- Browse courts, disputes, and juror activity
- Resolve court and dispute policy (what jurors are asked to apply when ruling)
- Walk evidence submissions, including IPFS-hosted attachments
- Classify arbitrable contracts and pull a composite dispute brief in one call
- Rank jurors by staked PNK
Every command works from the terminal or as an MCP server — with zero extra configuration. Write operations (staking, voting, creating disputes, submitting evidence, interacting with Curate/escrow/Reality.eth, ERC-8183 evaluators) are planned but not yet shipped — see Roadmap.
Features
- Agent-first: TOON output by default (40% fewer tokens than JSON), call-to-actions, token pagination,
--llmsmanifest - Human-friendly: readable table output, interactive fallbacks, shell completions
- MCP built-in:
kleros --mcpstarts an MCP stdio server - Multi-chain reads: Ethereum (v1), Gnosis (v1), Arbitrum One beta (v2), Arbitrum Sepolia testnet (v2) with automatic version routing. The Arbitrum Sepolia devnet is still reachable by name as
arbitrum-sepolia-devnet; it is registered but not advertised - Cross-chain by default: a list command with no
--chaindrains Ethereum, then Gnosis, then Arbitrum One, in that order. Because that set spans two protocol generations,dispute listrows carry aruledSemanticsmarker and the envelope carries a one-offsemanticsNoteexplaining it — see Mixed protocol generations
Architecture
+--------------------------------------------------+
| Kleros Skills (SKILL.md) | Agent-facing docs, examples,
| Wraps CLI with context, explains when and why | progressive disclosure
| to use each command |
+---------------------+----------------------------+
| CLI | MCP Server | incur surfaces
| kleros .. | --mcp | TOON output, CTAs,
| | | token pagination
+---------------------+----------------------------+
| Middleware (incur) | Chain resolution
| cli.use() -- chain resolution (read-only; | (no wallet middleware
| no wallet middleware shipped yet) | shipped yet)
+--------------------------------------------------+
| Core Functions (TypeScript) | Pure business logic,
| disputes, courts, evidence, policy, arbitrable | read-only,
| | framework-agnostic
+--------------------------------------------------+
| viem (on-chain reads) + subgraph (The Graph) + | Multi-chain
| IPFS (cdn.kleros.link) |
+--------------------------------------------------+
| Kleros Contracts (read paths) | Ethereum (v1),
| KlerosCore/KlerosLiquid, SortitionModule, | Gnosis (v1),
| DisputeKitClassic, EvidenceModule | Arbitrum One (v2 beta),
| | Arbitrum Sepolia (v2 testnet)
+--------------------------------------------------+Write-path components (wallet providers, staking, voting, dispute creation, Curate/escrow/Reality.eth integration) are planned but not part of this diagram — see Roadmap.
Agent Usage
In-Repo Skill
AgentKit ships a Claude Code skill at skills/agentkit/SKILL.md. Loading this skill gives agents the full command surface, peer-MCP composition guidance (markitdown-mcp for binary evidence), policy intersection rules, and common gotchas — all from the repo itself without network fetches.
To install in your project: copy or reference skills/agentkit/SKILL.md in your Claude Code configuration.
The CLI can also install it for you — kleros skills add puts it in your shared agent skills directory, kleros skills add --no-global puts it in the current project instead, and kleros skills list shows install status. The same command also installs a generated reference stub per command group, so expect more than one skill.
MCP Server (Claude Code, Cursor, Amp)
Register kleros as an MCP tool server so AI agents can call dispute queries directly. No installation required — the one-liner uses npx:
claude mcp add kleros -- npx -y @kleros/agentkit --mcpAlready installed the binary globally? Register it directly instead:
kleros mcp add # registers for Claude Code and Cursor by default
kleros --mcp # or start manually (stdio transport)Chain configuration: MCP clients choose the chain on each individual tool call — pass a chain argument alongside the tool's other arguments, e.g. "arguments": { "chain": "gnosis", ... } (see Example MCP Tool Call below). That per-call argument is the highest-priority chain source: it outranks the --chain flag, KLEROS_CHAIN and the persisted config, and it wins even when the value the server started with does not resolve at all. Full order in the KLEROS_CHAIN row.
KLEROS_CHAIN and kleros config set chain supply the session default — the chain used only when a call omits chain:
KLEROS_CHAIN=gnosis npx -y @kleros/agentkit --mcp
# Or persist: kleros config set chain gnosisTool Discovery (--llms)
kleros --llms # compact table -- best for agents
kleros --llms-full # full docs with args, options, output schemas
kleros --llms --format json # JSON for structured parsingExample MCP Tool Call (JSON-RPC)
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "dispute_list",
"arguments": { "court": "1", "limit": 10 }
}
}Tool names follow the pattern group_command (e.g., dispute_list, court_get, juror_info).
Context-Aware Suggestions (CTAs)
Every response includes a cta block with the next logical command:
{
"data": { "id": "42", "status": "Vote", "court": "1" },
"cta": {
"description": "Voting period -- review evidence and court policy",
"commands": [
{ "command": "evidence list", "description": "Review evidence before voting" },
{ "command": "court policy", "description": "Read court policy for this ruling" }
]
}
}For full MCP configuration options, see the incur documentation.
Mixed protocol generations
Running a list command without --chain fans out across Ethereum, Gnosis, then Arbitrum One, in that order — one chain per page, draining each before advancing to the next. That set spans two generations of the Kleros protocol, and the two do not agree on what ruled means:
| Kleros version | Chains running it today | ruled becomes true when |
|---|---|---|
| v1 | Ethereum, Gnosis | the ruling execution call notified the arbitrable contract |
| v2 | Arbitrum One, Arbitrum Sepolia testnet, Arbitrum Sepolia devnet | the dispute reached its execution period — which may lag actual notification |
The generation belongs to the Kleros deployment, not to the chain. The right-hand column is a fact about today's deployments, not a property of those chains — nothing prevents Kleros v2 from being deployed on a chain that runs v1 today. Branch on the marker below, never on the chain name.
Rather than leave that to documentation an agent never reads, dispute list states it in the output:
- Every row carries
ruledSemantics:executedon rows from a Kleros v1 deployment,period-reachedon rows from a v2 deployment. It is present on every row of every chain, so its absence never implicitly means anything. - The envelope carries
semanticsNotewhenever a chain running Kleros v2 is in scope — from the default fan-out or an explicit--chainalike, and regardless of which chain the current page happened to drain. It is emitted once per page, not per row.
dispute get needs neither: its ruling/ruled are read live from the arbitrator contract, so its rows are marked ruledSemantics: onchain and carry no lag caveat. Reach for dispute get whenever a ruling value has to be current.
Configuration
Persist defaults with config set to avoid passing flags on every command. Configuration is stored in ~/.kleros/config.json.
Supported keys
| Key | Type | Values | Description |
|-----|------|--------|-------------|
| chain | string | ethereum, gnosis, arbitrum-sepolia-devnet, arbitrum-sepolia-testnet, arbitrum-one, sepolia | Default chain for all commands. Overridden by --chain flag per-command. Accepts every registered chain, which is wider than the advertised set — arbitrum-sepolia-devnet and sepolia are reachable but not advertised. The retired arbitrum-sepolia is rejected; use one of the two deployment-qualified slugs. |
| datamapping-trust | string | trusted, all | Which v2 DisputeTemplate DataMapping actions may execute. trusted (default) allows only reads from endpoints AgentKit already trusts — the chain's registered subgraphs, its configured RPC, IPFS. all permits unrestricted read-only network egress to any endpoint a third-party template names, including loopback and private-range addresses. Operator-side only: env KLEROS_DATAMAPPING_TRUST or this config key, never a per-command flag. Public MCP/HTTP deployments must keep the default. |
Commands
kleros config set chain gnosis # Persist default chain
kleros config set datamapping-trust trusted # Persist the v2 DataMapping trust level
kleros config get chain # Read current value
kleros config unset chain # Remove persisted value (revert to flag/env resolution)
kleros config list # Show all supported keys with value/source/allowedValues/descriptionconfig get chain and config list report the chain that is actually enforced, not the raw string
found: a value in KLEROS_CHAIN or ~/.kleros/config.json that does not resolve is reported as
unresolved with the tier that supplied it (env or config) and a rejected: { value, tier } field
carrying the refused value, so it stays visible while no longer masquerading as the chain in force.
datamapping-trust resolves env → config → default: KLEROS_DATAMAPPING_TRUST wins over the persisted
value, which wins over the trusted default. Resolution stops at the first tier that supplies a value and
an unrecognised value there fails closed to trusted rather than falling through, so a typo in the
environment variable cannot silently activate a persisted all. See
Environment Variables for what each level permits.
Unknown keys are rejected with INVALID_CONFIG_KEY — only the keys listed above are supported.
Environment Variables
| Variable | Purpose | Default |
|----------|---------|---------|
| KLEROS_RPC_URL_ETHEREUM | Override the default public Ethereum RPC. Historical eth_getLogs requires an archive-capable endpoint, and providers differ in how they limit it: some cap the block range per request (eth.drpc.org and Infura both at 10 000 blocks), others cap the result-set size instead (Alchemy serves wide ranges when few logs match), and some serve no historical logs at all — including ethereum-rpc.publicnode.com, the default through 0.2.0. Meta-Evidence resolution now bounds its own scans to fit the strictest of these, so an archive-capable endpoint can serve dispute policy — but free public endpoints serve historical eth_getLogs unreliably (the default included), so disputes whose Meta-Evidence needs a historical scan want a dedicated endpoint set here. Reality-arbitrable enrichment (rulingOptions) still issues wide scans (backlog 999.30), so the Reality handler integration tests on Ethereum (disputes 1650, 1651) and pnpm update-deployment-blocks additionally need an endpoint tolerant of wide block ranges. | https://eth.drpc.org |
| KLEROS_RPC_URL_GNOSIS | Override the default public Gnosis RPC (e.g. https://rpc.gnosischain.com). A public Gnosis RPC is accepted by default since Gnosis archives eth_getLogs broadly. | https://rpc.gnosischain.com |
| KLEROS_RPC_URL_SEPOLIA | Override the default public Ethereum Sepolia RPC. This is a different chain from either Arbitrum Sepolia deployment — it is the Ethereum testnet, and neither of the two KLEROS_RPC_URL_ARBITRUM_SEPOLIA_* variables below applies to it. Same archive-capability rule as KLEROS_RPC_URL_ETHEREUM above: any archive-capable endpoint serves the bounded Meta-Evidence scans, while the Reality handler integration tests on Sepolia (disputes 111, 112) and pnpm update-deployment-blocks also need one tolerant of wide block ranges. This default was not re-probed during the 2026-08-19 provider survey, so it is left unchanged. | https://ethereum-sepolia-rpc.publicnode.com |
| KLEROS_RPC_URL_ARBITRUM_SEPOLIA_TESTNET | Override the RPC used for the Kleros v2 testnet deployment on Arbitrum Sepolia — the chain this README calls "Arbitrum Sepolia (testnet)", slug arbitrum-sepolia-testnet. | https://sepolia-rollup.arbitrum.io/rpc |
| KLEROS_RPC_URL_ARBITRUM_SEPOLIA_DEVNET | Override the RPC used for the Kleros v2 devnet deployment on Arbitrum Sepolia — the chain this README calls "Arbitrum Sepolia (devnet)", slug arbitrum-sepolia-devnet. Renamed: the previous KLEROS_RPC_URL_ARBITRUM_SEPOLIA no longer resolves, because the slug it was derived from is retired; the old name is read by nothing and fails silently if left set. | https://sepolia-rollup.arbitrum.io/rpc |
| KLEROS_RPC_URL_ARBITRUM_ONE | Override the default public Arbitrum One RPC — this is the v2 beta (mainnet) chain described throughout this README as "Arbitrum One (beta)". | https://arb1.arbitrum.io/rpc |
| KLEROS_SUBGRAPH_URL_ARBITRUM_ONE_CORE | Override the default Goldsky core subgraph URL for Arbitrum One (kleros-v2-coreneo). | https://api.goldsky.com/api/public/project_cmgx9all3003atlp2bqha1zif/subgraphs/kleros-v2-coreneo/v0.17.2/gn |
| KLEROS_SUBGRAPH_URL_ARBITRUM_ONE_DRT | Override the default Goldsky DRT (DisputeTemplate) subgraph URL for Arbitrum One (kleros-v2-drt). | https://api.goldsky.com/api/public/project_cmgx9all3003atlp2bqha1zif/subgraphs/kleros-v2-drt/v0.12.0/gn |
| KLEROS_INTEGRATION_TESTS | Set to true to enable integration tests that hit live subgraph and IPFS endpoints. | — |
| KLEROS_CHAIN | Pin the chain for every surface — CLI, MCP and HTTP alike — because it is read by the root chain middleware, not by --mcp. Resolution order: the per-command --chain flag (or the equivalent chain tool argument / query parameter) → this variable → the persisted ~/.kleros/config.json value → nothing. There is no default chain. When no source supplies one, commands fan out over the live production chains (ethereum, gnosis, arbitrum-one) rather than silently picking one; see Configuration to persist a value instead. | — |
| KLEROS_DATAMAPPING_TRUST | Which DisputeTemplate DataMapping actions AgentKit will execute when resolving a second-generation (v2) dispute policy. Two values. Under trusted (the default) a graphql action is permitted only when the mapping's endpoint is byte-equal to one of the active chain's registered subgraph URLs, reality actions are refused outright, on-chain reads go through AgentKit's own configured RPC, and IPFS reads are permitted. Under all every supported action type is permitted at any endpoint the template names — that is unrestricted read-only network egress, including loopback and private-range addresses. A public MCP or HTTP deployment should leave the default in place. This is operator-side configuration only: it is settable by this variable or by kleros config set datamapping-trust <value>, and is deliberately not settable by a remote caller or a per-command flag. An unrecognised value fails closed to trusted. | trusted |
| KLEROS_GRAPH_API_KEY | An operator-supplied Graph gateway key, seeded into the DataMapping render context only when the trust level is all. AgentKit never forwards its own embedded gateway credential to a third-party template endpoint, and under the default trusted level this variable is not read at all — a non-registered endpoint is refused before any key is needed. Exfiltration consequence, stated plainly: under all, this key is placed into a render context that untrusted template mappings can direct at any endpoint, so a hostile template can read it out. That is precisely the opt-in all represents. Use a dedicated least-privilege key — scoped to the subgraphs it needs and spend-capped — never one with broader access. | — |
Override names are derived from the chain slug, not hand-maintained: KLEROS_RPC_URL_{SLUG} and KLEROS_SUBGRAPH_URL_{SLUG}_{CORE|DRT}, uppercased with - replaced by _. Renaming a slug therefore renames its variables, which is why the Arbitrum Sepolia devnet's RPC override and its two subgraph overrides (KLEROS_SUBGRAPH_URL_ARBITRUM_SEPOLIA_DEVNET_CORE / ..._DRT) all carry the qualified spelling now; the pre-rename names no longer resolve and are read by nothing.
Default RPCs are free public endpoints — fine for light use, but may rate-limit under real traffic. Set the KLEROS_RPC_URL_* overrides above to a dedicated provider (Infura, Alchemy, or any RPC you trust) for reliable production use, especially right after this package's public launch. The default Ethereum RPC was eth.llamarpc.com through 0.1.2 — it went fully unreachable (HTTP 521) rather than just 403ing datacenter IPs, so it was replaced with ethereum-rpc.publicnode.com (2026-08-12). That endpoint turned out to be non-archive: it serves no historical eth_getLogs and no historical eth_getCode at all, which broke first-generation Ethereum policy resolution out of the box, so the default is now eth.drpc.org (2026-08-19) — archive-capable, keyless, and range-capped at 10 000 blocks, which the bounded Meta-Evidence scans respect. Set KLEROS_RPC_URL_ETHEREUM to a dedicated provider (any archive-capable RPC you trust) if you need higher throughput than a free public endpoint offers. See skills/agentkit/SKILL.md for which commands make live RPC calls vs. subgraph-only reads. Arbitrum One's Goldsky endpoints (KLEROS_SUBGRAPH_URL_ARBITRUM_ONE_*) have no documented rate limit or SLA — they are the free public beta subgraphs; expect possible throttling under heavy use and override with your own Goldsky project if needed.
Feedback
kleros report-issue create writes a local .md report by default. kleros report-issue create --submit posts it as a GitHub issue — by default to the public kleros/kleros-skills repository (requires $GITHUB_TOKEN). This repository (kleros/agentkit) stays private for now and would reject non-collaborator issue submissions, which is why report-issue targets kleros/kleros-skills instead.
Development
Setup
Requires Node.js >=22.
pnpm install
pnpm build
pnpm testTesting the MCP server against live source
The installed kleros binary is dist/cli.js, so code changes need a rebuild before the MCP server sees them. Three loops, fastest first:
1. Raw stdio (no client, no rebuild) — iterate on tools and handshake logic:
pnpm dev -- --mcp # runs tsx src/cli.ts --mcp
# pipe JSON-RPC frames in to exercise tools/list, tools/call, etc.2. tsx-shimmed registration (live source, restart per change) — iterate from inside Claude Code, Cursor, or any MCP client without rebuilding:
# Edit ~/.claude.json -> mcpServers.kleros:
# "command": "tsx",
# "args": ["/absolute/path/to/agentkit/src/cli.ts", "--mcp"]Restart the MCP client after each code change. No pnpm build needed — tsx reads src/*.ts directly.
3. Globally linked binary (closest to production) — test the real install flow end-to-end:
pnpm build
pnpm link --global # symlinks `kleros` -> this repo's dist/cli.js
which kleros # verify it points at your pnpm global bin
kleros mcp add # registers `kleros --mcp` in ~/.claude.jsonIteration loop: pnpm build after each change, then restart the MCP client.
Teardown:
pnpm unlink --global @kleros/agentkit
# then re-run `kleros mcp add` against the published version, or edit ~/.claude.json manuallyGotchas
- Tool list is cached at session start — adding a new command requires both rebuild AND client restart before it appears in
tools/list. - Only the session default is fixed at server-start — any single call switches chain freely by passing
chainin its tool arguments, but a call that omitschaingets whatever default the server started with (or the cross-chain fan-out, if it started with none). There is no session-level switch and no root-level chain option, so changing that default means editingKLEROS_CHAINorkleros config set chainand restarting the client. - Empty
dist/cli.jsafter a pull — theklerosshebang will fail silently. Runpnpm buildfirst. - Multiple local checkouts —
pnpm link --globalonly tracks the most-recently-linked one.
Release Process
The canonical release procedure — pre-flight checklist, security-gated tagging, and
post-release verification — lives in RELEASING.md at the repository root. In short:
only repository admins can publish, release tags must be GPG-signed by a trusted key,
and publishing authenticates via npm trusted publishing (GitHub Actions OIDC), so no
npm token exists.
Roadmap
Planned, not yet shipped:
- Write operations — staking PNK, casting votes, creating disputes, submitting evidence, appealing rulings (requires wallet middleware)
- Wallet-agnostic signing — plug in any EVM wallet (raw private key, Coinbase CDP, Privy, or any viem-compatible signer)
- Curate, escrow, and Reality.eth integration — registry entries, escrow payouts, oracle question resolution
- ERC-8183 evaluator registration and invocation
- v2 dispute creation — Arbitrum One reads and
dispute policyvia DisputeTemplate/@kleros/sdkalready ship, and the Arbitrum Sepolia testnet deployment is now supported for reads alongside them. What remains is the write path: creating v2 disputes
Not yet scheduled to a specific release. Tracked internally; file a feedback report if there's a specific capability you need.
