A framework & ref. implementation for policy-constrained agents that can safely move value onchain.
gctl is an open-source framework and reference implementation for running policy-constrained autonomous agents when real value or reputation is on the line, not just demos that "ask an LLM to send a transaction." It treats governance as first-class: a deterministic policy graph (YAML-style DSL, compiled and evaluated the same way every run) is anchored onchain via a PolicyRegistry, so constraints are inspectable and integrity-checked rather than implied by prompt text.
Identity is ENS-driven: structured roles, passports, and reverse verification on critical paths so automation is tied to accountable names, with fail-closed behavior when identity or policy cannot be trusted. Execution is reliability-aware through KeeperHub workflows, with policy-derived branches such as safe vs escalated vs blocked, with retries, reconciliation, and auditable run records instead of fire-and-forget sends. Optional 0G surfaces add compute preflight, encrypted-at-rest memory/artifacts, storage-backed policy URIs, and explicit attestation semantics (simulated vs onchain) without collapsing trust into a single opaque API call.
The product story is observable accountability: operators get evidence-shaped outputs, schema-validated trust artifacts, and a Vite + React operator console that never silently pretends synthetic data is live telemetry. Judges and builders can repeat a full gate with npm run judge:preflight, which ties env contracts, compilation, tests, typecheck, and captured evidence under docs/evidence/. In short: policy first, identity verified, execution observable, so an agent can explain why it acted, prove which constraints applied, and deny or degrade explicitly when dependencies are missing or untrusted.
The repo is a TypeScript monorepo on Node 22 (see root engines), with Vitest for tests, Hardhat 3 + ethers v6 + OpenZeppelin for Solidity (PolicyRegistry, optional anchoring contracts), and tsx-driven scripts for demos, env/evidence validation, and the judge:preflight harness. Core pieces: dsl/ (policy schema and samples), policy-engine/ (deterministic compiler + evaluator + storage adapter boundary), agent-sdk/ (PolicyClient and adapters for ENS, 0G, KeeperHub), keeperhub-workflows/ (routing, execution, reconciliation, analytics-shaped summaries), ens-identity/, contracts/, an indexer/ scaffold, and examples/.
The web app is Vite + React 18 with Radix UI, TanStack Query, and related UI utilities; it deploys to Vercel. api/ holds Vercel Functions: /api/ops/* wraps indexer-style payloads in a trust envelope (source, trustStatus, reasonCode, recoveryAction) so the SPA can show badges and fallback banners; api/functions/debate-policy.js runs a Proposer, Critic, and Synthesizer chain when OPENAI_API_KEY is set and otherwise falls back to a deterministic synthesizer, useful for demos that must not hard-require a vendor. Evidence is machine-checkable: AJV validates JSON against schemas (e.g. docs/evidence/schema/trust-evidence.schema.json).
Partner integration is deliberately adapter-shaped: ENS for passports and authorization records; KeeperHub for execution branches and logs; 0G for compute/memory/attestation with deterministic local fallbacks for judging. A notable engineering choice: the official 0G storage SDK is not a root npm dependency, it can be loaded as an optional peer at runtime when operators opt in (docs/zerog-storage-sdk-peer.md), keeping the default install and CI path stable while still supporting live storage paths. Root runtime deps stay small (yaml, ethers, dotenv, express for indexer, ajv for validation). That split, a strict fail-closed core, explicit trust UI, and repeatable preflight, is the "nitty-gritty" glue that makes the stack both demoable and defensible under review.

