osmTalk Docs
Agents

Call Transfer to Human

Hand off a live call to a human agent with a warm summary of the conversation.

When the AI agent can't solve the problem, or when the caller explicitly asks for a human, osmTalk can transfer the call to a human agent's phone. The bot dials the human, keeps the caller on hold with polite messages, and hands over context so the human knows where to pick up.

Only works on phone (SIP) channels — web-call-only agents can't transfer.


Example 1: Support Escalation

Goal: when a caller gets frustrated or the issue is too complex, transfer them to a human support agent.

Step 1 — Add transfer settings to your agent

In agent config → Tools → JSON editor:

{
  "httpTools": [...],
  "transferSettings": {
    "transferToHuman": {
      "enabled": true,
      "destinationNumber": "+919876543210",
      "triggerDescription": "Transfer the caller to a human support agent when they explicitly ask to speak to a person, when they express frustration, or when the issue involves a dispute, refund, or anything you can't resolve with available tools."
    }
  }
}
  • destinationNumber — the human's phone in E.164 format (e.g., +919876543210)
  • triggerDescription — tells the LLM when to trigger the transfer tool

Step 2 — No system-prompt changes needed

The LLM automatically gets a transfer_to_human tool it can call when the triggerDescription criteria are met. You don't need to reference the tool by name in your prompt.

Step 3 — What the caller experiences

Caller: "I've been trying to fix this for an hour. Let me talk to a real person!"
Bot:    "Of course. Please hold while I connect you to a human agent."

[bot silently captures the last 10 messages as a summary]
[bot calls +91-98765-43210 via SIP]

Bot:    "Ringing. Please stay on the line."
...
Bot:    "Still connecting your call. One moment please."
...
Bot:    "Thank you for your patience. Almost there."

[human picks up — bot exits the call, caller is now connected to the human]

Step 4 — What the human support agent receives

Your backend receives a POST to /api/calls/:id/transfer with:

{
  "destination": "+919876543210",
  "summary": "User: I've been trying to reset my password for an hour\nAssistant: I tried the reset_password tool but it returned 'account locked'\nUser: That's exactly the problem! Every time I try to reset it says locked\nAssistant: I see the lock was placed on 2026-04-19 due to 5 failed login attempts\nUser: Can you unlock it?\nAssistant: I don't have unlock permissions, let me connect you to support\nUser: I've been trying to fix this for an hour. Let me talk to a real person!"
}

Your CRM / support tool can display this summary on the human agent's screen so they can immediately pick up where the bot left off — no "tell me your problem again" loop.


Example 2: Outbound Sales Callback

Goal: if a prospect says "can you transfer me to a senior rep?", transfer them to the sales manager.

Transfer settings

{
  "transferSettings": {
    "transferToHuman": {
      "enabled": true,
      "destinationNumber": "+14155551234",
      "triggerDescription": "Transfer when the prospect explicitly asks to speak to a senior person, a manager, or when they raise concerns you can't address (pricing negotiation, custom contracts, enterprise features)."
    }
  }
}

System prompt adds context

You are Arjun, a sales development rep for CloudSync.

...(product details)...

If the prospect asks about enterprise pricing, custom SLAs, or wants to speak to a manager, politely transfer them. Say:
  "Happy to connect you with our senior rep who handles custom contracts. Please hold for a moment."

Then call the transfer_to_human tool.

Caller experience

Prospect: "What about SSO and SCIM for enterprise?"
Bot:      "Great question — that's covered in our Enterprise plan with custom provisioning. Happy to connect you with our senior rep who handles that. Please hold for a moment."

[transfer happens, sales manager picks up with full context]

Advanced: Multi-Agent Routing

You can configure multiple transfer destinations — different departments, or different AI agents.

{
  "transferSettings": {
    "transferToHuman": {
      "enabled": true,
      "destinationNumber": "+919876543210",
      "triggerDescription": "Transfer to a human only for billing disputes or refund requests."
    },
    "transferToAgents": [
      {
        "name": "technical_support",
        "description": "Transfer to the technical support specialist AI when the user has server errors, API issues, or needs help with integrations."
      },
      {
        "name": "sales_specialist",
        "description": "Transfer to the sales specialist AI when the user wants to discuss pricing, plans, or upgrades."
      }
    ]
  }
}

The LLM sees all three tools and picks the right one based on the conversation.


How the Warm Handoff Works

Before dialing the human, the bot:

  1. Captures the last 10 conversation turns (user + assistant only, strips system message)
  2. Formats them as:
    User: <message>
    Assistant: <response>
    User: <message>
    ...
  3. Truncates each message to 300 chars (prevents oversized payloads)
  4. POSTs the summary to your /api/calls/:id/transfer endpoint alongside the destination

Your API endpoint should:

  • Store the summary on the calls table (or your CRM)
  • Optionally surface it on the human agent's softphone/dashboard
  • Log the transfer event for analytics

Troubleshooting

ProblemLikely causeFix
Bot never transferstriggerDescription too vagueBe specific: "when user says X or Y"
Human doesn't hear the summaryYour API isn't storing/surfacing itCheck /api/calls/:id/transfer handler
Caller hears "Please hold" foreverHuman's phone didn't answer within 30sBot will exit after 30s — add a fallback like voicemail
Transfer disconnects immediatelydestinationNumber not in E.164 formatUse +<country><number>, no spaces or dashes

Configuration Reference

{
  "transferSettings": {
    "transferToHuman": {
      "enabled": true,
      "destinationNumber": "+919876543210",
      "triggerDescription": "Natural-language description of when to transfer"
    }
  }
}
FieldTypeRequiredDescription
enabledbooleanyesMaster toggle
destinationNumberstring (E.164)yesThe human's phone
triggerDescriptionstringyesPassed to the LLM as the tool's description