Skip to main content
Some conversations should end up with a person: a refund the model cannot approve, or a customer who asks for one. This guide transfers such a conversation to a human queue with its full history, using routing rules your application owns. It uses only existing platform features. The model decides or requests the transfer, the Conversations API supplies the history, and your application picks the queue and delivers the package. API Reference:

1. Decide when to hand over

There are two ways to get the decision from the model. Use either or both. Triage after each customer message. The console ships a “Customer care triage” agent template. In the console, open Agents, choose New agent, pick Customer care triage, select Use template, then Create agent. The agent returns one JSON object per run with category, priority, sentiment, language, summary, suggested_reply, needs_human_handoff and handoff_reason. The template’s instructions say when needs_human_handoff is true: the customer asks for a person, reports fraud or a security issue, threatens legal action or cancellation, is very upset, or needs a refund, account change or decision the model cannot make. Edit the categories in the instructions to match your support teams before you route on them. Copy the agent id; the sample below reads it from TRIAGE_AGENT_ID. Let the assistant ask for a person mid-conversation. Declare a function tool on the agent or Responses request that handles the chat. When the model calls it, the response contains a function_call item with the arguments. Your application builds the same handover package as below and answers with a function_call_output so the model can tell the customer what happens next. See Function calling for the loop.
Tool definition

2. Pause for a human decision

If the agent uses MCP tools that mutate external systems, set require_approval: "always" on the tool. The response then stops at an mcp_approval_request item instead of calling the tool. Your application shows the human the server, tool name and arguments, and continues the response with an mcp_approval_response item that approves or denies the call. This is the same approval flow as Require end-user approval, with a support agent making the decision instead of the end user.

3. Collect the full history

Keep each support chat in a conversation so the history is stored on the platform. When the handover fires, list the conversation’s items and attach them to the package. Items come back in the order they were added when you pass order: "asc".
TypeScript SDK
The list holds every message, function call and tool output the conversation contains, so the human agent sees what the customer and the assistant already said. The list is paginated; pass after with the last item id when a conversation is longer than one page.

4. Route with rules you control

Routing is a lookup your application owns. Keep it as data so support leads can change it without a deploy. The sample uses a list of rules, first match wins. A rule without priority matches every priority, and anything unmatched goes to a default queue.
Routing rules
category and priority come from the triage JSON. With the function tool, map queue_hint the same way.

5. Deliver to the queue

The handover package is plain JSON: the queue, the reason, the triage result, the conversation id and the history. Post it to the system that holds your human queues, such as a help desk webhook or a ticketing API. The sample posts to HANDOVER_WEBHOOK_URL when it is set and prints the package otherwise, so you can run it without a third-party account.
Handover package

Run the sample

The sample seeds a conversation so it runs on its own. In your application the conversation already exists and only steps 2 to 5 run. It needs MKA1_API_KEY and the TRIAGE_AGENT_ID from step 1.
handover.ts

Example output

This is what the sample printed against production, trimmed to the first history item.

Next steps