Concept
Four things can finish work for an agent. Each one returns control in a different way.
A handoff with
EXPECT_RETURN: false does not return. The parent finishes and the target owns the conversation. Hand off to a terminal agent covers that pattern.
To choose between a handoff and a delegate, see Use a handoff instead of a delegate and Use a delegate instead of a handoff. To start a returnable handoff, see Hand off to a returnable agent.
Two settings decide what the parent does after a child returns:
Minimal working example
A supervisor sends an unverified customer to a verification agent. The child returns. The supervisor replays the original question and routes it to the order agent.- The customer says “Where is my order?”.
verified_customer_idis not set, so the supervisor hands off to the verification agent. - The child asks for the customer ID and completes. The platform copies
customer_idfrom the child intoverified_customer_idon the supervisor. - The supervisor replays “Where is my order?”. Now
verified_customer_idis set and the intent isorder_status, so the supervisor hands off to the order agent.
How it works
How control returns
A child agent returns in one of two ways:- The child reaches
COMPLETE. Its thread ends. - The child’s model hands the conversation back before it completes. Its thread pauses and stays resumable.
State and memory after the return
Themap block decides which child values reach the parent.
Keep these rules in mind:
- A mapped child key must hold a value. A
GATHERfield or aSETassignment in the child gives it one. A key with no value is skipped without an error. - An empty returned value does not overwrite a parent value that is already set.
setassigns parent values after the map runs.- A map target that is a reserved or system variable is rejected. When any
map,set, orcleartarget is not writable, the platform applies none of the return effects. This includesRESPOND. - Memory with the
execution_treescope returns automatically. - Other child values stay with the child unless you map them.
What the parent does next
WithoutON_RETURN, the parent resumes. If the child returned a customer message, the parent routes that message as if the action were resume_intent.
With resume_intent, the platform picks the message to replay with resume_with:
If you omit
resume_with and the child passed a message back, the platform replays the passed message. The platform does not forward a message that answers a sensitive question, such as a PIN.
The platform replays once for each return. A reasoning parent allows one replay level. A parent that returns from a flow child can pass a replay up through four nested returns. When the limit is reached, the trace shows resume_intent_depth_limit.
With continue, the parent continues its own flow or turn without a replay.
Delegate results
A delegate runs in a separate scope inside one turn. It cannot wait for customer input. If the child needs input, the delegate fails. Give the child everything it needs throughINPUT.
The RETURNS block copies named child values into parent variables. If you declare RETURNS and the child returns none of those values, the delegate fails. The platform blocks unsafe key names and scrubs secrets from returned values.
A delegate stops waiting when TIMEOUT expires. Without TIMEOUT, the platform uses the runtime default. The default is 30 seconds unless your operator changes it. A failure follows ON_FAILURE:
A one-way child that hands back
In 1.9.0, a child that the parent left withEXPECT_RETURN: false can still hand the conversation back to its direct parent. The child needs its own HANDOFF entry that targets that parent. This works only while the first handoff call is still in progress. The platform blocks routes to any other earlier agent as cycles.
When a human agent finishes
Where the person works decides how the session resumes.post_agent is end unless you set return in the routing block or in the project default for agent transfer.
With post_agent: return, the agent that escalated resumes. A customer message such as thanks, bye, or done within 5 minutes of the transfer end completes the session. Any other message goes to the agent.
With a SmartAssist survey, the platform keeps the session open until the customer answers the survey or the answer window ends.
The person’s wrap-up form arrives after the disconnect and finishes the transfer record. The resume decision is already made at that point.
While the person is working, customer messages go to the person. The agent does not answer them.
Conditions for on_human_complete
When on_human_complete has entries, the platform pauses the session at escalation. The customer receives the waiting message for every message until the task resolves. The pause record expires after 7 days.
The resolve call carries a decision value. The platform checks the entries in order and returns the action of the first match. These are the only supported conditions:
An entry with any other condition never matches. If no entry matches, the action is
continue.
Timeouts and abandoned handoffs
Common variations
Continue with the parent’s own flow
Usecontinue when the parent keeps working and only needs the returned values. This example copies the income and records a note.
Delegate a check and map the result
The order desk asks the refund checker for a decision. The checker never talks to the customer. Project-local assumption: the project defines thecheck_refund_policy tool.
ON_FAILURE in a DELEGATE entry. A DELEGATE entry that uses ON_FAIL compiles without an error, and the platform ignores the line.
Resume the agent after the person finishes
Setpost_agent: return so the agent that escalated resumes when the person disconnects.
End the session when the person finishes
Setpost_agent: end, or leave it out, when the person closes the conversation.
Pause for a reviewer decision
Useon_human_complete when a reviewer answers through the inbox or the resolve API. The decision string drives the returned action.
POST to the project session path /sessions/<session ID>/escalation/resolve. The caller needs the session:execute permission. The body holds resolution with decision, respondedBy, and optional notes and fields. The response returns data.action. Your integration reads the action and acts on it.
Conditions such as human.resolved == true never match. The resolve call returns continue for them.
Hand a one-way child back to the parent
A child that the parent left for good can hand the conversation back to the parent while the first handoff call is still in progress.Verification
- Validate the project. Fix every warning about unset variables or unknown conditions.
- Run a conversation that triggers the handoff. Confirm that the child owns the next turns.
- Complete the child task. Open the session trace and find
return_to_parentorthread_return. - Check the parent variables. Each mapped variable holds the child value. A mapped variable with no value means the child did not hold the key.
- For
resume_intent, find theresume_intentevent. CheckresumeMessageandresumeMessageSource. Confirm that the parent routed to the expected agent. - Find the
handoff_completedevent. CheckoutcomeanddurationMs. This event records the handoff attempt. It does not record the return. - For a delegate, find
delegate_complete. Checksuccess. Finddelegate_return_mappingto see which keys were set or blocked. - Force a delegate failure in a test project. Confirm that
ON_FAILUREruns and the customer sees the message. - For a desk escalation, end the conversation at the desk. With
post_agent: return, send a message and check that the agent answers. Withend, check that the session reports the conversation as complete. - For
on_human_complete, call the resolve endpoint once for each decision. Checkdata.action. Find theescalation_resolvedevent.
Production readiness checklist
- Every
mapkey exists in the child as aGATHERfield or aSETtarget. - Every map target has a
MEMORYdeclaration in the parent and is not a reserved name. - Each
resume_intentparent has a route that can handle the replayed message. - Each child has a
COMPLETErule or a way to hand back. A child without one keeps the conversation. - Each
DELEGATEhas aTIMEOUTand anON_FAILURE. - You set
post_agenton every desk route. You do not rely on the defaultend. - Every
on_human_completecondition usesdecision. Your integration readsdata.action. - You set a service level for the escalation inbox. Someone watches tasks that are due.
- You tested the success path, a returned message, a delegate timeout, a delegate failure, and each
post_agentvalue. - Monitoring watches
handoff_completed,delegate_complete,memory_error, andescalation_resolvedevents.