Logical route JSON reference
The console "Logic JSON" is the single source of truth (logic_json / RouteLogicV2). The flow diagram is a visual mapping of flowNodes; every apply or canvas edit runs parseRouteLogic + syncLogicFromFlowNodes, then the same validateRouteLogic pipeline (including Gateway Endpoint context).
Top-level fields
routingMode: single | byInputFormat | conditional | flow. operation is always "generate" (embedding uses flowNodes with kind: embed).
| Path | Type | Description |
|---|---|---|
| version | number | Must be 2 |
| operation | string | Always "generate" |
| routingMode | string | single | byInputFormat | conditional | flow |
| input.promptTemplate | string | Prompt template, e.g. {{prompt}} |
| defaultBranch | object | Default branch: providerId, model or nodeKey (Endpoint), generation |
| branches[] | array | Conditional branches (synced with flowNodes) |
| flowChain[] | array | Fallback steps (routingMode: flow) |
| flowNodes[] | array | Flow canvas source; apply runs syncLogicFromFlowNodes |
| protocolFlowNodes | object | Per access-protocol flowNodes buckets (split editor view) |
| embedBranch | object | Compiled from kind: embed nodes |
Branch condition when
Used on branches[].when, deny.when, and nested branches. First match wins.
format
Input shape: text | chat_content | image | image_text | multimodal | file | audio | video | openapi_json | any
{ "type": "format", "format": "image_text" }modelId
Caller upstream model (Header x-gateway-model or metadata.model)
{
"when": { "type": "modelId", "op": "eq", "value": "gemini-2.5-flash" }
}fileSize
Total inlineData byte threshold
{ "type": "fileSize", "op": "gt", "value": 1, "unit": "MB" }metadata
Match header / metadata / body field
{ "type": "metadata", "source": "metadata", "key": "user_id", "op": "exists" }messageType
Message role or part type (text / image / audio / video / file)
{ "type": "messageType", "variant": "role", "role": "system", "scope": "any" }messageContent
Match text in messages (concatenated text parts in contents / messages)
{ "type": "messageContent", "scope": "last_user", "op": "contains", "value": "summarize" }messageParts
Multiple part types in contents[] / messages[]; match all (across messages), any, only, or all in same message
{ "type": "messageParts", "parts": ["text", "image"], "match": "same_message", "scope": "last_user" }flowNodes.kind
- single — Single upstream Endpoint
- conditional — IF / ELSE
- switch — Multi-case + DEFAULT
- fallback — Ordered fallback steps[]
- deny — Reject when when matches
- embed — Vector embed embedContent
Examples
Single Endpoint
{
"version": 2,
"operation": "generate",
"routingMode": "single",
"input": { "promptTemplate": "{{prompt}}" },
"defaultBranch": {
"providerId": "gemini",
"model": "",
"nodeKey": "your-endpoint-node-key",
"generation": { "temperature": 0.7 }
},
"flowNodes": [
{
"id": "single-1",
"kind": "single",
"providerId": "gemini",
"model": "",
"nodeKey": "your-endpoint-node-key"
}
]
}Conditional (image+text / text)
{
"version": 2,
"operation": "generate",
"routingMode": "byInputFormat",
"input": { "promptTemplate": "{{prompt}}" },
"defaultBranch": { "providerId": "gemini", "model": "", "nodeKey": "default-node" },
"flowNodes": [
{
"id": "if-1",
"kind": "conditional",
"branches": [
{
"id": "image",
"label": "图文",
"when": { "type": "format", "format": "image_text" },
"providerId": "gemini",
"model": "",
"nodeKey": "vision-node"
}
],
"elseBranch": {
"providerId": "openai",
"model": "",
"nodeKey": "text-node"
}
}
]
}Ctrl+Enter applies JSON; after apply the flow canvas and runtime registry share the same logic_json.