Decision Branch Node
Applies to: ChengOS v0.2.0+ | Last verified: 2026-09-25 | Source:
crates/cheng-nodes/src/nodes/builtin/ai/decision_branch.rs,config/decision_providers.toml,config/decision_calibration.toml
ai/decision_branch routes a conversation turn to exactly one of the routes you declare, using a
typed decision provider rather than a chat model: TypeSafe Jev (hosted, calibrated
probabilities), Laya (a local model the operator runs), or a connected LLM as an uncalibrated
baseline. The provider sees only the latest request, the route descriptions, the routing
instruction, and in sticky mode the previous route ID — never history, tools, or credentials.
The context itself is delivered unchanged to route_<id>; anything ordinary, ambiguous,
multi-intent, low-confidence, or failed goes to fallback_out, so a misroute or an outage
degrades to what the workflow did without the router. Authoring guidance, thresholds, and the
two-stage cascade are in Semantic Routing; provider setup is in
Decision Providers & TypeSafe Jev.
Decision Branch — ai/decision_branch
Route the request to exactly one declared route with a typed decision model (Jev or an LLM baseline); anything unclear goes to fallback_out with the context unchanged
Inputs
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
context | object (port) | — | null | Input AgentContext; the latest user request is routed and the context is delivered unchanged. Connection port, not a form field. Control: code-editor |
provider | enum | — | jev | Jev: hosted typed decision model (the routed request is sent to TypeSafe). LLM: a connected chat model as an uncalibrated baseline. Laya: the installation's own local model, when the operator has enabled it (at most 15 routes; uncalibrated unless the operator pins the served artifact). Control: select. Options: jev (TypeSafe Jev (hosted; calibrated probabilities).), llm (A connected chat model with constrained output (uncalibrated).), laya (The installation's own Laya deployment (local; enabled by the operator).) |
credential_id | string | — | null | TypeSafe Jev credential. Leave empty to use the deployment's JEV_API_KEY, if configured. Control: credential-select |
decision_model | string | — | "" | Decision model; empty uses the credential's pin, then the provider default. Wins over the legacy jev_model when set. Control: decision-model-select |
llm_model | string | — | null | Chat model for the LLM baseline provider. Control: llm-model-select |
routing_instruction | string | — | "" | How to interpret the request and when to choose each route. Route IDs come from the route list; keep tool-operation instructions on the focused LLMs. Control: textarea |
routes | array<object> | — | [] | Declared routes (keyed output ports). Control: route-list |
route_memory | enum | — | sticky | Sticky: send the previous route as context; in calibrated mode it is also held for a referential follow-up (in none mode there are no hold thresholds, so only the context applies). Remembered per conversation in this server process. Off: route every turn on its own. Control: select. Options: off (Every turn is routed on its own.), sticky (The previous turn's route is sent as context, and may be held for a referential follow-up ("reply to him and say yes").) |
threshold_mode | enum | — | calibrated | Calibrated: apply the measured profile for this provider/model/language, or fall back when none exists; providers that report no probabilities (LLM baseline) cannot use it. None (uncalibrated): route on the raw answer. Control: select. Options: calibrated (Apply the measured calibration profile; without one, fall back.), none (Uncalibrated: route on the raw answer; only invalid, out-of-set, timed-out, or failed decisions fall back.) |
failure_mode | enum | — | fallback | Fallback: provider errors and missing configuration go to fallback_out. Fail closed: they fail the node. Control: select. Options: fallback (Failures and missing configuration go to fallback_out.), fail_closed (Failures and missing configuration fail the node with a typed error.) |
uncertain_routing | enum | — | fallback | Fallback: low-confidence decisions go to fallback_out with everything else. Separate port: in calibrated mode they go to uncertain_out (below the threshold, or no profile for this model/language), so a second-stage arbiter can decide them; confident fallbacks and provider failures still go to fallback_out. Control: select. Options: fallback (Together with every other non-route outcome, to fallback_out.), separate (To uncertain_out, so a second-stage arbiter can decide it while confident fallbacks (ordinary conversation) go straight to fallback_out.) |
timeout_ms | integer | — | null | Decision deadline; empty uses the provider's default (Jev and Laya: 1500 ms). For the LLM baseline an empty timeout adapts to the chosen chat model from its observed decisions, so a reasoning model gets the time it needs. A miss follows the failure mode and never stalls the turn. Values above the provider's maximum are capped. |
Outputs
| Field | Type | Description |
|---|---|---|
fallback_out | object (port) | Unchanged context when no route was selected. Connection port, not a form field. |
uncertain_out | object (port) | Unchanged context for a low-confidence decision, when separated. Connection port, not a form field. |
decision | object (port) | Bounded decision summary (no user text). Connection port, not a form field. |