diff --git a/api/routes/telephony.py b/api/routes/telephony.py
index 0e423cb..5c57cc2 100644
--- a/api/routes/telephony.py
+++ b/api/routes/telephony.py
@@ -1728,7 +1728,6 @@ async def complete_transfer_function_call(transfer_id: str, request: Request):
status=result["status"],
action=result.get("action", ""),
reason=result.get("reason"),
- end_call=result.get("end_call", False),
)
# Publish the event via Redis
diff --git a/api/services/telephony/ari_manager.py b/api/services/telephony/ari_manager.py
index 193ed9f..98dacfc 100644
--- a/api/services/telephony/ari_manager.py
+++ b/api/services/telephony/ari_manager.py
@@ -790,8 +790,6 @@ class ARIConnection:
message="Transfer destination answered",
status="success",
action="destination_answered",
- end_call=True,
- timestamp=time.time(),
)
await transfer_manager.publish_transfer_event(success_event)
@@ -824,8 +822,6 @@ class ARIConnection:
status="failed",
action="transfer_failed",
reason=reason,
- end_call=False,
- timestamp=time.time(),
)
await transfer_manager.publish_transfer_event(failure_event)
diff --git a/api/services/telephony/transfer_event_protocol.py b/api/services/telephony/transfer_event_protocol.py
index 761d3f6..7e7815e 100644
--- a/api/services/telephony/transfer_event_protocol.py
+++ b/api/services/telephony/transfer_event_protocol.py
@@ -52,7 +52,6 @@ class TransferEvent:
"conference_id": self.conference_name,
"transfer_call_sid": self.transfer_call_sid,
"original_call_sid": self.original_call_sid,
- "end_call": self.end_call,
"reason": self.reason,
}
return result
diff --git a/api/services/workflow/pipecat_engine_custom_tools.py b/api/services/workflow/pipecat_engine_custom_tools.py
index 0c2dfca..c915fb8 100644
--- a/api/services/workflow/pipecat_engine_custom_tools.py
+++ b/api/services/workflow/pipecat_engine_custom_tools.py
@@ -318,7 +318,6 @@ class CustomToolManager:
"message": "I'm sorry, but call transfers are not available for web calls. Please try a telephony call.",
"action": "transfer_failed",
"reason": "webrtc_not_supported",
- "end_call": True,
}
await self._handle_transfer_result(
webrtc_error_result, function_call_params, properties
@@ -332,7 +331,6 @@ class CustomToolManager:
"message": "I'm sorry, but I don't have a phone number configured for the transfer. Please contact support to set up call transfer.",
"action": "transfer_failed",
"reason": "no_destination",
- "end_call": True,
}
await self._handle_transfer_result(
validation_error_result, function_call_params, properties
@@ -354,7 +352,6 @@ class CustomToolManager:
"message": "I'm sorry, but the transfer destination appears to be invalid. Please contact support to verify the transfer settings.",
"action": "transfer_failed",
"reason": "invalid_destination",
- "end_call": True,
}
await self._handle_transfer_result(
validation_error_result, function_call_params, properties
@@ -369,7 +366,6 @@ class CustomToolManager:
"message": "I'm sorry, but the transfer phone number appears to be invalid. Please contact support to verify the transfer settings.",
"action": "transfer_failed",
"reason": "invalid_destination",
- "end_call": True,
}
await self._handle_transfer_result(
validation_error_result, function_call_params, properties
@@ -388,7 +384,6 @@ class CustomToolManager:
"message": "I'm sorry, there's an issue with this call transfer. Please contact support.",
"action": "transfer_failed",
"reason": "no_organization_id",
- "end_call": False,
}
await self._handle_transfer_result(
validation_error_result, function_call_params, properties
@@ -402,7 +397,6 @@ class CustomToolManager:
"message": "I'm sorry, there's an issue with this call transfer. Please contact support.",
"action": "transfer_failed",
"reason": "provider_does_not_support_transfer",
- "end_call": False,
}
await self._handle_transfer_result(
validation_error_result, function_call_params, properties
@@ -512,7 +506,6 @@ class CustomToolManager:
"message": "I'm sorry, but the call is taking longer than expected to connect. The person might not be available right now. Please try calling back later.",
"action": "transfer_failed",
"reason": "timeout",
- "end_call": True,
}
await self._handle_transfer_result(
timeout_result, function_call_params, properties
@@ -530,7 +523,6 @@ class CustomToolManager:
"message": "I'm sorry, but something went wrong while trying to transfer your call. Please try again later or contact support if the problem persists.",
"action": "transfer_failed",
"reason": "execution_error",
- "end_call": True,
}
await self._handle_transfer_result(
diff --git a/docs/docs.json b/docs/docs.json
index c6e8d42..37c8809 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -43,7 +43,24 @@
"voice-agent/introduction",
"voice-agent/editing-a-workflow",
"voice-agent/template-variables",
- "voice-agent/tools",
+ {
+ "group": "Tools",
+ "pages": [
+ {
+ "group": "Built-in Tools",
+ "pages": [
+ "voice-agent/tools/call-transfer",
+ "voice-agent/tools/end-call"
+ ]
+ },
+ {
+ "group": "Custom Tools",
+ "pages": [
+ "voice-agent/tools/http-api"
+ ]
+ }
+ ]
+ },
{
"group": "Nodes",
"pages": [
diff --git a/docs/voice-agent/tools/call-transfer.mdx b/docs/voice-agent/tools/call-transfer.mdx
new file mode 100644
index 0000000..064df3c
--- /dev/null
+++ b/docs/voice-agent/tools/call-transfer.mdx
@@ -0,0 +1,57 @@
+---
+title: "Call Transfer"
+description: "Enable your AI agent to transfer calls to phone numbers or SIP endpoints with built-in call transfer functionality."
+---
+
+The Call Transfer tool enables your AI agent to transfer active calls to phone numbers or SIP endpoints. When configured, your agent can seamlessly transfer callers to human operators, departments, or other systems while maintaining a professional experience.
+
+## Supported Providers
+
+Call transfer is available for telephony calls using Twilio or Asterisk ARI providers. Web calls do not support transfer functionality.
+
+## How It Works
+
+The Call Transfer tool performs **blind transfers** where no call context is shared with the destination. Here's what happens:
+
+1. **Agent Decision**: Your AI agent determines a transfer is needed and calls the transfer function
+2. **Pre-transfer Message**: (Optional) Agent plays a custom message like "Let me transfer you to our sales team"
+3. **Hold Experience**: Caller hears hold music while the transfer is processed
+4. **Connection**: Once the destination answers, the caller is connected directly
+5. **Agent Handoff**: The AI agent ends its involvement in the call
+
+## Configuration
+
+### Basic Settings
+
+- **Destination**: Phone number or SIP endpoint (see formats below)
+- **Timeout**: How long to wait for destination to answer (default 30 seconds)
+- **Pre-transfer Message**: Optional custom message played before transfer
+
+### Destination Formats
+
+**For Twilio:**
+- **Phone numbers**: E.164 format: `+1234567890`
+- Must be a valid reachable phone number
+
+**For Asterisk ARI:**
+- **SIP endpoints only**: `PJSIP/extension` or `SIP/endpoint`
+- **Examples**: `PJSIP/sales-queue`, `SIP/1001`, `PJSIP/conference-room`
+
+