ROOST
Product notes

Permission
before action.

ROOST evaluates every proposed agent action against a mandate you define, server side, using state it loads itself. Decisions and executions produce separately signed receipts that anyone can verify.

Open the app →

Network

ROOST runs on Robinhood Chain, an Arbitrum Nitro network. This deployment runs on mainnet (chain 4663), where actions you sign move real funds. A testnet (chain 46630) exists and is what the server defaults to; pointing it at mainnet requires an explicit acknowledgement in configuration, which has been given here.

Robinhood Chain is a public EVM network. There is no brokerage integration and no tokenised-stock pair; the PLTR and Robinhood strings in the original demo were narrative examples and were not carried into the product. A clean $ROOST token launch is being prepared separately. No contract address is currently published, and the application does not require a token.

01 / Define

A mandate sets the account it governs, the assets that may move, the destinations value may reach, a per-transaction cap, a daily cap, an approval threshold, and optionally a concentration limit. Limits are expressed in the chain’s native token, because that is the unit this deployment can actually enforce without a price feed.

Saving changes writes a new immutable version. Earlier versions are never edited, so any past decision can still be read against the exact rules that produced it. Every evaluation records the hash of the version it ran against.

Assets are matched on chain and contract address. A symbol is display text: two tokens can share one, and an issuer can change it.

02 / Evaluate

An action submits an intent — what to move, how much, to whom. It does not submit balances, daily totals or fees. Those are loaded by the server from the chain and from its own accounting, because a caller that can assert its remaining budget has no budget.

Every rule returns a state, not a yes or no:

  • pass — satisfied.
  • fail — violated. The action is blocked.
  • requires_approval — within policy, but a human must confirm.
  • not_applicable — the rule does not govern this kind of action.
  • indeterminate — the rule applies, but its input is missing or stale, so the action is blocked rather than assumed safe.

That last state matters. A configured rule that cannot be checked is not a rule that passed. A stale quote, an unreachable node or a limit with no data source behind it all block, and the trace says which.

Boundaries are deliberate. Caps allow the exact limit; the approval threshold triggers strictly above it, because a mandate that says “approve above 0.5” must let 0.5 through. Concentration for a transfer uses (exposure − value) / (portfolio − value): value leaving reduces both the position and the portfolio.

03 / Reserve

An action that could still execute reserves its value against the current accounting window before the response is returned. The window row is locked for the whole decision, so two simultaneous actions cannot each fit into the same remaining headroom. A retry carrying the same idempotency key returns the original action and never reserves twice.

A window is a fixed 24-hour period ending at local midnight for a chosen offset from UTC. The offset is fixed rather than a named timezone, so no daylight-saving transition can quietly stretch a daily cap to 25 hours.

04 / Approve

An action above the threshold waits for a person. The approval binds to one exact action hash and one exact mandate version, and it expires. It stops applying if the mandate moves to a new version, and it can never override a hard limit or an emergency pause.

Pausing takes effect immediately. It is operational state held outside the mandate version, so pausing never rewrites policy history, and it is checked again before any already-approved work is dispatched.

05 / Execute

ROOST holds no signing key. You sign in your own wallet. Dispatching re-validates the entire policy against fresh state, then releases exactly one transaction — and nothing else may be submitted for that action.

Being honest about the boundary: ROOST can refuse to authorise, and it can prove afterwards that what landed on chain was not what it authorised, by comparing sender, target, value, calldata and chain. It cannot stop an owner opening their wallet and transacting directly. Preventing that would need a constrained signer whose authority is bounded on chain, which is not built here.

If a submission times out, the action is marked uncertain and keeps its budget reservation. A request that failed is not proof that nothing was broadcast, and releasing a hold on that guess is how a spending cap gets exceeded. Reconciliation resolves it against the chain; only a revert returns the budget, because only then did nothing move.

06 / Verify

Two receipt types, kept separate on purpose. A decision receipt attests that an evaluation happened and what it concluded — it is not evidence that anything settled. An execution receipt additionally records an observed transaction and its block reference.

Both are Ed25519 signatures over canonical JSON (RFC 8785). The public key and its identifier are served without authentication, and any payload can be checked against them, so a receipt is verifiable by someone who does not trust this server. Rotating a key keeps the old one published so historic receipts stay verifiable.

A signature proves this server produced that payload. It does not vouch for the market data inside it, and it cannot prove finality — a reorganisation can still displace a referenced block. Each receipt says so in its own text.

Not built yet

  • Agents can propose, not execute. An enrolled agent reads its bound mandates and submits actions through the MCP server; it cannot approve, dispatch, sign or pause, and revoking it takes effect on the next request.
  • Transfers only — native and ERC-20. No swaps, quotes or routing, so the liquidity and slippage rules report not_applicable rather than implying a check that never ran.
  • USD limits depend on a live rate. Prices come from several public venues that are cross-checked; if fewer than two answer, or they disagree beyond tolerance, no price is reported and the action blocks rather than being judged against a guess. An ERC-20 still cannot be valued in USD.
  • No position tracking, so no loss accounting. A mandate that sets a daily loss limit blocks with a reason instead of passing a guard that is not there.
  • No constrained signer, so no agent-level enforcement guarantee.
  • One approver. No team roles.

Sandbox

The original in-browser simulator is still available at /lab.html. It runs entirely in your tab, you type the market data yourself, and nothing it produces is authoritative. It is kept because it is a useful way to feel how the rules interact, not because it is part of the product.