docs

how interlock works

A model writes trade proposals. A pure function decides them. Everything below is either arithmetic you can re-run or a live read you can check yourself.

Overview

Interlock is an AI trading agent for tokenized stocks on Solana with one unusual property: it cannot decide anything. The model's output is a request. The decision is made by lib/policy.ts — a pure function with no clock, no network, and no model inside it.

That separation is the entire safety story. A model can be confident and wrong, or steered by whatever it just read. None of that reaches your money if the thing holding the trigger is arithmetic.

The loop

  1. 1You set six numbers — the policy.
  2. 2The agent reads live prices for the symbols you allow and writes one proposal with a thesis.
  3. 3The engine runs every rule and stamps ALLOW or REFUSE, naming the line that decided it.
  4. 4You tighten a rule and the same proposal is re-judged instantly — in your browser, by the same function.

The six rules

verdict = f(proposal, policy, spentTodayUsd)

symbol      ∈ policy.allowedSymbols     SPYx, QQQx, GLDx
side        ∈ policy.allowedSides       buy
0 < size    ≤ policy.maxSizeUsd         $500
confidence  ≥ policy.minConfidence      0.62
thesis.len  ≥ policy.minThesisChars     180
spent+size  ≤ policy.dailyBudgetUsd     $2000
  • ·Symbols are an allowlist, never a blocklist. A ticker that isn't named is refused — including ones that didn't exist when you wrote the rule.
  • ·The budget counts today's spend. It's passed in, not read from a clock, so the same inputs always give the same verdict.
  • ·Every failing rule is reported — not just the first one.

Edges

A proposal that passes by sitting exactly on a limit is stamped EDGE. It's still an ALLOW — you authorized it — but a rule you only just cleared is a rule worth re-reading. The engine also exposes the weakest proposal your policy would allow: max size, minimum confidence, minimum thesis. Not a suggestion — a warning about the floor you've set.

The adversary

A second model is told your policy and asked for the worst trades it still permits. Its attempts go through the same engine, in public. Whatever gets through is not a flaw in the engine — it's the floor of what you allowed. The fix is always to tighten the rules, never to argue with the model.

attack my rules →

API reference

All endpoints return JSON. The verdict is the same function the UI runs.

POST/api/decide

Rule on a proposal. No model involved — pure arithmetic, so anyone can audit a verdict without trusting our UI.

{
  "proposal": { "symbol": "SPYx", "side": "buy",
                "sizeUsd": 200, "confidence": 0.8,
                "thesis": "…" },
  "policy": { "maxSizeUsd": 500 },
  "spentTodayUsd": 0
}
→ { "verdict": { "decision": "ALLOW", "checks": [...],
                 "failed": [], "edges": [], "reason": "…" } }
POST/api/propose

The agent writes one proposal under your policy, priced from the live market — then the engine rules on it.

{ "policy": { "allowedSymbols": ["SPYx"] } }
→ { "proposal": {...}, "verdict": {...}, "market": [...] }
POST/api/probe

The adversary hunts for the weakest trades your policy still allows, and the engine rules on each attempt.

{ "policy": { "minConfidence": 0.5 } }
→ { "floor": {...}, "attempts": [...],
    "gotThrough": 2, "refused": 1 }
GET/api/stocks

The 59 verified tokenized stocks, priced live. Anything unpriced is labelled, not quietly counted.

→ { "stocks": [ { "symbol": "SPYx", "name": "S&P 500",
       "mint": "Xso…", "priceUsd": 773.83 } ], … }

Honesty & safety

  • ·Nothing is executed. Interlock decides; it does not trade for you. When execution ships, it ships behind these same rules.
  • ·Non-custodial. Connecting a wallet only reveals your address.
  • ·Real or zero. Counters that need real signed verdicts stay at zero until they exist.
  • ·One official address. $ILOCK's contract appears only on the token page and @interlocklat on X — anywhere else is a fake, however early it appeared.