Docs
What GlassBox actually verifies, how to wire your own trading agent into it, and the exact hashing rules a stranger would need to check our work independently.
What it verifies (and what it doesn't)
GlassBox proves one specific thing: that a trading decision and an independent risk verdict existed, in exactly the form shown, before execution was allowed to proceed — and that nobody has edited that record since. Every hash on this site was produced by a real commit to Monad testnet; nothing here is simulated.
It does not broker real trades. In this reference build, the execution step (place_order()) is a clearly labeled stub that prints instead of calling an exchange — because the thing being proven (a real risk check ran and was committed first) is true regardless of what happens after the gate opens. A real integration replaces that one function with your actual exchange call; the commit-and-verify guarantee doesn't change.
Integrate your agent
The gate is a decorator, not a framework — it wraps the boundary between "a decision was reached" and "an action executes." It doesn't inspect your trading logic or your risk logic. Wrap whatever function currently executes a trade, wherever that already happens in your pipeline:
pip install -e path/to/gate # or from your fork's git URL from glassbox_gate import onchain_gate @onchain_gate(policy="your_policy_v1")def execute_trade(decision, risk_verdict): if risk_verdict["verdict"] == 1: your_existing_place_order_function(decision)Point it at a running GlassBox backend with GLASSBOX_BACKEND_URL. The gate canonicalizes your payload, posts it, waits for the commit to confirm, and raises GateBlockedError instead of calling your function if the commit fails — it never executes on a best-effort basis.
Required fields
Only three fields are structurally required. Everything else is free-form — send whatever your agent actually has:
| Field | Required | Notes |
|---|---|---|
decision.agentId | Yes | Any string identifying your agent on the shared registry. |
decision.action | Yes | Whatever verb describes the decision — not limited to buy/sell/hold. |
riskVerdict.verdict | Yes | 0 (rejected) or 1 (approved). |
decision.price | No | If numeric and present, the feed plots it on the price chart. Omit it if it doesn't apply. |
anything else | No | Stored and shown on the Verify modal exactly as sent, whatever the shape. |
Today, integrating means self-hosting: you run your own instance of the backend (or point at one someone else runs) and either deploy your own contract or register your policy on a shared one. There's no hosted signup flow yet.
Canonical hashing
The whole Verify flow depends on two independent implementations producing byte -identical output. The rules, fixed and non-negotiable:
- Object keys sorted alphabetically, recursively.
- Numbers rounded to 8 decimal places and serialized as fixed-point strings, never raw floats.
- Timestamps as ISO 8601, UTC, second precision (
YYYY-MM-DDTHH:MM:SSZ). - Compact JSON serialization — sorted keys, no incidental whitespace, raw UTF-8 (no
\u-escaping). - Hash = keccak256 of the UTF-8 bytes of that string, as a 0x-prefixed hex string.
Reference implementations: gate/glassbox_gate/canonical.py (Python) and webapp/lib/canonical.ts (TypeScript). Reimplement this in any other language and you can verify a commit without trusting either of ours.
API reference
The backend exposes three endpoints:
POST /api/decisions body: canonical {decision, policy, riskVerdict, timestamp} payload → { id, onchainId, decisionHash, txHash, explorerUrl } Non-2xx means the commit failed -- the gate blocks on any non-2xx response. GET /api/decisions → [{ id, onchainId, agentId, action, verdict, price, decisionHash, txHash, explorerUrl, createdAt }] GET /api/decisions/:id → same shape as above, plus the full raw "payload" used for VerifyContract
Two mutating functions, no update or delete, ever: registerPolicy(bytes32) and commitDecision(bytes32, string, uint8). The agentId parameter means this is a shared registry — any number of agents can commit to the same contract.
Deployed at 0x0f0bcD814fcba81D6cEb900F1313E64f07d6E800 on Monad testnet.