CallCloudAgent Dialer
Agent Dialer · MCP

Give your AI agent a phone line.

Agents can already read, write, and decide. They cannot pick up a phone. So the moment a workflow needs a human voice, it stops and waits for you, and the thing you were automating becomes a task on your list again.

This is a full VoIP line your agent can drive over MCP. It dials real numbers through your own caller ID, detects and drops answering machines, and the second a live human speaks it puts them through. The audio arrives in your browser over WebRTC, so a headset is the whole setup and the person who picks up never waits on a second phone ringing.

Set it upRead the docs
$30 per 1,000 dials. No seat, no subscription, credits do not expire. Answer on a phone or in the browser.

How it works

Four things happen on every call

You give it numbers. Everything that happens between dialing them and a person being on the line is the product.

It dials
Numbers go out through your own caller ID, one at a time or several in parallel.
It screens
Answering-machine detection runs on pickup. Machines are hung up on, never bridged.
It connects
A live human is put through mid-sentence to your browser leg, which is already open, so there is no robotic pause to give it away.
It reports
The call is recorded on split channels, transcribed, and handed back to your agent.
Screening modes

Two ways to screen, and the tradeoff is latency

Every call is answered in your browser, so a screened-in human always has a live leg waiting. What differs is HOW we decide a pickup is a person, and that decision is where connect delay comes from.

amd
Classic detection
The carrier listens to the pickup and rules on the audio. It catches machines that a clock cannot, like a person-sounding greeting on a voicemail. The cost is that it has to hear enough to decide, so every connect carries that delay, including the real people.
Best when your list is full of unknown numbers and a wrong answer is expensive.
gate
Ring-time gate
The rule our own web dialer runs on. Nothing listens to audio. A pickup that arrives faster than a person plausibly could, measured from when the phone actually started ringing, is a machine and is dropped. The verdict lands before the bridge completes, so everything that passes connects with no detection delay at all.
Best when the first second of the call matters, which is most outbound.
dial(numbers=[...])                          // classic detection, the default
dial(numbers=[...], screening="gate")        // instant connect
dial(numbers=[...], screening="gate", gate_ring_seconds=8)

Gate mode fails OPEN: if the ring never registered, the call is treated as a human and put through. Missing a machine costs you a few seconds, wrongly dropping a real person costs you the conversation.

Use cases

What people point it at

It is a tool, not an app, so it composes with whatever your agent already does.

Work a list while you do something else
Hand your agent 200 numbers. It dials them down, drops the answering machines, and only puts you through when a real person is on the line. You answer calls instead of placing them.
Call everyone in this CSV and put them through to me when someone answers.
Follow up the moment something happens
Wire it to whatever your agent already watches. A form fill, a support ticket, a webhook, a row landing in a sheet. Speed to lead measured in seconds, with no human waiting on the queue.
When a demo request comes in, call the number on it and connect them to me.
Get through a confirmation list faster
Appointments, deliveries, renewals, no-shows. You still have the conversations, but you stop dialing, stop waiting through rings, and stop listening to voicemail greetings to find out nobody is home.
Work through tomorrow’s 60 appointments and put each person through.
Let the agent read the call back
Every connected call comes back as a transcript, an AI summary, and a signed recording link. That is what we hand over. What your agent then does with it, draft the follow-up, file it somewhere, pick who to call next, is down to the other tools it has.
Summarise everyone who picked up today.
Slot it in after whatever qualifies the list
We are the phone, not the research. If your agent already has tools that find, enrich or score leads, this picks up where they stop: you hand it the numbers worth calling and it hands back what happened on each one.
Take the accounts you shortlisted and call those numbers.
Put a dialer inside your own product
Live humans arrive over WebRTC in your app. You get the dialing, screening and recording engine without building telephony, and your users never touch a phone number.
dial(numbers=[...], screening="gate")
Setup

Three steps to your first call

Two minutes, and afterwards the only thing you need is somewhere to take the call.

1
Buy dials

Dialing is prepaid: $30 per 1,000 dials, billed once, no subscription behind it. Credits do not expire and do not reset monthly.

dials remaining
2
Create an API key

This authenticates your MCP client. It is shown once and stored only as a hash, so copy it now.

3
Point your MCP client at it

Paste this into your client config (Claude Desktop uses claude_desktop_config.json) and restart the client. Nothing to install: npx fetches the current version each time it launches, so fixes reach you without you doing anything.

{
  "mcpServers": {
    "callcloud-agent-dialer": {
      "command": "npx",
      "args": ["-y", "callcloud-agent-dialer-mcp"],
      "env": {
        "CALLCLOUD_API_KEY": "cak_YOUR_KEY_HERE"
      }
    }
  }
}
Then just ask, in plain language
“Call these 40 leads, skip the voicemails, and put anyone who picks up through to me.”

The agent calls dial with your numbers and a destination, polls run_status until nothing is left, then reads run_results. Give it a number to ring your phone, or "browser" to take the audio in a tab. You just answer the calls that reach you.

Reference

The tools your agent gets

Seven tools. Your agent picks them up automatically once the client restarts.

TOOLWHAT IT DOES
Dialing
dialStart a run over E.164 numbers. screening="amd" uses carrier detection (accurate, adds connect delay); screening="gate" judges on ring time before the bridge (instant connect). Humans land on your browser leg. Returns run_id.
pause_runStop pulling new numbers without losing the queue. In-flight calls finish normally.
resume_runCarry on from where a pause stopped. Re-checks account standing and dial balance first.
stop_runEnd a run and hang up anything live.
hangup_callEnd ONE call and move on, leaving the run dialing. The "next" button in a cockpit.
transfer_callBring a third party into a live call. Warm: all three are on, the rep can then drop. Costs a dial credit.
Reading calls
run_statusPoll a run: counts, the currently bridged call, and credits_remaining.
run_resultsPer-number outcomes with transcript and a signed recording link. Paginated; filter: humans | machines | connected | all.
list_runsPaginated run history, filterable by status and date.
list_callsCall history across the workspace with dispositions, AI summaries, and transcript/recording flags.
get_callOne call in full: transcript, AI summary and next steps, notes, and a 15-minute signed recording link.
Recording outcomes
set_resultRecord a disposition and/or notes on a call. Free text: you own your taxonomy.
schedule_callbackBook a follow-up. Stored and queryable, never auto-dialled.
list_callbacksScheduled callbacks, soonest first. due=true is the work queue to poll.
update_callbackMark a callback done or cancelled, move it, or edit the note.
get_outcomesThe outcome list your UI should offer. Shared with the CallCloud web dialer.
set_outcomesReplace the outcome list. Labels slugged to stable ids, de-duplicated, max 30.
Numbers
list_numbersYour numbers with reputation status, plus how much of the included allotment is left.
search_numbersCarrier inventory in an area code. Read-only, reserves nothing.
provision_numberClaim a number. Free within the allotment, then $1/month (needs a card on file).
release_numberRelease a number and stop its charge. Refuses to release your last one.
list_caller_idsThe numbers this workspace can present as caller ID.
Money and events
get_usageCredits, dials, outcome mix, a chartable daily series, purchase ledger, auto top-up state.
get_analyticsPerformance rather than spend: human-answer rate by caller ID, by hour, by screening mode, plus ring-time percentiles for tuning the gate.
get_webhookWebhook config and delivery health (last status, last error, consecutive failures).
set_webhookRegister the endpoint that receives call events, so you can stop polling.
Events

Webhooks, so you can stop polling

Register one endpoint and we push these to it. Signed HMAC-SHA256 over `${timestamp}.${rawBody}`, so a captured payload cannot be replayed.

EVENTWHEN
call.ringingThe destination started ringing.
call.connectedA screened-in human was put through. Fires while the call is LIVE.
call.voicemailScreened out as a machine and hung up on. Never bridged, never recorded.
call.failedNever reached the network, or the carrier ended it abnormally.
call.completedThe call ended. Carries duration and final verdict.
call.transcriptTranscription finished. Lands after call.completed.
run.finishedA run reached done or stopped, with final counters.
session.pausedNew dialing stopped. In-flight calls continue.
session.resumedDialing resumed.
rep.disconnectedThe browser leg went away. With no leg online, screened-in humans are hung up on.

The answer-to-bridge path is handled entirely server-side and never waits on your endpoint: a human is conferenced into your browser leg first, and the event follows. Nothing you build sits between a prospect answering and your rep hearing them.

Browser audio

Wiring the VoIP leg into your own app

What connect_to: "browser" needs behind it. Your backend mints a short-lived browser token with your API key, your frontend goes online with it, and live humans arrive over WebRTC.

// your backend (keeps the cak_ key server-side)
POST https://dialer.callcloud.app/api/agent-dialer/browser-token
  Authorization: Bearer cak_...
  -> { sw_token, browser_token, dial_number, pin, session_id }

// your frontend: copy app/components/useAgentBrowserLine.ts + npm i @signalwire/js
const line = useAgentBrowserLine()   // line.goOnline(), line.call, line.goOffline()

// your agent, via MCP:
dial(numbers=[...], connect_to="browser")

Working reference build you can try right now: /mcp/console.

Build on it

Handing this to a coding agent

If you are building your own UI around the dialer, there is a full integration guide written to be pasted straight into an agent's context: exact request and response shapes, the credential model, the run lifecycle, and the browser-leg mechanics.

POINT YOUR AGENT AT THESE
cdn.jsdelivr.net/npm/callcloud-agent-dialer-mcp/openapi.yaml
cdn.jsdelivr.net/npm/callcloud-agent-dialer-mcp/INTEGRATION.md
cdn.jsdelivr.net/npm/callcloud-agent-dialer-mcp/BUILD-A-DIALER.md
OpenAPI 3.1, no auth, no login. Generate the client from the spec rather than from prose: it removes the whole class of bug where an agent invents a plausible field name. The guides cover what a schema cannot express.
INTEGRATION.md covers the things that are easy to get wrong from the API surface alone: which credential may reach a browser and which may never, why answered_by: "unknown"is a connected human rather than an error, why the online indicator has to come from the server, and why a "connecting" spinner is the wrong UI for a product whose whole point is that there is nothing to wait for.
Both screening modes
What each one decides, where it decides it, and which to default to.
Full API reference
Every endpoint with real request and response bodies, and the four error codes worth a UI.
Browser leg mechanics
Token minting, the DTMF bind, heartbeats, and going offline cleanly.
UI requirements
The behaviours that fall out of the mechanics rather than out of taste.
Build a full cockpit
BUILD-A-DIALER.md: the parallel-dialer blueprint, concurrency model, screen layout, and a pre-ship checklist.
Details

Things worth knowing before you dial

Does the AI talk to the person?
No. This is not a voice bot. The agent does the dialing and the screening, and a real human has the conversation: whoever is on the browser leg. Nothing synthetic is ever spoken to the person who picks up.
What counts as a dial?
One credit per number handed to the carrier. A number that never reaches the network (bad format, no caller ID available, a run you stopped first) is never charged. If a run runs out mid-way it stops at the credit that ran out rather than overshooting.
What happens to answering machines?
They are hung up on and never bridged or recorded, so you never listen to voicemail. Both modes fail OPEN on an ambiguous verdict and put the call through: missing a machine costs seconds, dropping a real person costs the conversation.
Do I need a seat or a subscription?
No. This product is prepaid dials only. The parallel dialer with seats is a separate thing and you do not need it to use this.
Which number does it call from?
Any number your workspace owns. Pass caller_id to pick one, or leave it out and it uses your first active number. list_caller_ids shows the options.
Do I need a phone at all?
No, and there is no option to use one. Audio arrives over WebRTC in a tab, so a laptop and a headset is the whole setup. Ringing a phone after the prospect answers would make them wait through your ring time, which is the delay this product exists to remove.
Is it recorded?
Connected human calls are recorded on separate channels and transcribed automatically, which is what makes the speaker split clean. Machines are never recorded.
Can I use it before my account is approved?
No. Outbound calling is gated on account verification for every product here, including this one. If your account is pending or suspended, dial returns 403 until that is resolved.
Ready when you are
$30 per 1,000 dials. No seat, no subscription, no expiry.
Base URL https://dialer.callcloud.app