GlassBox

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.

01

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.

02

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:

FieldRequiredNotes
decision.agentIdYesAny string identifying your agent on the shared registry.
decision.actionYesWhatever verb describes the decision — not limited to buy/sell/hold.
riskVerdict.verdictYes0 (rejected) or 1 (approved).
decision.priceNoIf numeric and present, the feed plots it on the price chart. Omit it if it doesn't apply.
anything elseNoStored 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.

03

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.

04

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 Verify
05

Contract

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.

Source: https://github.com/arnnnavvvvv/GlassBox