Human-in-the-loop for agents
A checkpoint your agent can reach: a real person, on a phone.
Agent wants to refund 3 customers
support-agent reached a step that needs a person's yes before it acts.
- Total
- $4,200
- Customers
- 3
- Reason
- Late delivery
- Agent
- support-agent
A notification that opens into a decision
Every Roundtrip request is one loop: something happens, a person decides on their phone, and the decision lands back in your app, signed.
- 1Trigger
The trigger
An agent connected over MCP reaches a risky step: spending money, deploying, deleting data, or messaging someone. It pauses for human judgment instead of acting unsupervised.
An agent connected over MCP reaches a risky step: spending money, deploying, deleting data, or messaging someone. It pauses for human judgment instead of acting unsupervised.
- 2Ask
The ask
Via request_human_approval, Roundtrip pushes the agent's intent and context to a person's phone with Approve / Reject. The call is non-blocking: the agent gets a request id and continues correlating, not hanging.
Via request_human_approval, Roundtrip pushes the agent's intent and context to a person's phone with Approve / Reject. The call is non-blocking: the agent gets a request id and continues correlating, not hanging.
- 3Response
What comes back
The human's decision returns via signed webhook, and the agent resumes with real authorization behind it. The same loop accepts a form when the agent needs input, not just permission.
The human's decision returns via signed webhook, and the agent resumes with real authorization behind it. The same loop accepts a form when the agent needs input, not just permission.
One request out, one signed response back
The card on the phone is rendered straight from the request body, not a mockup. When the recipient responds, Roundtrip POSTs a signed event to your webhook and retries until it lands.
{
"channels": [
"agent-tasks"
],
"notification": {
"title": "Agent · refund batch",
"body": "Wants to refund 3 customers ($4,200) — needs a yes."
},
"content": {
"title": "Agent wants to refund 3 customers",
"description": "support-agent reached a step that needs a person's yes before it acts.",
"status": {
"label": "Needs approval",
"tone": "warning"
},
"sections": [
{
"type": "keyvalue",
"columns": 2,
"items": [
{
"label": "Total",
"value": "$4,200",
"mono": true
},
{
"label": "Customers",
"value": "3"
},
{
"label": "Reason",
"value": "Late delivery"
},
{
"label": "Agent",
"value": "support-agent"
}
]
},
{
"type": "list",
"items": [
{
"label": "Maria G.",
"value": "$1,800"
},
{
"label": "Dan P.",
"value": "$1,500"
},
{
"label": "Wei L.",
"value": "$900"
}
]
}
],
"actions": [
{
"id": "approve",
"label": "Approve all",
"style": "primary"
},
{
"id": "reject",
"label": "Reject",
"style": "destructive"
}
]
},
"response": {
"mode": "required",
"webhook": "https://api.example.com/roundtrip"
}
}Agent wants to refund 3 customers
support-agent reached a step that needs a person's yes before it acts.
- Total
- $4,200
- Customers
- 3
- Reason
- Late delivery
- Agent
- support-agent
{
"requestId": "req_8Kx2…",
"channel": "agent-tasks",
"kind": "tap",
"action": "approve",
"respondedAt": "2026-06-20T16:41:09Z"
}