Agent trading tools: candles, copy-trading, hire a strategy for your Robinhood vault, pay on chain
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Bearer <your Cubicle key>. Optional: initialize, tools/list, catalogue, plans, strategies and strategy_quote answer without one. A free key: https://cubicle.algotrada.com/deck/join
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
The caller's Cubicle account: their tier (free, Cubicle Operators holder, pro-50, max premium-99), their plan and until when, and every capability with whether it is open and which tier opens it. Call it before telling a trader what they can or cannot do.
This tool takes no arguments.
Tool list last changed Oct 25, 2026.
The caller's Cubicle account: their tier (free, Cubicle Operators holder, pro-50, max premium-99), their plan and until when, and every capability with whether it is open and which tier opens it. Call it before telling a trader what they can or cannot do.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}The whole Cubicle API as data: the studio's eight-state machine and what each gate asks, every tool with the tier that opens it (and whether it is open to the caller), and the flows. Call it first when asked what Cubicle can do.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}The deck's own chart plate for one market, timeframe and window, rendered server-side from the same geometry the screen uses (bars, indicators, the envelope cone when its calibration permits) as a PNG you can look at, together with the chart_state JSON for the same window. The picture is for shape; the numbers are in the JSON — quote those, never read them off the image. Past windows only; at most 600 bars.
| Argument | Type | Description |
|---|---|---|
| tf* | string | timeframe |
| to* | string | window end, ISO-8601 UTC, in the past |
| from* | string | window start, ISO-8601 UTC |
| market* | string | the market |
| indicators | array | indicator ids to draw; defaults to ema20 and envelope |
{
"type": "object",
"required": [
"market",
"tf",
"from",
"to"
],
"properties": {
"tf": {
"enum": [
"15s",
"1m",
"5m",
"1h"
],
"type": "string",
"description": "timeframe"
},
"to": {
"type": "string",
"description": "window end, ISO-8601 UTC, in the past"
},
"from": {
"type": "string",
"description": "window start, ISO-8601 UTC"
},
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market"
},
"indicators": {
"type": "array",
"items": {
"type": "string"
},
"description": "indicator ids to draw; defaults to ema20 and envelope"
}
},
"additionalProperties": false
}What the deck's chart would show for one market, timeframe and window, as ONE JSON object computed in code: the bars (count, first and last, the last candle), the indicators drawn, the trader's own marked levels and zones (theirs — they may be used as levels the trader gave), the envelope under its draw gate and its facts, and the fact sheet of the window (open, close, high, low, range, change, volume, session). Use it instead of reading pixels: every number is measured, not read. Past windows only; at most 600 bars.
| Argument | Type | Description |
|---|---|---|
| tf* | string | timeframe |
| to* | string | window end, ISO-8601 UTC, in the past (the logical clock for a replay) |
| from* | string | window start, ISO-8601 UTC |
| market* | string | the market |
| indicators | array | indicator ids to include, e.g. ["ema20","vwap","envelope"]; defaults to ema20 and envelope |
{
"type": "object",
"required": [
"market",
"tf",
"from",
"to"
],
"properties": {
"tf": {
"enum": [
"15s",
"1m",
"5m",
"1h"
],
"type": "string",
"description": "timeframe"
},
"to": {
"type": "string",
"description": "window end, ISO-8601 UTC, in the past (the logical clock for a replay)"
},
"from": {
"type": "string",
"description": "window start, ISO-8601 UTC"
},
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market"
},
"indicators": {
"type": "array",
"items": {
"type": "string"
},
"description": "indicator ids to include, e.g. [\"ema20\",\"vwap\",\"envelope\"]; defaults to ema20 and envelope"
}
},
"additionalProperties": false
}The house Nemotron desk (llm-nemotron-fest) as it is: its last turn (every 30 minutes), each market's decision and which reader decided it (the vote rule the Nemotron answers, or Jev), the facts it read, and the venue's own positions with realised and unrealised PnL. Composed from the desk's log and the venue, no model asked; a turn older than 45 minutes is marked stale. Not a forecast.
| Argument | Type | Description |
|---|---|---|
| market | string | one market, or every market when absent |
{
"type": "object",
"properties": {
"market": {
"enum": [
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "one market, or every market when absent"
}
},
"additionalProperties": false
}FREE, no key: the sha256 (or keccak256) digest of a text, as 64 hex characters, computed here. Agents, registries and the coordination layer use it to check that this server answers with content they can verify by code; it is also a plain utility. Nothing is stored.
| Argument | Type | Description |
|---|---|---|
| text* | string | the text to hash (UTF-8) |
| algorithm | string | sha256 (default) or keccak256 |
{
"type": "object",
"required": [
"text"
],
"properties": {
"text": {
"type": "string",
"description": "the text to hash (UTF-8)"
},
"algorithm": {
"enum": [
"sha256",
"keccak256"
],
"type": "string",
"description": "sha256 (default) or keccak256"
}
},
"additionalProperties": false
}Draw on the trader's chart, as they ask: a line (two points), a box (two corners), a path (2 to 24 points moving forward in time: a zigzag of legs) or a note (one point and a short word). Every point is a bar's time (ISO-8601 UTC, in the past) and a price the trader gave or the tape tool returned; never invent a level. Inks: parchment, gold, teal, brick (lime is the fire's and is refused). The drawing appears on their chart and in any film of that window.
| Argument | Type | Description |
|---|---|---|
| ink | string | the ink |
| kind* | string | what to draw |
| text | string | a short word beside it (required for a note), at most 48 characters |
| market* | string | the market |
| points* | array | the anchors, earliest first |
{
"type": "object",
"required": [
"market",
"kind",
"points"
],
"properties": {
"ink": {
"enum": [
"parchment",
"gold",
"teal",
"brick"
],
"type": "string",
"description": "the ink"
},
"kind": {
"enum": [
"line",
"box",
"path",
"note"
],
"type": "string",
"description": "what to draw"
},
"text": {
"type": "string",
"description": "a short word beside it (required for a note), at most 48 characters"
},
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market"
},
"points": {
"type": "array",
"items": {
"type": "object",
"required": [
"t",
"p"
],
"properties": {
"p": {
"type": "number",
"description": "the price"
},
"t": {
"type": "string",
"description": "the bar's time, ISO-8601 UTC"
}
},
"additionalProperties": false
},
"maxItems": 24,
"minItems": 1,
"description": "the anchors, earliest first"
}
},
"additionalProperties": false
}The trader's own drawings on one market's chart: lines, boxes, paths and notes, each anchored at bars (UTC times) and prices. They are things the trader drew (or asked you to draw), not signals; a film of the window lets each one appear as the clock reaches it.
| Argument | Type | Description |
|---|---|---|
| market* | string | the market |
{
"type": "object",
"required": [
"market"
],
"properties": {
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market"
}
},
"additionalProperties": false
}Remove one of the trader's drawings by its id (from the drawings tool). Only when they ask.
| Argument | Type | Description |
|---|---|---|
| id* | string | the drawing's id as the drawings tool lists it (sk_ and 16 hex characters) |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "the drawing's id as the drawings tool lists it (sk_ and 16 hex characters)"
}
},
"additionalProperties": false
}Seal a past window of the tape into a FILM: the bars replayed one by one with the trader's drawings and marked levels, optionally the structure computed over the bars (pivots, legs, swings and the range they share, none drawn before the bar that confirmed it) and a rehearsed machine's trades. Returns the film's public link, where it plays and can be downloaded as a video. 24 to 360 bars; the window must be in the past. A film is a replay of what printed: say so, and never present it as a forecast.
| Argument | Type | Description |
|---|---|---|
| tf* | string | timeframe |
| to* | string | window end, ISO-8601 UTC, in the past |
| from* | string | window start, ISO-8601 UTC |
| marks | boolean | include the trader's marked levels (default true) |
| title | string | a short name beside the wordmark |
| kicker | string | a short line at the right, e.g. price → structure |
| market* | string | the market |
| machine | boolean | include the trades of the trader's rehearsed machine on this market, labelled a rehearsal |
Follow a trading model (max plan): creates the follow record — the model, your sizing (fixed_notional usd, or proportional bps of your balance), your caps (max_notional_usd, max_open_positions, max_daily_loss_usd, markets) and optionally the wallet your own runner will sign with. Validated exactly as follow_quote; one active follow per model, a new one supersedes it. Returns the record, its digest (the coordination record follow.created) and the attribution every mirror of it is placed under (copy:<you>:<model>). Nothing is traded by this call: your own runner mirrors fills under this record, and it can be stopped with unfollow at any time.
| Argument | Type | Description |
|---|---|---|
| caps* | object | {"max_notional_usd":100,"max_open_positions":3,"max_daily_loss_usd":40,"markets":["BTC"]} |
| model* | string | the model's attribution from the models tool |
| sizing* | object | {"kind":"fixed_notional","usd":50} or {"kind":"proportional","bps":200} |
| follower_wallet | string | the 0x address your runner signs mirrors with (optional now; required once the venue enforces per-order auth) |
{
"type": "object",
"required": [
"model",
"sizing",
"caps"
],
"properties": {
"caps": {
"type": "object",
"description": "{\"max_notional_usd\":100,\"max_open_positions\":3,\"max_daily_loss_usd\":40,\"markets\":[\"BTC\"]}"
},
"model": {
"type": "string",
"description": "the model's attribution from the models tool"
},
"sizing": {
"type": "object",
"description": "{\"kind\":\"fixed_notional\",\"usd\":50} or {\"kind\":\"proportional\",\"bps\":200}"
},
"follower_wallet": {
"type": "string",
"description": "the 0x address your runner signs mirrors with (optional now; required once the venue enforces per-order auth)"
}
},
"additionalProperties": false
}Quote following a trading model (max plan): checks the model is live and followable, validates the follower's sizing (fixed_notional usd, or proportional bps of their balance) and caps (max_notional_usd, max_open_positions, max_daily_loss_usd, markets the model trades), and shows what one mirror would be at the given balance. Creates nothing and moves nothing.
| Argument | Type | Description |
|---|---|---|
| caps* | object | {"max_notional_usd":100,"max_open_positions":3,"max_daily_loss_usd":40,"markets":["BTC"]} |
| model* | string | the model's attribution from the models tool |
| sizing* | object | {"kind":"fixed_notional","usd":50} or {"kind":"proportional","bps":200} |
| balance_usd | number | the follower's balance, to show a mirror's size (optional) |
{
"type": "object",
"required": [
"model",
"sizing",
"caps"
],
"properties": {
"caps": {
"type": "object",
"description": "{\"max_notional_usd\":100,\"max_open_positions\":3,\"max_daily_loss_usd\":40,\"markets\":[\"BTC\"]}"
},
"model": {
"type": "string",
"description": "the model's attribution from the models tool"
},
"sizing": {
"type": "object",
"description": "{\"kind\":\"fixed_notional\",\"usd\":50} or {\"kind\":\"proportional\",\"bps\":200}"
},
"balance_usd": {
"type": "number",
"description": "the follower's balance, to show a mirror's size (optional)"
}
},
"additionalProperties": false
}Your own follow records (max plan): every follow you created, active, stopped or replaced, with its digest and attribution. Yours only — no follower ever sees another's.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}The envelope the forecast sidecar had issued for one market and timeframe by a given time: a MAGNITUDE band (how far price may travel over the next 24 bars, as two prices and a width in ATR), the odds of a move of 0.5, 1 and 2 ATR within 6, 12 and 24 bars, and its measured calibration (ece, n, band coverage). It carries NO direction — there is no side, no median, and the band is symmetric about the last close by construction; say so, and never turn it into 'up' or 'down'. When calibration reads unmeasured or uncalibrated the deck does not draw it and you should say the band is not yet trusted. Facts only, computed in code; nothing here is a recommendation.
| Argument | Type | Description |
|---|---|---|
| at | string | ISO-8601 UTC time the envelope must have been issued by (defaults to now); for a replay, the logical clock |
| tf* | string | timeframe the sidecar forecasts |
| market* | string | the market |
{
"type": "object",
"required": [
"market",
"tf"
],
"properties": {
"at": {
"type": "string",
"description": "ISO-8601 UTC time the envelope must have been issued by (defaults to now); for a replay, the logical clock"
},
"tf": {
"enum": [
"5m",
"1h"
],
"type": "string",
"description": "timeframe the sidecar forecasts"
},
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market"
}
},
"additionalProperties": false
}The studio machine's FORGED move: compiles the trader's strategy from the gates the tape can measure. The studio refuses it unless the strategy has passed READ, CLARIFIED and EXPRESSIBLE — when refused, tell the trader the move the studio is waiting for (it is in the result).
| Argument | Type | Description |
|---|---|---|
| intent* | string | the rule in the trader's words, every part included |
{
"type": "object",
"required": [
"intent"
],
"properties": {
"intent": {
"type": "string",
"description": "the rule in the trader's words, every part included"
}
},
"additionalProperties": false
}A link to buy USDG on Robinhood Chain with a card, bank transfer or Apple/Google Pay through MoonPay, paid straight into the trader's own wallet (Cubicle never holds the money). Then call onboard again: the next step is funding the vault. Answers plainly when card purchases are not switched on yet.
| Argument | Type | Description |
|---|---|---|
| owner* | string | the 0x address of the trader's wallet on Robinhood Chain |
| amount_usd | number | USD to spend (20 to 10,000; default 100) |
{
"type": "object",
"required": [
"owner"
],
"properties": {
"owner": {
"type": "string",
"description": "the 0x address of the trader's wallet on Robinhood Chain"
},
"amount_usd": {
"type": "number",
"description": "USD to spend (20 to 10,000; default 100)"
}
},
"additionalProperties": false
}Grade a forge with Jev (RUBRIC_v1): code checks the facts first, then Jev answers whether the code does what the trader said. Spends one of the trader's Jev decisions (trial, plan or their own key). It judges fidelity to their words, never profitability.
| Argument | Type | Description |
|---|---|---|
| seed_hash* | string | the seed hash forge returned |
{
"type": "object",
"required": [
"seed_hash"
],
"properties": {
"seed_hash": {
"type": "string",
"description": "the seed hash forge returned"
}
},
"additionalProperties": false
}Look at a chart the trader attached (the id is in the studio state). Read what is on it — instrument, timeframe, levels, the pattern they point at — and say plainly that numbers read off a picture are READ, not measured; check the ones that matter against the tape.
| Argument | Type | Description |
|---|---|---|
| id* | string | the attached image's id |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "the attached image's id"
}
},
"additionalProperties": false
}One trading model's record from the venue's first-in-first-out paired closes: realized PnL, maximum drawdown, win rate, per market, and the window. Always say what the record is not: a forecast, or what a follower would have made.
| Argument | Type | Description |
|---|---|---|
| model* | string | the model's attribution, from the models tool (starts with llm-) |
{
"type": "object",
"required": [
"model"
],
"properties": {
"model": {
"type": "string",
"description": "the model's attribution, from the models tool (starts with llm-)"
}
},
"additionalProperties": false
}The trading LLM models on the Taifoon venue a trader can study and, on the max plan, follow: each with its status (trading or stopped, derived from its last trade), markets, fills, realized PnL and win rate — all read from the venue, never from a model's words. Simulated market-maker and flow actors are never listed.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}The caller's trading vaults, read from the chain: each with whether its funds are devnet (test money) or mainnet (real), what is in it, what is free, what is set aside as margin, the mandate and who administers it.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Where a wallet stands on the way to a funded Cubicle vault, read from the chain (gas, USDG in the wallet, its accounts, the factory's invite gate), and the ONE next step with the tool that does it: connect, add gas, open a vault (vault_prepare), buy USDG with a card (fund_with_card) or send it, fund the vault (vault_prepare), or ready. Also `path`: the account's whole way from join to withdraw in eight steps (join, sign in, second factor, wallets, plan, vault, trade, withdraw), each done, next, later or blocked with the reason, and `path.next_step`. Call it first, and again after every step the trader signs.
| Argument | Type | Description |
|---|---|---|
| chain | number | 4663 Robinhood Chain (real money, the default) or 36927 the devnet (test money) |
| owner | string | the 0x address of the trader's wallet (defaults to the wallet linked to this principal) |
{
"type": "object",
"properties": {
"chain": {
"enum": [
4663,
36927
],
"type": "number",
"description": "4663 Robinhood Chain (real money, the default) or 36927 the devnet (test money)"
},
"owner": {
"type": "string",
"description": "the 0x address of the trader's wallet (defaults to the wallet linked to this principal)"
}
},
"additionalProperties": false
}Make a wallet the venue's payout wallet for this principal (S1 step 4). A name or email join registers the principal under the deck's house wallet, and the venue pays withdrawals ONLY to the principal's operator wallet — so until this step a venue withdrawal cannot reach the person. Call without arguments for the exact message to sign (EIP-191 personal_sign, valid 10 minutes) and its signed_at; then call again with wallet_hex, signed_at and signature_hex. The identity door recovers the signer itself; refused when the signature is stale or foreign, when another principal already operates under that wallet, or when the principal is registered on chain. Behind the second factor.
| Argument | Type | Description |
|---|---|---|
| signed_at | integer | the unix seconds the message carries (from the first call) |
| wallet_hex | string | the wallet to make the payout wallet, 0x + 40 hex |
| signature_hex | string | the wallet's EIP-191 signature over the message, 0x + 130 hex |
{
"type": "object",
"properties": {
"signed_at": {
"type": "integer",
"description": "the unix seconds the message carries (from the first call)"
},
"wallet_hex": {
"type": "string",
"description": "the wallet to make the payout wallet, 0x + 40 hex"
},
"signature_hex": {
"type": "string",
"description": "the wallet's EIP-191 signature over the message, 0x + 130 hex"
}
},
"additionalProperties": false
}Claim a plan you paid for on chain: give the payment's transaction hash and the paying wallet's EIP-191 signature over the exact message the plans tool returns ("Cubicle plan claim\nagent: <your agent id>\ntx: <tx hash>"). The door reads the transfer to the treasury itself and opens the plan for this principal; only the wallet that paid can claim it. Needs your Cubicle key.
| Argument | Type | Description |
|---|---|---|
| chain | string | the chain the payment was made on (Cubicle takes plans on Robinhood Chain only) |
| tx_hash* | string | the payment transaction's hash (0x + 64 hex) |
| payer_signature_hex* | string | the paying wallet's EIP-191 signature (0x + 130 hex) over the claim message |
{
"type": "object",
"required": [
"tx_hash",
"payer_signature_hex"
],
"properties": {
"chain": {
"enum": [
"robinhood"
],
"type": "string",
"description": "the chain the payment was made on (Cubicle takes plans on Robinhood Chain only)"
},
"tx_hash": {
"type": "string",
"description": "the payment transaction's hash (0x + 64 hex)"
},
"payer_signature_hex": {
"type": "string",
"description": "the paying wallet's EIP-191 signature (0x + 130 hex) over the claim message"
}
},
"additionalProperties": false
}The Cubicle plans (price per 30 days, what each includes) and exactly how to pay on Robinhood Chain in USDG: the treasury, the token, and — when the subscription vault is live — the two wallet transactions (approve, subscribe) that renew automatically every 30 days. Nothing here moves money: the trader signs in their own wallet.
| Argument | Type | Description |
|---|---|---|
| plan | string | a plan id (pro-50 or premium-99) to prepare the payment steps for |
| wallet | string | the 0x address of the wallet that will pay — needed for the renewing subscription, which is authorized for that wallet only |
{
"type": "object",
"properties": {
"plan": {
"enum": [
"pro-50",
"premium-99"
],
"type": "string",
"description": "a plan id (pro-50 or premium-99) to prepare the payment steps for"
},
"wallet": {
"type": "string",
"description": "the 0x address of the wallet that will pay — needed for the renewing subscription, which is authorized for that wallet only"
}
},
"additionalProperties": false
}FREE, no key, no sign-in: the tape's latest price for one market (NQ, ES, YM, BTC, ETH or SOL) with the time of that 1-minute close and whether the tape is stale. Use it whenever an agent needs a current price; it is the same tape every Cubicle vault checks its orders against. For a window of candles use tape (needs a key).
| Argument | Type | Description |
|---|---|---|
| symbol* | string | the market, by ticker |
{
"type": "object",
"required": [
"symbol"
],
"properties": {
"symbol": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market, by ticker"
}
},
"additionalProperties": false
}Walk a forged machine over the real tape with the canonical stepper (the last week by default): how many trades it took, the R, and a comparison with a random null. Call it after a forge when the trader wants to know whether the rule actually fires. A rehearsal is evidence about the past, never a forecast.
| Argument | Type | Description |
|---|---|---|
| market | string | the market to walk, defaults to the one the trader named |
| seed_hash* | string | the seed hash forge returned |
{
"type": "object",
"required": [
"seed_hash"
],
"properties": {
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market to walk, defaults to the one the trader named"
},
"seed_hash": {
"type": "string",
"description": "the seed hash forge returned"
}
},
"additionalProperties": false
}Put the trader's chart and its time compressor on a past window: the market, the window, the speed to play it at and, optionally, the moment to hold on (a trade, a sweep, a touch of a level). The studio shows a card; pressing it opens the chart there, held and ready to play, with a way back to the studio. Use it whenever you talk about what happened in a window: show it on the chart instead of only describing it. Past windows only, ten minutes to thirty days; a replay shows what printed, never a forecast.
| Argument | Type | Description |
|---|---|---|
| to* | string | window end, ISO-8601 UTC, in the past |
| from* | string | window start, ISO-8601 UTC |
| note | string | one short sentence shown beside the card: what to watch for (at most 140 characters) |
| focus | string | optional: the moment inside the window to hold the clock at, ISO-8601 UTC |
| speed | string | how fast to play it: 60, 600 or 6000 times real time, or max (default 600) |
| market* | string | the market |
{
"type": "object",
"required": [
"market",
"from",
"to"
],
"properties": {
"to": {
"type": "string",
"description": "window end, ISO-8601 UTC, in the past"
},
"from": {
"type": "string",
"description": "window start, ISO-8601 UTC"
},
"note": {
"type": "string",
"description": "one short sentence shown beside the card: what to watch for (at most 140 characters)"
},
"focus": {
"type": "string",
"description": "optional: the moment inside the window to hold the clock at, ISO-8601 UTC"
},
"speed": {
"enum": [
"60",
"600",
"6000",
"max"
],
"type": "string",
"description": "how fast to play it: 60, 600 or 6000 times real time, or max (default 600)"
},
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market"
}
},
"additionalProperties": false
}Read back what happened in the trader's last replay of one market: every beat on the tape, each of their strategies' trades and state changes, and their own moves (travel, speed, seek), in order with their times, plus the recording's hash (the same at any replay speed). Use it after replay_open, or when the trader asks what they just watched, to answer from what was recorded rather than from memory.
| Argument | Type | Description |
|---|---|---|
| kinds | array | only these sources or kinds (default: all) |
| market* | string | the market |
{
"type": "object",
"required": [
"market"
],
"properties": {
"kinds": {
"type": "array",
"items": {
"enum": [
"tape",
"slot",
"user",
"agent",
"fire",
"gate",
"veto",
"nearmiss",
"settle",
"move"
],
"type": "string"
},
"description": "only these sources or kinds (default: all)"
},
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market"
}
},
"additionalProperties": false
}Reverse-engineer what the trader POSTED before saying anything about it: a rule in words, a pasted Pine script (read statically, never run) or a chat transcript. Returns a dossier: the route (what it is and the first tool), findings each marked observation, inference or unknown with an id (E1, E2) and what would settle each unknown, the checklist (market, bar size, trigger, direction, stop, target, stand aside, numbers match the tape, run over recorded bars) as answered, partial or unresolved, and the ceiling (hypothesis until rehearsed). Cite the ids; never present an inference or an unknown as a fact. For an attached chart use the image tool first.
| Argument | Type | Description |
|---|---|---|
| text* | string | what the trader posted, verbatim: the rule, the Pine source or the transcript |
{
"type": "object",
"required": [
"text"
],
"properties": {
"text": {
"type": "string",
"description": "what the trader posted, verbatim: the rule, the Pine source or the transcript"
}
},
"additionalProperties": false
}Step a cubicle.script v1 over the deck's own bars with the deterministic reference runner (cubicle-script run): one frame per bar (state, every gate's truth and the two sides it compared, fields, vars, position, order, fill, log), the summary (trades, wins, sum R, final state, blocked counts) and the frame hash — the run's receipt. Same script, params and window → the same hash (cached). Window defaults: the previous weekday's cash session (13:30–20:00 UTC) for NQ/ES, the last sealed 8 h for BTC/ETH/SOL; at most 6,000 bars. Pass `script` (YAML) or `example` (bender-corridor, ny-open-breakout, range-aware-stop); `params` replaces defaults within min..max and changes the hash. Metered on the run, not the bars.
| Argument | Type | Description |
|---|---|---|
| tf | string | default 1m |
| to | number | unix seconds (in the past) |
| from | number | unix seconds; with `to`, an explicit sealed window |
| hours | number | crypto only: the last N sealed hours (default 8) |
| frames | number | how many frames to return from the END of the run (default 60, max 600); the summary covers the whole run |
| market | string | default NQ |
| params | object | param overrides {name: number}, clamped to the script's min..max |
Validate a cubicle.script v1 (the YAML text) with the reference validator: the JSON report with every diagnostic (codes C000–C095, file:line:col) and the budget (warm-up bars, memory, nodes per bar). Nothing runs. Free.
| Argument | Type | Description |
|---|---|---|
| script* | string | the cubicle.script v1 YAML text |
{
"type": "object",
"required": [
"script"
],
"properties": {
"script": {
"type": "string",
"description": "the cubicle.script v1 YAML text"
}
},
"additionalProperties": false
}How big to trade the crypto session that is open now (BTC, ETH, SOL): full size when the session is expected to move more than usual, reduced when it should be quiet. Set by Cubicle's house model vol-weekday (trained by the 120B, distilled to the 4B, promoted because it matched the clean room's PROVEN rule on unseen weeks) and checked against that rule in code. A sizing input only, never a direction.
| Argument | Type | Description |
|---|---|---|
| market | string | BTC, ETH or SOL (default: all three) |
{
"type": "object",
"properties": {
"market": {
"enum": [
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "BTC, ETH or SOL (default: all three)"
}
},
"additionalProperties": false
}Read one skill's method (its SKILL.md) — only the methodology and engineering skills are readable; strategy, lens, pillar and copy skills are sealed and will be refused.
| Argument | Type | Description |
|---|---|---|
| name* | string | the skill's name as the skills tool lists it |
{
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "the skill's name as the skills tool lists it"
}
},
"additionalProperties": false
}List the Cubicle skill bank: every skill's name, family, grade and status (runnable / stub / concluded). A stub is a promise, not a capability — say so when you cite one.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}A five-minute proof that the account's owner passed their second factor, for the venue's vault: send it as the x-step-up header of POST /vault/withdraw (api.taifoon.dev/vault/withdraw) with your key. Minted only for an account that has a second factor set up (in the deck, by its owner) and is unlocked right now with agents allowed; a key with no second factor cannot withdraw from the venue at all.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}The strategies anyone can rent to run a Cubicle spot vault (today: accumulate, which buys a fixed amount of ETH or BTC on an interval up to a budget and never sells): what each does, its parameters, the venues and assets, the limits the vault itself enforces, the fee, how to rent it, and its honest status (not live with real funds yet).
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}A live quote for one accumulate buy on Robinhood Chain: what a USD amount of USDG buys of ETH or BTC on the best Uniswap route right now, the tape's price, the cost against the tape in bps, and whether the vault's own price rule (at most 1% worse than the tape) would accept it. A static call: nothing is signed or sent.
| Argument | Type | Description |
|---|---|---|
| usd* | number | USD of USDG to spend |
| asset* | string | the asset |
{
"type": "object",
"required": [
"asset",
"usd"
],
"properties": {
"usd": {
"type": "number",
"description": "USD of USDG to spend"
},
"asset": {
"enum": [
"ETH",
"BTC"
],
"type": "string",
"description": "the asset"
}
},
"additionalProperties": false
}The steps the trader's last tested strategy took on one market, as the test engine reported them: each step's time, the move (ready to in a trade, and so on), the conditions true at that bar, the trade it opened or closed, and the watched items' values at that bar. Also, per watched item, its average at the entries of winning trades and of losing trades. Use it to answer 'what was the RSI when it bought', 'why did it enter there', 'what do the winners have in common'. These are past bars of one tested week: a description, never a forecast and never advice.
| Argument | Type | Description |
|---|---|---|
| only | string | trades = only the steps that opened or closed a trade (default); all = every step |
| market | string | the market the strategy was tested on (defaults to the newest test) |
{
"type": "object",
"properties": {
"only": {
"enum": [
"trades",
"all"
],
"type": "string",
"description": "trades = only the steps that opened or closed a trade (default); all = every step"
},
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market the strategy was tested on (defaults to the newest test)"
}
},
"additionalProperties": false
}Cubicle's paid signal stream on the Taifoon coordination layer (pro-50 or premium-99): the desks' world-clock signals and Kronos forecasts arrive as kind signal from venue cubicle, sealed with a topic key per UTC day. Register your X25519 PUBLIC key (make a pair with `npx -y @taifoon-io/sdk coord keygen --out FILE`; the secret never leaves your machine) and the day's keys are sealed to it on the stream; you get your holder id, the stream URL and the one SDK command that prints the signals decoded. Call again to have today's keys re-sent; action forget stops it. Ticks and outcomes are public; anyone without a key sees the signal bodies as ciphertext.
| Argument | Type | Description |
|---|---|---|
| action | string | register (default: register or refresh your key), status (what is registered, nothing changes) or forget (remove your key) |
| x25519 | string | your X25519 public key: 0x and 64 hex characters (needed for register) |
{
"type": "object",
"properties": {
"action": {
"enum": [
"register",
"status",
"forget"
],
"type": "string",
"description": "register (default: register or refresh your key), status (what is registered, nothing changes) or forget (remove your key)"
},
"x25519": {
"type": "string",
"description": "your X25519 public key: 0x and 64 hex characters (needed for register)"
}
},
"additionalProperties": false
}Move the trader's rule through the studio's state machine when forge is refused: score_parts (Jev scores clarity — needs the trader's own TypeSafe key), accept_parts (the trader accepts the rule as read, without a Jev score), choose_coverage with choice approximate (build from the gates the tape can measure) or stop, reset (start over). Ask the trader before accepting or choosing for them; the studio decides every gate, this only performs the move they chose.
| Argument | Type | Description |
|---|---|---|
| move* | string | the move |
| choice | string | for choose_coverage: approximate or stop |
{
"type": "object",
"required": [
"move"
],
"properties": {
"move": {
"enum": [
"score_parts",
"accept_parts",
"choose_coverage",
"reset"
],
"type": "string",
"description": "the move"
},
"choice": {
"enum": [
"approximate",
"stop"
],
"type": "string",
"description": "for choose_coverage: approximate or stop"
}
},
"additionalProperties": false
}Read real candles from the Taifoon tape for one market. Use it to ground an answer in what the market actually did in a past window — never to predict. NQ is not continuous (weekend halt, 21:00 UTC daily break). A past window is SEALED: its bars never change, so cache it. The same tape is open over plain HTTP with no key: GET https://clob.taifoon.dev/tape/v1/candles/{market}/{tf}?from=&to= with unix SECONDS and a User-Agent that names you (OpenAPI: https://www.taifoon.io/clob/openapi.yaml). It is the tape the coordination layer's conformance check replays, so what you read here is what the judge reads.
| Argument | Type | Description |
|---|---|---|
| tf* | string | timeframe (the time machine serves these; build a 15-minute range from 1m or 5m bars) |
| to* | string | window end, ISO-8601 UTC, in the past |
| from* | string | window start, ISO-8601 UTC |
| market* | string | the market |
{
"type": "object",
"required": [
"market",
"tf",
"from",
"to"
],
"properties": {
"tf": {
"enum": [
"15s",
"1m",
"5m",
"1h"
],
"type": "string",
"description": "timeframe (the time machine serves these; build a 15-minute range from 1m or 5m bars)"
},
"to": {
"type": "string",
"description": "window end, ISO-8601 UTC, in the past"
},
"from": {
"type": "string",
"description": "window start, ISO-8601 UTC"
},
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market"
}
},
"additionalProperties": false
}Stop following a model at once (any tier may stop): the active follow record is marked stopped and kept; open mirror positions stay yours to manage. Returns the stopped record, or says there was none.
| Argument | Type | Description |
|---|---|---|
| model* | string | the model's attribution |
{
"type": "object",
"required": [
"model"
],
"properties": {
"model": {
"type": "string",
"description": "the model's attribution"
}
},
"additionalProperties": false
}The wallet steps for a Cubicle vault as UNSIGNED transactions and EIP-712 typed data for the owner's own wallet. Open: call without vault for the transaction that opens it. Fund and hire: call again with the new vault's address (from my_vaults) for allow + deposit and the mandate to sign. Withdraw: withdraw_shares queues shares, then claim_shares pays what the vault's free funds cover to the owner. Chain 4663 is Robinhood Chain (real USDG; open to any wallet since 2026-10-07, no deposit cap; the contracts are not externally audited, so deposit only what you can afford to lose); 36927 is the devnet (test money). Signs and sends nothing.
| Argument | Type | Description |
|---|---|---|
| kind | string | what the account is for: spot (trades on Uniswap today) or futures (margin; settles when the venue sends statements) |
| name | string | a name for the vault |
| chain | number | 4663 Robinhood Chain (real money) or 36927 the devnet (test money); defaults to the devnet |
| owner* | string | the 0x address of the wallet that owns (or will own) the vault |
| vault | string | the vault's 0x address (every call after the first) |
| market | string | spot administrators only: the market it buys |
| margin_usd | number | margin vaults only: the most the mandate may ever lose (second call) |
What a strategy test reports at every step the strategy takes: the trader's current list, and the whole vocabulary, grouped by indicator (price, volume, RSI 14, EMA 20, EMA 60, VWAP, the Bollinger bands, the 20 bar range, bar size, the 50 bar mean, the clock). Each indicator has named fields (the bands have boll_up and boll_dn, the range has range_high, range_low and range_pos). An item may also be an expression over the fields, such as close - ema20 or rsi14 > 50. Call it before watch_set, and when the trader asks what can be tracked.
No arguments.
{
"type": "object",
"properties": {},
"additionalProperties": false
}Set what the trader's strategy tests report at every step: up to 8 items, each a field id from watch_fields or an expression over those fields (numbers, + - * / and brackets, optionally one comparison with < > <= >=). This replaces the list. It applies to the NEXT test, so offer to rehearse again afterwards. An item that cannot be read is refused by name and the rest are kept. Use it when the trader says what they want tracked ('watch the RSI and how far price is from the EMA'): translate their words into fields; never invent a field.
| Argument | Type | Description |
|---|---|---|
| items* | array | field ids or expressions, in the order they should be shown |
{
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 8,
"minItems": 0,
"description": "field ids or expressions, in the order they should be shown"
}
},
"additionalProperties": false
}The weather over a market: the tone the last 72 h of news headlines set (each headline tagged up, down or flat by Cubicle's house model; the tone and its band are computed in code from those tags, recency-weighted), the headlines themselves with their times and links, the tape's regime (trend, drift or chop by the efficiency ratio of the last 48 five-minute closes) and one word for the sky (clear, crosswind, overcast, fog). Refreshed every half hour. A mood, never a forecast or a direction to trade; social feeds are not read and the result says so.
| Argument | Type | Description |
|---|---|---|
| market | string | the market (default: all six) |
{
"type": "object",
"properties": {
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market (default: all six)"
}
},
"additionalProperties": false
}Read a trading idea the way the studio does: the deterministic reader fills the 7 parts (markets, trigger, direction, stand aside, stop, target, session) from the trader's OWN words and says which required parts are still missing. Use it before restating or forging a rule; never fill a part the trader did not say.
| Argument | Type | Description |
|---|---|---|
| text* | string | everything the trader has said about the rule, in their words |
{
"type": "object",
"required": [
"text"
],
"properties": {
"text": {
"type": "string",
"description": "everything the trader has said about the rule, in their words"
}
},
"additionalProperties": false
}| palette | string | the inks |
| seconds | number | length, 8 to 40 seconds (default 18) |
| drawings | boolean | include the trader's drawings (default true) |
| headline | string | the headline's first part (drawn in parchment), at most 44 characters |
| structure | boolean | draw the computed structure and name the chapters after it |
| headline_gold | string | the headline's second part (drawn in gold) |
{
"type": "object",
"required": [
"market",
"tf",
"from",
"to"
],
"properties": {
"tf": {
"enum": [
"15s",
"1m",
"5m",
"1h"
],
"type": "string",
"description": "timeframe"
},
"to": {
"type": "string",
"description": "window end, ISO-8601 UTC, in the past"
},
"from": {
"type": "string",
"description": "window start, ISO-8601 UTC"
},
"marks": {
"type": "boolean",
"description": "include the trader's marked levels (default true)"
},
"title": {
"type": "string",
"description": "a short name beside the wordmark"
},
"kicker": {
"type": "string",
"description": "a short line at the right, e.g. price → structure"
},
"market": {
"enum": [
"NQ",
"ES",
"YM",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "the market"
},
"machine": {
"type": "boolean",
"description": "include the trades of the trader's rehearsed machine on this market, labelled a rehearsal"
},
"palette": {
"enum": [
"house",
"engraving",
"tide"
],
"type": "string",
"description": "the inks"
},
"seconds": {
"type": "number",
"description": "length, 8 to 40 seconds (default 18)"
},
"drawings": {
"type": "boolean",
"description": "include the trader's drawings (default true)"
},
"headline": {
"type": "string",
"description": "the headline's first part (drawn in parchment), at most 44 characters"
},
"structure": {
"type": "boolean",
"description": "draw the computed structure and name the chapters after it"
},
"headline_gold": {
"type": "string",
"description": "the headline's second part (drawn in gold)"
}
},
"additionalProperties": false
}| script | string | the cubicle.script v1 YAML text (or use example) |
| example | string | a bundled example instead of script: bender-corridor | ny-open-breakout | range-aware-stop |
{
"type": "object",
"properties": {
"tf": {
"enum": [
"15s",
"1m",
"5m",
"1h"
],
"type": "string",
"description": "default 1m"
},
"to": {
"type": "number",
"description": "unix seconds (in the past)"
},
"from": {
"type": "number",
"description": "unix seconds; with `to`, an explicit sealed window"
},
"hours": {
"type": "number",
"description": "crypto only: the last N sealed hours (default 8)"
},
"frames": {
"type": "number",
"description": "how many frames to return from the END of the run (default 60, max 600); the summary covers the whole run"
},
"market": {
"enum": [
"NQ",
"ES",
"BTC",
"ETH",
"SOL"
],
"type": "string",
"description": "default NQ"
},
"params": {
"type": "object",
"description": "param overrides {name: number}, clamped to the script's min..max",
"additionalProperties": {
"type": "number"
}
},
"script": {
"type": "string",
"description": "the cubicle.script v1 YAML text (or use example)"
},
"example": {
"type": "string",
"description": "a bundled example instead of script: bender-corridor | ny-open-breakout | range-aware-stop"
}
},
"additionalProperties": false
}| deposit_usd | number | USD of the stable to deposit (second call) |
| claim_shares | string | withdrawal step two: whole shares to claim (read claimableRedeemRequest(0, owner) on the vault) |
| administrator | string | who administers the vault under the mandate (second call), e.g. llm-nemotron-dual |
| withdraw_shares | string | withdrawal step one: whole shares to queue (read balanceOf(owner) on the vault) |
{
"type": "object",
"required": [
"owner"
],
"properties": {
"kind": {
"enum": [
"spot",
"futures",
"funding"
],
"type": "string",
"description": "what the account is for: spot (trades on Uniswap today) or futures (margin; settles when the venue sends statements)"
},
"name": {
"type": "string",
"description": "a name for the vault"
},
"chain": {
"enum": [
4663,
36927
],
"type": "number",
"description": "4663 Robinhood Chain (real money) or 36927 the devnet (test money); defaults to the devnet"
},
"owner": {
"type": "string",
"description": "the 0x address of the wallet that owns (or will own) the vault"
},
"vault": {
"type": "string",
"description": "the vault's 0x address (every call after the first)"
},
"market": {
"enum": [
"ETH",
"BTC"
],
"type": "string",
"description": "spot administrators only: the market it buys"
},
"margin_usd": {
"type": "number",
"description": "margin vaults only: the most the mandate may ever lose (second call)"
},
"deposit_usd": {
"type": "number",
"description": "USD of the stable to deposit (second call)"
},
"claim_shares": {
"type": "string",
"description": "withdrawal step two: whole shares to claim (read claimableRedeemRequest(0, owner) on the vault)"
},
"administrator": {
"type": "string",
"description": "who administers the vault under the mandate (second call), e.g. llm-nemotron-dual"
},
"withdraw_shares": {
"type": "string",
"description": "withdrawal step one: whole shares to queue (read balanceOf(owner) on the vault)"
}
},
"additionalProperties": false
}