changedInput schema / properties / edges / description
Previous value: -"Directed edges between node ids. A plain {from, to} is a data edge; add `guard` to make it a CONDITIONAL route (stateful_graph loops: 'revise until good' = critique → revise guarded on the verdict, plus an exit edge)."New value: +"Directed edges; add `guard` for a conditional route."
removedInput schema / properties / edges / items / properties / from / description
Removed value: -"Source node id"
changedInput schema / properties / edges / items / properties / guard / description
Previous value: -"Take this edge ONLY when the condition holds — {source, op, value?}. `source` is a `{{node.port}}` channel ref (e.g. '{{critique.out}}'); `op` is eq | not_eq | contains | gt | gte | lt | lte | truthy | exists (a bounded interpreter, never eval). e.g. {\"source\": \"{{critique.out}}\", \"op\": \"contains\", \"value\": \"REVISE\"}."New value: +"{source: a `{{node.port}}` ref, op: eq | not_eq | contains | gt | gte | lt | lte | truthy | exists, value?}."
removedInput schema / properties / edges / items / properties / guard / properties
Removed value: -{
- "op": {
- "enum": [
- "eq",
- "not_eq",
- "contains",
- "gt",
- "gte",
- "lt",
- "lte",
- "truthy",
- "exists"
- ],
- "type": "string"
- },
- "source": {
- "type": "string"
- },
- "value": {}
-}
removedInput schema / properties / edges / items / properties / guard / required
Removed value: -[
- "source",
- "op"
-]
removedInput schema / properties / edges / items / properties / kind
Removed value: -{
- "description": "'data' (default) | 'control' | 'conditional' (implied when guard is set)",
- "enum": [
- "data",
- "control",
- "conditional"
- ],
- "type": "string"
-}
removedInput schema / properties / edges / items / properties / to / description
Removed value: -"Destination node id"
changedInput schema / properties / input / description
Previous value: -"WHAT THIS RIG ASKS ITS RUNNER FOR — the labelled input box the Builder canvas and the rig's product page render, and the value that fills every `{{input}}` placeholder at run time. Pass a plain string (the label) or {label, kind?, hint?, required?, multiple?} — kind is text (default) | number | boolean | date | url | email | file | document | markdown | code | image | audio | video | data | table | list | contact | location | secret | embedding | skill | harness | rig | any. The LISTING kinds (skill/harness/rig) mean the value is a PICKED registry listing — the Explore/Audit shape. DECLARE IT whenever the flow works on something the user supplies: without it the rig saves with no input box and only works when something passes `input` to rig_run. e.g. {\"label\": \"token address\", \"kind\": \"text\", \"hint\": \"0x… on chain 4663\"}."New value: +"What the rig asks its runner for; fills `{{input}}`."
removedInput schema / properties / inputs
Removed value: -{
- "description": "ADDITIONAL input ports beyond `input` (or the full list on their own) — same shapes as `input`. The FIRST input fills `{{input}}`; a multi-input rig renders one labelled box per port.",
- "items": {
- "type": [
- "string",
- "object"
- ]
- },
- "type": "array"
-}
changedInput schema / properties / key / description
Previous value: -"Rig storage key — EACH DISTINCT KEY IS ITS OWN SAVED RIG (default 'agent-rig' = the Working Rig; use a fresh kebab key per additional rig, e.g. 'news-digest')"New value: +"Storage key; each distinct kebab-case key is its own saved rig (default 'agent-rig')."
changedInput schema / properties / name / description
Previous value: -"THE RIG'S NAME — the Builder's header box, which gates BOTH Save and ▶ Run for a human. Defaults to `summary` so the rig is always nameable; pass a short product-style name ('X Sentiment Digest') when you have one."New value: +"The rig's name; gates Save and Run for a human."
changedInput schema / properties / nodes / description
Previous value: -"Graph nodes. Each is one step."New value: +"The steps. Rarer fields (label, agent, model_policy, headers, data_type, doc_input, expects, produces, inputs, pos, state) are in the full reference."
removedInput schema / properties / nodes / items / properties / agent
Removed value: -{
- "description": "The step's ACTOR — a Forge agent's handle (see /api/agents/available). ANY step kind takes one, and the step then runs AS that agent: an instruction or prompt-shaped skill step speaks in its persona (frame, bio, creator harnesses, voice); an `endpoint`+`tool` or `url` step is PERFORMED by it — the bound call becomes the agent's one tool, it calls it and writes the step's output (without an actor the call stays deterministic); sandbox, decision (Jev) and platform-rail steps carry its name only. Several agents across one rig are fine — each step resolves its own. The RUNNER pays (the agent lends its persona + locked-model preference, never its owner's keys or its allowance; a locked model the runner can't pay for runs on the lane default, said out loud). Authorized at RUN time against the RUNNER — their own agent always works, someone else's only while public; a private/missing actor is a typed agent_unavailable error on that step only. Empty = Rokha performs the step, as always.",
- "type": "string"
-}
changedInput schema / properties / nodes / items / properties / data_key / description
Previous value: -"The DATA collection key (data_op steps only). `{{input}}` templates the run input. The runtime FORCES the `data.` prefix and blocks any reach at system harnesses (profile/chat/keys) — e.g. 'data.x-signals.{{input}}'"New value: +"The memory collection."
changedInput schema / properties / nodes / items / properties / data_op / description
Previous value: -"Makes this a DATA step — durable, owner-scoped cross-rig memory. 'write' overwrites, 'append' accumulates across runs, 'read' loads a stored collection into the flow. Writes are PRIVATE by default (never in the public pulse, not forkable). This is how one rig persists a collection a LATER rig reads."New value: +"A durable, owner-scoped memory step on data_key."
removedInput schema / properties / nodes / items / properties / data_type
Removed value: -{
- "description": "The harness_type a data write lands as (default 'knowledge'); one of knowledge/strategy/preference/persona/compliance",
- "enum": [
- "knowledge",
- "strategy",
- "preference",
- "persona",
- "compliance"
- ],
- "type": "string"
-}
removedInput schema / properties / nodes / items / properties / doc_input
Removed value: -{
- "description": "true = LIGHT LISTING step: read this skill's real registry listing + document and hand it forward (no execution, no runtime needed)",
- "type": "boolean"
-}
changedInput schema / properties / nodes / items / properties / endpoint / description
Previous value: -"Live MCP JSON-RPC endpoint URL — the run performs a REAL tools/call here (optional; empty = agentic step)"New value: +"MCP JSON-RPC URL for a real tools/call."
removedInput schema / properties / nodes / items / properties / expects
Removed value: -{
- "description": "What this step EXPECTS from upstream, in plain words ('a list of post URLs') — the step's I/O story, shown on the canvas and carried into the published skeleton",
- "type": "string"
-}
removedInput schema / properties / nodes / items / properties / headers
Removed value: -{
- "description": "Extra HTTP headers for a `url` fetch (string→string). Combine with secret_refs to inject a key: {\"Authorization\": \"Bearer {{secret:my-api-key}}\"}.",
- "type": "object"
-}
changedInput schema / properties / nodes / items / properties / id / description
Previous value: -"Stable node id used by edges (e.g. 'draft', 'a')"New value: +"Stable id edges refer to."
removedInput schema / properties / nodes / items / properties / inputs
Removed value: -{
- "description": "PER-NODE input ports — the labelled landing slots a multi-parent (fan-in) edge binds to. Same shapes as the rig-level `input`.",
- "items": {
- "type": [
- "string",
- "object"
- ]
- },
- "type": "array"
-}
changedInput schema / properties / nodes / items / properties / instruction / description
Previous value: -"Per-step instruction for the agent (optional)"New value: +"What this step must do."
removedInput schema / properties / nodes / items / properties / label
Removed value: -{
- "description": "Display label (optional; defaults to the skill)",
- "type": "string"
-}
removedInput schema / properties / nodes / items / properties / method / description
Removed value: -"HTTP method for a `url` fetch: GET (default) or POST"
changedInput schema / properties / nodes / items / properties / model / description
Previous value: -"Optional Anthropic model id to pin for this step's agentic execution (e.g. 'claude-sonnet-4-6'). Non-Haiku models need the owner's own API key; without one, 'preferred' swaps to Haiku and 'required' refuses the step"New value: +"Pin a model id; non-Haiku needs the owner's key."
removedInput schema / properties / nodes / items / properties / model_policy
Removed value: -{
- "description": "'preferred' (default — swap to the best usable model when the pin isn't available) or 'required' (the step refuses to run without its model, typed model_unavailable)",
- "enum": [
- "preferred",
- "required"
- ],
- "type": "string"
-}
changedInput schema / properties / nodes / items / properties / params / description
Previous value: -"Arguments for the live tool call, or a plain-HTTP fetch's query/body params (optional). USE `{{input}}` ANYWHERE IN A VALUE to thread what the runner typed — {\"address\": \"{{input}}\"} is how a param comes from user input. `{{secret:<alias>}}` injects one of their saved keys (see secret_refs)."New value: +"Call or fetch arguments; `{{input}}`, `{{upstream.<field>}}` and `{{secret:<alias>}}` template inside values."
removedInput schema / properties / nodes / items / properties / pos
Removed value: -{
- "description": "Explicit canvas position {x, y} (optional — omitted nodes are auto-laid by topological layer, parallel branches side by side)",
- "properties": {
- "x": {
- "type": "number"
- },
- "y": {
- "type": "number"
- }
- },
- "type": "object"
-}
removedInput schema / properties / nodes / items / properties / produces
Removed value: -{
- "description": "What this step PRODUCES for downstream ('a sentiment table') — same story, output side",
- "type": "string"
-}
changedInput schema / properties / nodes / items / properties / questions / description
Previous value: -"Makes this a DECISION step (the Jev decision model): typed questions answered with calibrated probabilities — no prose, no tools. Shape: {<id>: {type: 'noul' (yes/no → answers.<id>.noul = p) | 'choice' (pick one of named criteria → answers.<id>.choice + confidence + probabilities) | 'score' (ordinal over a criteria LIST → answers.<id>.score + confidence), instructions, criteria}}. Route on it with a guard, e.g. {source:'{{decide.answers.enter.noul}}', op:'gte', value:0.7}. USE for gates, routing, classification, scoring, trade entry/exit calls; NEVER for anything that writes words or uses tools."New value: +"A DECISION step: {<id>: {type: 'noul' | 'choice' | 'score', instructions, criteria}} answered with probabilities; route on it with an edge guard such as {source: '{{decide.answers.enter.noul}}', op: 'gte', value: 0.7}."
changedInput schema / properties / nodes / items / properties / secret_refs / description
Previous value: -"ATTACH THE RUNNER'S OWN SAVED KEYS to this step — the only way a rig calls an API that needs credentials. Each item {alias, as?}: `alias` is a key the user saved in Profile → API KEYS (or a connect alias like 'oauth-x' / 'mcp-<host>'); `as` binds HOW it lands — `param:<key>` (a tools/call argument), `header:<Name>[:<prefix>]` (e.g. 'header:Authorization:Bearer ' — the trailing space is meaningful), or omit `as` and put {{secret:<alias>}} inside any param/header value. The VALUE is resolved server-side at the call and never appears in params, traces, or the published listing — so a published rig is safe to share and each RUNNER supplies their own key."New value: +"The runner's saved keys this step may use: [{alias, as?}]."
removedInput schema / properties / nodes / items / properties / secret_refs / items
Removed value: -{
- "properties": {
- "alias": {
- "type": "string"
- },
- "as": {
- "type": "string"
- }
- },
- "required": [
- "alias"
- ],
- "type": "object"
-}
changedInput schema / properties / nodes / items / properties / signet_action / description
Previous value: -"What the Signet step does. WRITES (move value, need a mandate + target + value): 'pay'/'transfer' (send SOL or an SPL token), 'swap' (trade via Jupiter), 'x402' (BUY a paid HTTP resource — signet_target = the resource URL, signet_value = your USDC ceiling in base units; Signet does the 402→pay→retry and returns the content). READS (no mandate, no value moved, safe on any step): 'metrics' (stage-shaped budgets/counts/spend for this actor — point a STAGE dashboard at this step), 'mandates' (is a mandate ready for this actor?), 'portfolio' (SOL + SPL balances; `signet_target` optionally names an address), 'price' (a live quote; `signet_target` = mint, `signet_value` = amount). PAPER (no mandate, no actor, NO money moves — real Jupiter quotes, a recorded ledger on the runner's account; output carries paper:true): 'wallet_activity' (a wallet's recent swaps; `signet_target` = the wallet, `signet_value` = limit) · 'paper_positions' / 'paper_reset' (`signet_target` = ledger name) · 'paper_buy' / 'paper_sell' (`signet_target` = ledger; the fills come from the previous step's JSON `buys` / `sells` list; `signet_value` = the default USD per buy or the sell fraction; a paper_buy step passes `sells` through for a following paper_sell). Defaults to 'pay' — the narrowest action — rather than guessing a wider one."New value: +"Writes move value under the mandate; metrics, mandates, portfolio and price read; paper_* record a paper ledger. Default pay."
changedInput schema / properties / nodes / items / properties / signet_actor / description
Previous value: -"Makes this a SIGNET step — the rig acts with VALUE under a mandate the RUNNER already granted to this actor (e.g. `rig:trader`). The step carries NO credentials: no key, no mandate id, no address. The rail resolves (runner, actor) -> mandate, so a published or forked rig carries the strategy and none of the authority — run someone else's copy and it spends THEIR OWN mandate or refuses. If no mandate exists for the actor, the step refuses and names the fix."New value: +"A Signet step under the RUNNER's mandate to this actor, e.g. 'rig:trader'; no credentials in the rig."
changedInput schema / properties / nodes / items / properties / signet_target / description
Previous value: -"Destination address (pay/transfer), the mint to trade into (swap), an address (portfolio) or the mint to price (price). For a WRITE it MUST be on the mandate's allowlist or the rail refuses. Templating: `{{input}}` is the run input and `{{upstream.<field>}}` reads the previous step's output. Not needed for 'metrics' or 'mandates'."New value: +"Address, mint, wallet or paper ledger name; templates allowed."
changedInput schema / properties / nodes / items / properties / signet_value / description
Previous value: -"Amount in BASE units — lamports for SOL, the mint's base units for an SPL token. Never a decimal. Templating: `{{input}}` is the run input, and `{{upstream.<field>}}` reads the PREVIOUS step's output — which is how a decided position size actually reaches the trade (`{{upstream.size_lamports}}`). Hard-coding an amount in a rig whose earlier step computes one is a bug: the strategy's sizing is then calculated and discarded. If the reference does not resolve, the field is EMPTY and the step refuses — a trade sized by a leftover constant is a trade nobody decided. Not needed for a read action."New value: +"Amount in base units, never a decimal; `{{upstream.<field>}}` sizes it."
changedInput schema / properties / nodes / items / properties / skill / description
Previous value: -"Registry skill name to bind this step to (discover via registry_search)"New value: +"Registry skill to bind (registry_search)."
removedInput schema / properties / nodes / items / properties / state
Removed value: -{
- "description": "DECISION step only: what to decide about — a template reading {{input}} and {{upstream.<field>}}; empty = the upstream output.",
- "type": "string"
-}
changedInput schema / properties / nodes / items / properties / sub_rig / description
Previous value: -"Make this node a SUB-RIG step — the referenced SAVED rig runs here as a bounded sub-run (one level deep; runner-pays, shared budget, traces nested under this node). Pass {rig_id, name?} or a bare rig-id string (rig_search finds ids). Mutually exclusive with `skill`. ⚠ the canvas renders it as a labeled ⬡ block; its INNER edits go through you."New value: +"A saved rig id to run here as a sub-run."
changedInput schema / properties / nodes / items / properties / tool / description
Previous value: -"Tool name to invoke on the endpoint (optional)"New value: +"Tool name on that endpoint."
changedInput schema / properties / nodes / items / properties / url / description
Previous value: -"Plain-HTTP fetch target — the run performs a REAL HTTP request here via the SSRF-guarded proxy (optional; use with method + params + headers + secret_refs). `{{input}}` substitutes into the PATH or QUERY too (e.g. 'https://api.example.com/tokens/{{input}}'); the host stays fixed."New value: +"HTTP fetch target; `{{input}}` may sit in the path or query."
changedInput schema / properties / outputs / description
Previous value: -"What the rig DECLARES IT PRODUCES — the contract's output side, shown on the canvas Output box and the product page. Same shapes as `input` (required is input-only). e.g. [{\"label\": \"the audit report\", \"kind\": \"markdown\"}]."New value: +"What the rig declares it produces."
removedInput schema / properties / outputs / items
Removed value: -{
- "type": [
- "string",
- "object"
- ]
-}
changedInput schema / properties / requirements / description
Previous value: -"MODEL + AGENT REQUIREMENTS a runner (and an agent hired for this rig) must meet — {model?: {exact?: '<model id>' | allowed?: ['<id>', …] (≤8) , min_tier?: 'haiku'|'sonnet'|'opus'}, agent?: {tools?: ['<tool>', …] (≤32), kit?: '<kit>'}}. exact OR allowed, not both; every id must be a model the platform knows (the model picker's ids). A hired agent qualifies and is priced ON the required model, and the price floor follows that model's cost. e.g. {\"model\": {\"exact\": \"claude-opus-5-5\"}}."New value: +"{model?: {exact | allowed[] | min_tier}, agent?: {kit, tools[]}} a runner must meet."
removedInput schema / properties / requirements / properties
Removed value: -{
- "agent": {
- "properties": {
- "kit": {
- "type": "string"
- },
- "tools": {
- "items": {
- "type": "string"
- },
- "type": "array"
- }
- },
- "type": "object"
- },
- "model": {
- "properties": {
- "allowed": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "exact": {
- "type": "string"
- },
- "min_tier": {
- "enum": [
- "haiku",
- "sonnet",
- "opus"
- ],
- "type": "string"
- }
- },
- "type": "object"
- }
-}
removedInput schema / properties / state
Removed value: -{
- "description": "SHARED STATE CHANNELS (stateful_graph) — named channels loop iterations read/write via `{{node.port}}` refs; `reducer` merges concurrent fan-out writes: 'last_write' (default) | 'append' | 'add'. Each {id, kind?, reducer?}.",
- "items": {
- "properties": {
- "id": {
- "type": "string"
- },
- "kind": {
- "type": "string"
- },
- "reducer": {
- "enum": [
- "last_write",
- "append",
- "add"
- ],
- "type": "string"
- }
- },
- "required": [
- "id"
- ],
- "type": "object"
- },
- "type": "array"
-}
changedInput schema / properties / structure_type / description
Previous value: -"'linear' (a simple chain — what the guided Builder produces), 'dag' (default; acyclic, parallel branches + real fan-in) or 'stateful_graph' (cyclic loops + conditional edge guards — the runtime evaluates guards and skips unfired branches for real; the Builder CANVAS can't edit it yet, so tell the owner edits go through you)"New value: +"linear = a chain; dag (default) = branches and fan-in; stateful_graph = loops with guards."
changedInput schema / properties / summary / description
Previous value: -"Short human description of the flow (shows as the rig's name)"New value: +"One line on what the flow does."
removedInput schema / properties / wallet_address
Removed value: -{
- "description": "Wallet address that owns the rig (the scope the run reads)",
- "type": "string"
-}
changedInput schema / required
Previous value: -[
- "wallet_address",
- "nodes"
-]New value: +[
+ "nodes"
+]