Automatic Flow Routing
ACP Engine can select an eligible published Flow from free text in any supported realm use case. A Flow is a versioned capability module: it contributes a bounded system-instruction fragment, approved capabilities, tools, outputs, and execution steps after it is selected. Conversational clients normally use POST /api/v1/runtime/ai/chat and omit flow_id. Protected server integrations may still supply flow_id when one exact Flow must run.
Endpoint Responsibilities
| Endpoint | Use it for | Selects a Flow from free text? |
|---|---|---|
POST /api/v1/runtime/ai/chat | Primary conversational/BFF integration with ordered chat messages and a flattened response. | Yes, when flow_id is omitted and realm routing is enabled. |
POST /api/v1/runtime/execute | Structured sync/async execution, idempotency, deadlines, capabilities, and advanced controls. | Yes, using the same resolver when flow_id is omitted. |
POST /api/v1/runtime/mcp/tools/execute | Protected direct execution of a known approved MCP tool, including fixed BFF mappings for deterministic widget operations. | No. It routes a tool to an eligible MCP server; it does not classify intent, select a Flow, or return a runtime action. |
Supplying flow_id is the explicit-selection signal. There is no separate force_flow field:
- Without
flow_id, ACP builds a realm-bounded candidate set and makes an automatic routing decision. - With
flow_id, ACP skips intent classification and validates that exact Flow. An invalid explicit Flow fails; ACP does not silently choose another Flow.
Create a Subject-Bound Session
Create one ACP session when a conversation or purchase journey begins. flow_id is optional at creation and should normally be omitted when the first customer message must select the Flow.
POST /api/v1/runtime/sessions
Authorization: Bearer {{token}}
Content-Type: application/json
{
"agent_id": "{{agent_id}}",
"subject_type": "external",
"subject_id": "customer-reference-42",
"channel": "web",
"ttl_seconds": 86400,
"metadata": {
"locale": "en-US",
"client_capabilities": {
"actions": [
"RESPOND",
"CLARIFY",
"RENDER_PRODUCTS",
"OFFER_PRODUCT_ALTERNATIVES",
"RENDER_PRODUCT_ALTERNATIVES",
"RENDER_PRODUCT_DETAILS",
"ERROR"
]
}
},
"transcript_retention": true
}
| Field | Required | Meaning |
|---|---|---|
agent_id | Yes | Agent in the authenticated realm. |
realm_id | No | If supplied, it must match the authenticated realm. |
flow_id | No | Initial explicit active published Flow. Omit for automatic first-message routing. |
subject_type | No | anonymous by default; also supports external and user. |
subject_id | Conditional | Required for external and user; generated by ACP for anonymous sessions when omitted. Raw values are not stored. |
channel | No | Defaults to server. |
channel_conversation_id | No | Channel conversation reference; stored as a realm-scoped hash. |
ttl_seconds | No | Defaults to 24 hours and is capped at 30 days. |
metadata | No | Safe, non-secret session metadata such as locale. |
transcript_retention | No | Defaults to true; set false for zero-transcript sessions. |
The response contains session_id, resume_token, and expires_at. Store the token only in protected BFF/server or HttpOnly state. A session ID is a reference, not resume authorization.
Automatic Conversational Routing
POST /api/v1/runtime/ai/chat
Authorization: Bearer {{token}}
Content-Type: application/json
{
"agent_id": "{{agent_id}}",
"session_id": "{{session_id}}",
"resume_token": "{{resume_token}}",
"messages": [
{
"role": "user",
"content": "I want to buy an iPhone"
}
]
}
| Field | Required | Meaning |
|---|---|---|
agent_id | Yes | Agent used for the conversation. |
messages | Yes | Ordered messages; the last user message must contain text. |
session_id | No | Recommended for multi-turn continuity and Flow pinning. |
resume_token | Conditional | Required when resuming a newly created subject-bound session. |
flow_id | No | Omit for automatic routing; include to execute one exact conversational Flow. |
The flattened response contains action, content, optional data, identifiers, and a safe routing summary. For example, CLARIFY asks for missing details; a product Flow may return RENDER_PRODUCTS with structured data.
The chat adapter takes channel, locale, and client capabilities from the subject-bound session. Set them during session creation. Structured /runtime/execute callers can send those fields directly in the execution envelope.
Clients cannot override routing policy with provider IDs, MCP server IDs, tool names, hidden prompts, or arbitrary candidate IDs. ACP selects the classifier provider, eligible Flow, execution provider, MCP servers, and tools from authenticated realm configuration.
For a known widget operation, the BFF may bypass intent classification and use a fixed allowlisted tool mapping through /runtime/mcp/tools/execute. The frontend supplies only validated business input such as a selected catalogId; it does not supply the tool or server choice. If the client needs an ACP runtime action such as RENDER_PRODUCT_DETAILS, use a protected Flow through /runtime/execute instead. These are alternative transports for one operation, not two calls to run for the same event.
Explicit Conversational Flow
{
"agent_id": "{{agent_id}}",
"session_id": "{{session_id}}",
"resume_token": "{{resume_token}}",
"flow_id": "{{flow_id}}",
"messages": [
{
"role": "user",
"content": "Start the configured checkout journey"
}
]
}
Explicit execution does not silently repin a session that is already on another Flow. Permanent session changes happen through an allowed automatic handoff or an authorized routing reset.
Structured Runtime Execution
POST /api/v1/runtime/execute uses the same automatic/explicit resolver but has a structured envelope:
{
"version": "2026-08-22",
"agent_id": "{{agent_id}}",
"session_id": "{{session_id}}",
"resume_token": "{{resume_token}}",
"channel": "web",
"locale": "en-US",
"input": {
"message": "Show waterproof hiking jackets"
},
"client_capabilities": {
"actions": [
"RESPOND",
"CLARIFY",
"RENDER_PRODUCTS",
"OFFER_PRODUCT_ALTERNATIVES",
"RENDER_PRODUCT_ALTERNATIVES",
"RENDER_PRODUCT_DETAILS",
"ERROR"
]
},
"idempotency_key": "journey-123-step-1",
"mode": "sync"
}
input is required. agent_id, flow_id, session_id, resume_token, channel, locale, capabilities, metadata, deadline, idempotency key, and mode are optional or conditional. resume_token becomes required when a new subject-bound session_id is supplied. mode accepts sync or async.
Session Continuity and Lifecycle
One session may span several allowed Flow capabilities, such as product discovery and checkout, incident triage and log analysis, or onboarding and policy support. It should remain active until the journey completes, is cancelled, expires, or is deliberately reset.
| Endpoint | Purpose | Body |
|---|---|---|
POST /api/v1/runtime/sessions/{sessionId}/complete | Mark a successful journey terminal. | { "resume_token": "{{resume_token}}" } |
POST /api/v1/runtime/sessions/{sessionId}/cancel | Cancel the journey and reject further continuation. | { "resume_token": "{{resume_token}}" } |
POST /api/v1/runtime/sessions/{sessionId}/reset | Clear the pinned Flow for a deliberate new routing decision in the same active session. | { "resume_token": "{{resume_token}}" } |
POST /api/v1/runtime/sessions/{sessionId}/resume-token/refresh | Rotate a valid token before expiry. | Current resume_token; optional ttl_seconds, chat_id, metadata. |
POST /api/v1/runtime/sessions/{sessionId}/resume-token/recover | Recover an active or expired session with runtime:session_recover. | Optional ttl_seconds, chat_id, metadata; no old token. |
GET /api/v1/runtime/sessions/{sessionId}/status | Read effective session status. | None. |
Payment-provider sessions and merchant cart/checkout IDs are separate business references. They never replace the ACP session_id.
Candidate and Decision Boundaries
Before model classification, ACP filters candidates by authenticated realm, publication and activation state, activation window, required input, channel, locale, client capabilities, routing manifest or profile, and session handoff policy. Draft, archived, expired, cross-realm, denied-channel, input-incompatible, and capability-incompatible Flows never enter the model candidate set.
The classifier receives opaque candidate aliases, not an unrestricted Flow namespace. ACP validates the result against that allowlist and applies confidence and risk thresholds. Financial, destructive, and sensitive routing requires at least 0.90 confidence; it does not remove downstream user or tool approval requirements.
Flow Capability Modules
New adaptive and hybrid Flows can carry their routing and behavior contract in the published Flow config. A separate routing profile remains supported and takes precedence when both are present.
{
"schema_version": "2026-09-25",
"orchestration_mode": "hybrid",
"routing": {
"enabled": true,
"when_to_use": "Investigate service incidents and operational failures.",
"when_not_to_use": "Do not approve access requests.",
"capabilities": ["incident.triage", "logs.search"],
"allowed_handoffs": ["access.request", "human.escalation"],
"minimum_confidence": 0.75
},
"behavior": {
"instructions": "Act as the realm's incident-triage specialist. Separate evidence from inference.",
"completion_criteria": ["Likely cause identified", "Safe next action proposed"]
},
"permissions": {
"allowed_actions": ["RESPOND", "CLARIFY", "ESCALATE"],
"risk_tier": "elevated"
},
"runtime": {
"max_tool_calls": 3
}
}
The same structure works for commerce, support, banking, HR, operations, developer tooling, and other realm-owned domains. Runtime does not contain ecommerce-specific Flow selection rules. Capability names are tenant configuration, not authorization by themselves.
After routing, ACP composes the selected Flow's behavior, completion criteria, allowed actions, and runtime limits with the realm and Agent system prompt. The visual graph stays server-side and is not copied wholesale into model instructions. Only the selected Flow fragment is added; unrelated Flow prompts are not exposed to the execution model.
orchestration_mode supports:
| Mode | Purpose |
|---|---|
deterministic | Execute the reviewed graph without adaptive branch selection. Existing Flows keep this behavior. |
adaptive | Let bounded AI decision and supervisor nodes select among declared branches or children. |
hybrid | Combine deterministic steps for controlled operations with bounded AI decisions for semantic work. |
Bounded AI Decisions
The visual Flow Builder includes AI Decision and adaptive Supervisor nodes. An AI decision declares between two and twenty choices. The model receives opaque choice aliases and cannot introduce another node, Flow, tool, provider, or ACP action.
{
"id": "decide_next_step",
"type": "ai_decision",
"instructions": "Choose whether the request can be answered or needs clarification.",
"minimum_confidence": 0.7,
"fallback_choice": "clarify",
"choices": [
{"key": "answer", "description": "Enough verified context exists to answer."},
{"key": "clarify", "description": "Required information is missing or ambiguous."}
]
}
The node stores decision, confidence, and reason in Flow state. Graph edges can branch on $results.decide_next_step.decision. Invalid output, an unknown choice, provider failure, or confidence below the threshold uses the declared fallback when present; otherwise execution fails safely. Adaptive supervisors apply the same bounded selection to their configured child nodes and execute only the selected child.
AI selection never grants authority. Realm and Agent scope, published Flow eligibility, tool allowlists, schemas, approval requirements, idempotency, allowed output actions, risk thresholds, cost, latency, retry, and data-egress controls remain deterministic Runtime checks.
Manager Configuration
Open Orchestration → Flow Routing Settings for the selected realm:
- Configure one active, text-capable realm default provider. This is the Flow-routing classifier; Agent provider selection happens after the Flow is chosen.
- Publish and activate each routable Flow.
- In Flow Builder, choose
deterministic,adaptive, orhybrid. For adaptive/hybrid Flows, define when to use it, exclusions, semantic capabilities, capability-based handoffs, Flow instructions, completion criteria, allowed actions, and risk tier. - Optionally configure a dedicated routing profile when a Flow needs advanced positive/negative examples, channel or locale constraints, client capabilities, priority, or an explicit profile override.
- Run routing preview and an approved labeled evaluation dataset.
- Use
shadowbeforeenforced, inspect applied versus proposed decisions, and begin enforced rollout with a limited canary percentage.
Realm routing modes are:
| Mode | Behavior |
|---|---|
disabled | Executes the compatibility order: session Flow, Agent default Flow, then latest eligible active Flow. |
shadow | Computes and records the automatic proposal but executes the compatibility selection. |
enforced | Executes the automatic decision for canary traffic after a passing evaluation. |
Rollback is immediate: return the realm policy to disabled. Routing profiles and decision history remain available for diagnosis.
Security and Data Handling
- ACP stores a realm-scoped subject hash, not the raw external subject value.
- The resume token is signed and bound to realm, session, subject hash, version, and expiry.
data_egress_allowed: false, a missing/inactive default text provider, or a routing-disabled provider forces deterministic local fallback.- Routing and adaptive nodes never bypass tool allowlists, output-action permissions, MCP policy, approval, idempotency, retention, consent, quota, or data-egress enforcement.
- Do not put credentials, raw card data, CVV, OTP, payment tokens, or unnecessary personal data in messages, metadata, or session state.
For lifecycle details and BFF recovery rules, see Runtime Sessions, Chat IDs, and Recovery.