When a user asks "Is there a fee for canceling a reservation?", they need to check the policy. When they say "Check my order", they need to read personal order data. When they say "Cancel it if it's free", they need to first check the facts, evaluate the condition, then proceed to the operation. All three sentences relate to hotels and cancellations, yet the processing paths differ.
Intent routing selects the corresponding service or processing flow based on recognition results. It must consider user goals, current state, parameters, and business constraints together. Using a hotel assistant as an example, this article introduces four types of processing paths: knowledge retrieval, read-only tools, write operations, and clarification. The code is available in the full project.
1. The Division Between Intent Recognition and Routing
When a classifier returns cancel_booking, it only indicates the user expressed a cancellation goal. The routing layer still needs to know which order to cancel, whose order it is, whether cancellation is allowed, what the fee is, and whether the user has confirmed the current plan.
If all these questions were handled through tags, we would constantly need new categories like "cancel but missing order number", "cancel with fee", "cancel already confirmed". The number of tags would expand rapidly with process state, and labeling would become difficult to maintain stably.
A clearer structure is: intents describe goals, slots describe parameters, state describes current progress, and business rules determine available actions. The routing layer decides the next operation based on this information—it cannot simply look up a handler function by tag.
2. Defining Business Capabilities and Intent Mapping
The capability catalog describes what services the system can actually provide. One intent can map to a multi-step process; multiple query intents can also share the same retrieval capability.
| User Goal | Tag | Processing Capability | Return Basis |
|---|---|---|---|
| Breakfast, check-in, or cancellation policies | policy_query | Knowledge Retrieval | Document content and source |
| Search listings and prices | room_search | Read-only Listing Tool | Current available information |
| Query personal orders | order_query | Permission-constrained Order Tool | Specific order facts |
| Book, modify, cancel | Corresponding business tags | Write Operation Flow | Parameters, verification, confirmation, and execution results |
| Missing parameters or unclear object | Target may be known | Clarification Strategy | Current state and options |
| Beyond current capabilities | Out-of-scope state | Explain scope or transfer | Published capability catalog |
Whether small talk needs a separate receiver depends on the product. A general-purpose assistant can route small talk to general conversation capability; the hotel assistant in this series provides capability explanations instead. Don't disguise small talk as a hotel intent just because every input needs a response.
3. Knowledge Retrieval vs. Order Queries
Knowledge bases are suitable for storing relatively stable rules and explanations, such as breakfast times, check-in policies, and material requirements. Personal order status comes from business systems, with user ownership, timeliness, and access permissions.
Sending "Did my order get canceled?" to regular document retrieval might surface "How to cancel an order" but fail to answer what state this specific order is actually in. Semantically relevant retrieval results don't mean they possess the facts the question requires.
So first ask two questions: Does the answer primarily come from public documentation, or from the current user's business object? If the latter, first locate the object and call the permission-constrained tool; retrieve the policy explanation tool's results only when necessary.
For example, an order query returns "Cancellation fee: 50", and the policy retrieval explains the fee basis. Together they form the answer, but the knowledge base's generalization that "some room types can cancel for free" cannot override the specific fee for that order.
4. Rewriting Queries with Context
When a user asks "Can that be refunded?", using those exact words for retrieval is usually insufficient. First confirm through session state what "that" refers to—which order or which type of product—then generate a clear retrieval query.
A common sequence is:
Current Input + Dialog State
→ Determine goal and reference
→ Identify knowledge topic or business object
→ Rewrite query in the knowledge branch
→ Retrieve, organize evidence, generate response
But this isn't a fixed pipeline all systems must follow. Some questions need lightweight retrieval first to confirm capability; some classifiers also use retrieved label examples. The key is distinguishing retrieval's purpose: is it helping select labels, or finding evidence for the final answer? Different purposes should have independent inputs and evaluations.
Preserve negation and conditions when rewriting. "Don't cancel if there's a fee" cannot be compressed to "Cancel order". For write operations especially, avoid treating short queries generated during retrieval optimization as full user authorization.
5. Verification and Confirmation for Write Operations
When canceling an order, you first need to identify the cancellation intent, determine the order, query status and fees, then present the plan to the user and wait for confirmation.
Confirmation records should at least bind operation type, key parameters, object version, and valid conditions. For example, if the user confirmed "Cancel DEMO-A, current fee: 0", you shouldn't continue using that old confirmation after the fee or order object changes.
The attached mock flow saves the pending confirmation plan; only after the user replies "confirm" does it read the order version and fee. If conditions change, return a conflict and let the application display the new plan. This way, there's a clear correspondence between recognition results, user confirmation, and actual submission.
Recognize cancellation goal
→ Fill in order number
→ Query user's ownership, status, and fee
→ Evaluate whether "cancel only if free" holds
→ Present plan
→ User confirms
→ Re-verify key facts
→ Submit and save result
"Confirm parameters" and "confirm execution" also need distinction. When the user answers "Yes, this is the order", they may have only confirmed the object, not the cancellation fee and actual operation. Products should ask complete confirmation questions so users know what their reply will trigger.
6. The Division Between Workflow and Agent
For known, stable operations requiring strict constraints, a fixed Workflow is appropriate. What checks exist for canceling an order, what conditions must hold—these should be expressed in verifiable code.
Agents are better suited for goals with uncertain paths, such as supplementing queries across multiple information sources, comparing candidate options, and organizing materials returned by different tools. They can propose next steps, but tool permissions, parameter validation, and write operation constraints should still be enforced by the runtime.
The two can be combined: the Agent handles understanding complex requirements and gathering evidence, while specific bookings or cancellations are completed by fixed flows. This preserves flexibility while concentrating critical business constraints in few interfaces.
When choosing the approach, look at where uncertainty lies. If it's just diverse expression, often a stronger recognizer suffices; only if the processing path also needs exploration is dynamic planning more necessary. Don't let every order modification become free planning just because the entry point uses an LLM.
7. Multi-task Dependencies and Execution Order
"Check the order, cancel if free, also look at rooms for tomorrow" contains multiple goals. The routing layer should preserve each task's ID, parameters, and dependencies, not compress the entire input into a single tag.
The diagram in the task dependency article can first execute order query, turning results into trusted facts; the cancellation node checks this fact, while the room search node continues based on its own dependencies.
If cancellation conditions aren't met, only skip the cancellation node. Room search doesn't depend on cancellation succeeding, so it shouldn't stop together. Conversely, when a task must depend on the previous step succeeding, you can't continue just because "the previous step has returned."
The attached batch3/planner.py advances this graph using mock order results: read nodes return results, write nodes return pending confirmation plans. The program selects subsequent nodes based on query results, pausing write operations requiring confirmation.
8. Access Control and Prompt Injection Protection
Knowledge documents might contain text like "Ignore previous instructions," and users might claim admin privileges in their requests. These can be analyzed as data but must not alter server-side access control or tool capabilities.
Prompt injection is dangerous because models processing natural language can confuse data with instructions. The routing layer should keep identity, permissions, capability whitelists, and write operation thresholds in trusted programs, not rely solely on the model following rules. See OWASP Prompt Injection
For example, when querying orders, permission checks should use the server's authenticated identity. A user typing "This order belongs to me" in chat cannot be the basis for access. The model returning a valid order ID also doesn't prove the user has permission to view it.
9. Exception Handling and Service Degradation
When retrieval finds no evidence, return "Insufficient information" and guide for supplementation; when order tools timeout, enter limited retries or service degradation; when the goal is unclear, ask specific questions. These three outcomes cannot all be compressed into "I don't understand."
Service degradation also shouldn't arbitrarily change the goal. If the cancellation tool is unavailable, you can save the pending state and explain the result is not yet determined; you cannot change to a cancellation policy explanation to give a smooth response and claim the task is complete.
Typical routing results in engineering include knowledge, read_tool, clarify, confirm, condition_false, and mock_write. Only the last indicates mock business write is complete; each of the others has a clear next step.
From the project root, run:
python batch3/assistant.py
python batch3/planner.py
For more complete retrieval, Agent execution, and streaming service design, revisit Production-Grade RAG and Agent System Design. This article focuses on why requests route to certain capabilities; the next article Going Live continues with how the same request reliably completes.