twilio-voice-outbound-calls
Make outbound phone calls via Twilio's Programmable Voice REST API. Covers the full voice platform: calls.create(), answering machine detection (AMD), conference-based agent bridging, call recording, status tracking, and SIP Trunking. Use this skill for outbound calls, sales dialers, or when asking what voice APIs are available.
What this skill does
## Overview
> **Agent safety:** Before placing an outbound call, always confirm the recipient number and intent with the user. Outbound calls are irreversible and may incur charges. For automated systems, implement TCPA compliance: obtain prior express consent, respect quiet hours (8 AM–9 PM recipient local time), and maintain a Do Not Call list.
Every outbound call requires a `from` Twilio number, a `to` recipient, and TwiML instructions that define what happens when the call is answered — either as a webhook URL or inline.
---
## Voice Platform Capabilities
Outbound calls go beyond basic `calls.create()`. Here's what you can build:
| Capability | How | When to use |
|-----------|-----|-------------|
| **Basic outbound call** | `calls.create()` with TwiML or webhook URL | Any outbound call — see Quickstart below |
| **Answering Machine Detection (AMD)** | `machineDetection` parameter on `calls.create()` | Sales dialers, call campaigns — filter voicemail from humans |
| **Conference-based agent bridging** | `<Dial><Conference>` in TwiML | Connect agents to live prospects with whisper, barge, hold |
| **SIP Trunking** | Elastic SIP Trunking | Bring your own carrier for outbound calls — cost reduction at scale |
| **Call Recording** | `record=True` on `calls.create()` or `<Record>` verb | Compliance, QA, training |
| **Voice Insights** | Automatic per-call metrics | Call quality monitoring — latency, jitter, packet loss, answer rates |
| **AI Voice Agents** | ConversationRelay + LLM | Real-time speech recognition → LLM → TTS for conversational AI |
For TwiML verbs (Say, Gather, Dial, Record, Conference, Pay), see `twilio-voice-twiml`.
For AI voice agents, see `twilio-voice-conversation-relay`.
---
## Prerequisites
- Twilio account with a voice-capable phone number
— New to Twilio? See `twilio-account-setup` for signup, getting a number, and trial limitations
— Trial accounts can only call verified numbers
- Environment variables:
- `TWILIO_ACCOUNT_SID`
- `TWILIO_AUTH_TOKEN`
— See `twilio-iam-auth-setup` for credential setup and best practices
- SDK: `pip install twilio` / `npm install twilio`
---
## Quickstart
**Python**
```python
import os
from twilio.rest import Client
client = Client(os.environ["TWILIO_ACCOUNT_SID"], os.environ["TWILIO_AUTH_TOKEN"])
call = client.calls.create(
from_="+15017122661", # Your Twilio number (E.164)
to="+15558675310", # Recipient (E.164)
twiml="<Response><Say>Your order has shipped. Goodbye.</Say></Response>"
)
print(call.sid) # CAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
print(call.status) # queued | ringing | in-progress | completed | failed
```
**Node.js**
```node
const twilio = require("twilio");
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
const call = await client.calls.create({
from: "+15017122661",
to: "+15558675310",
twiml: "<Response><Say>Your order has shipped. Goodbye.</Say></Response>",
});
console.log(call.sid);
console.log(call.status);
```
---
## Key Patterns
### Use a Webhook URL for Dynamic Call Handling
Pass a `url` instead of inline `twiml` — Twilio POSTs to your server when the call connects and executes the TwiML you return.
**Python**
```python
call = client.calls.create(
from_="+15017122661",
to="+15558675310",
url="https://yourapp.com/twiml/welcome"
)
```
**Node.js**
```node
const call = await client.calls.create({
from: "+15017122661",
to: "+15558675310",
url: "https://yourapp.com/twiml/welcome",
});
```
**Python (Flask) — TwiML webhook handler**
```python
from flask import Flask
from twilio.twiml.voice_response import VoiceResponse
app = Flask(__name__)
@app.route("/twiml/welcome", methods=["POST"])
def welcome():
response = VoiceResponse()
response.say("Hello! Press 1 to hear your account balance.")
response.gather(num_digits=1, action="/twiml/handle-input")
return str(response)
```
**Node.js (Express) — TwiML webhook handler**
```node
const { VoiceResponse } = require("twilio").twiml;
app.post("/twiml/welcome", (req, res) => {
const response = new VoiceResponse();
response.say("Hello! Press 1 to hear your account balance.");
response.gather({ numDigits: 1, action: "/twiml/handle-input" });
res.type("text/xml").send(response.toString());
});
```
For all TwiML verbs (Say, Gather, Dial, Record, Conference), see `twilio-voice-twiml`.
### Track Call Status
**Python**
```python
call = client.calls.create(
from_="+15017122661",
to="+15558675310",
url="https://yourapp.com/twiml/welcome",
status_callback="https://yourapp.com/call-status",
status_callback_method="POST"
)
```
**Node.js**
```node
const call = await client.calls.create({
from: "+15017122661",
to: "+15558675310",
url: "https://yourapp.com/twiml/welcome",
statusCallback: "https://yourapp.com/call-status",
statusCallbackMethod: "POST",
});
```
Status transitions: `queued → ringing → in-progress → completed` (or `failed`/`busy`/`no-answer`).
### Record a Call
**Python**
```python
call = client.calls.create(
from_="+15017122661",
to="+15558675310",
url="https://yourapp.com/twiml/welcome",
record=True,
recording_status_callback="https://yourapp.com/recording-ready"
)
```
**Node.js**
```node
const call = await client.calls.create({
from: "+15017122661",
to: "+15558675310",
url: "https://yourapp.com/twiml/welcome",
record: true,
recordingStatusCallback: "https://yourapp.com/recording-ready",
});
```
Recordings accessible at `https://api.twilio.com/2010-04-01/Accounts/{AccountSid}/Recordings`.
---
## Answering Machine Detection (AMD)
Detect whether a human or voicemail answers before connecting an agent or leaving a message. Two modes:
| Mode | Behavior | Best for |
|------|----------|----------|
| `Enable` | Returns result immediately when human/machine first detected | **Sales dialers** — connect agent to humans ASAP |
| `DetectMessageEnd` | Waits for voicemail greeting to finish (beep/silence) | **Leaving voicemail** — wait for beep, then play/record message |
**Python — Sales dialer (connect agents to live answers only)**
```python
call = client.calls.create(
from_="+15017122661",
to="+15558675310",
url="https://yourapp.com/handle-answer",
machine_detection="Enable", # Immediate detection — use for live-agent connect
async_amd=True, # Non-blocking — call connects while AMD analyzes
async_amd_status_callback="https://yourapp.com/amd-result",
async_amd_status_callback_method="POST"
)
```
**Node.js**
```javascript
const call = await client.calls.create({
from: "+15017122661",
to: "+15558675310",
url: "https://yourapp.com/handle-answer",
machineDetection: "Enable",
asyncAmd: true,
asyncAmdStatusCallback: "https://yourapp.com/amd-result",
asyncAmdStatusCallbackMethod: "POST",
});
```
**AMD webhook delivers `AnsweredBy` parameter:**
| Value | Meaning | Action |
|-------|---------|--------|
| `human` | Live person detected | Connect to agent |
| `machine_start` | Machine detected, greeting still playing | Hang up or wait |
| `machine_end_beep` | Voicemail beep heard | Leave message |
| `machine_end_silence` | Silence after greeting | Leave message |
| `fax` | Fax tone detected | Hang up |
| `unknown` | Could not determine | Treat as human or retry |
**Conference-based agent bridging** (production pattern for sales dialers):
```python
# In /handle-answer webhook — when AMD says "human":
response = VoiceResponse()
dial = response.dial()
dial.conference(
f"Sales-{call_sid}",
start_conference_on_enter=False, # Prospect waits for agent
end_conference_on_exit=True
)
# Separately, dial agent into same conference:
client.calls.create(
from_="+15017122661",
to=agent_number,
twiml=f'<Response><Dial><Conference startConferenceOnEnter="true">Sales-{call_sid}</Conference></Dial></Response>'
)
```
This pattRelated in Image & Video
watch
IncludedWatch a video (URL or local path). Downloads with yt-dlp, extracts auto-scaled frames with ffmpeg, pulls the transcript from captions (or Whisper API fallback), and hands the result to Claude so it can answer questions about what's in the video.
physical-ai-defect-image-generation
IncludedUse when the user wants to orchestrate defect image generation, run associated setup, or handle outputs on OSMO. The Day 0 path handles cold-start with USD-to-ROI, image-edit augmentation, and AnomalyGen to create initial PCBA datasets. The Day 1 path performs inference and labeling on real images. This skill helps with first-time asset setup, creation of finetuning checkpoints, and configuring deployment. Trigger keywords: defect image generation, dig workflow, dig pipeline, defect image detection workflow, aoi pipeline, aoi anomalygen, usd2roi anomalygen, day 0 pcba, day 1 pcba, day 1 real-photo alignment, day 1 manual roi, metal surface anomaly, glass defect, anomalygen finetune, setup_pcb, setup_metal, setup_glass, setup_pretrained, dig setup, dig datasets, dig pretrained checkpoint, dig image-edit endpoint.
accelint-react-best-practices
IncludedReact performance optimization and best practices. ALWAYS use this skill when working with any React code - writing components, hooks, JSX; refactoring; optimizing re-renders, memoization, state management; reviewing for performance; fixing hydration mismatches; debugging infinite re-renders, stale closures, input focus loss, animations restarting; preventing remounting; implementing transitions, lazy initialization, effect dependencies. Even simple React tasks benefit from these patterns. Covers React 19+ (useEffectEvent, Activity, ref props). Triggers - useEffect, useState, useMemo, useCallback, memo, inline components, nested components, components inside components, re-render, performance, hydration, SSR, Next.js, useDeferredValue, combined hooks.
elevenlabs-agents
IncludedBuild conversational AI voice agents with ElevenLabs Platform using React, JavaScript, React Native, or Swift SDKs. Configure agents, tools (client/server/MCP), RAG knowledge bases, multi-voice, and Scribe real-time STT. Use when: building voice chat interfaces, implementing AI phone agents with Twilio, configuring agent workflows or tools, adding RAG knowledge bases, testing with CLI "agents as code", or troubleshooting deprecated @11labs packages, Android audio cutoff, CSP violations, dynamic variables, or WebRTC config. Keywords: ElevenLabs Agents, ElevenLabs voice agents, AI voice agents, conversational AI, @elevenlabs/react, @elevenlabs/client, @elevenlabs/react-native, @elevenlabs/elevenlabs-js, @elevenlabs/agents-cli, elevenlabs SDK, voice AI, TTS, text-to-speech, ASR, speech recognition, turn-taking model, WebRTC voice, WebSocket voice, ElevenLabs conversation, agent system prompt, agent tools, agent knowledge base, RAG voice agents, multi-voice agents, pronunciation dictionary, voice speed control, elevenlabs scribe, @11labs deprecated, Android audio cutoff, CSP violation elevenlabs, dynamic variables elevenlabs, case-sensitive tool names, webhook authentication
humanizer
IncludedHumanize AI-generated text by detecting and removing patterns typical of LLM output. Rewrites text to sound natural, specific, and human. Uses 28 pattern detectors, 560+ AI vocabulary terms across 3 tiers, and statistical analysis (burstiness, type-token ratio, readability) for comprehensive detection. Use when asked to humanize text, de-AI writing, make content sound more natural/human, review writing for AI patterns, score text for AI detection, or improve AI-generated drafts. Covers content, language, style, communication, and filler categories.
generating-mermaid-diagrams
IncludedSalesforce architecture diagrams using Mermaid with ASCII fallback. Use this skill when generating text-based diagrams for Salesforce architecture, OAuth flows, ERDs, integration sequences, or Agentforce structure. TRIGGER when: user says "diagram", "visualize", "ERD", or asks for sequence diagrams, flowcharts, class diagrams, or architecture visualizations in Mermaid. DO NOT TRIGGER when: user wants PNG/SVG image output (use generating-visual-diagrams), or asks about non-Salesforce systems.