Skip to main content

Open-source outbound call-control runtime for agent builders

Project description

call-use

PyPI Tests License: MIT Python 3.11+ Docs Website

Give your AI agent the ability to make phone calls. The browser-use for phones.

from call_use import CallAgent

outcome = await CallAgent(phone="+18001234567", instructions="Cancel my subscription").call()
print(outcome.disposition)  # "completed"

What it does

  • Dials outbound via Twilio SIP trunk through LiveKit
  • Talks using Deepgram STT + GPT-4o + GPT-4o-mini TTS
  • Reports structured CallOutcome with transcript, events, and disposition
  • Human takeover — pause the agent mid-call and take over the conversation
  • Approval flow — agent asks for user approval before taking sensitive actions
  • REST API — deploy as a service with create_app() for multi-tenant usage

Why call-use?

call-use Build from scratch Pine AI
Make a phone call 3 lines months sign up + $$$
IVR navigation built-in weeks built-in
Live transcript built-in weeks built-in
Human takeover built-in weeks
Approval flow built-in days
Open source yes no
Self-hostable yes no
Any agent framework yes no

Works with

Claude Code · LangChain · OpenAI Agents · CrewAI · Any agent that runs bash

Architecture

┌──────────────┐         ┌──────────────┐         ┌──────────────┐
│  Your code   │────────▶│  LiveKit      │────────▶│  Twilio SIP  │
│  (CallAgent) │  room   │  Cloud/OSS    │  trunk  │  → PSTN      │
└──────────────┘         └──────────────┘         └──────────────┘
                               │
                         ┌─────┴──────┐
                         │ call-use   │
                         │ worker     │
                         │ (Agent)    │
                         └────────────┘

Two processes:

  1. Your code (or the REST API) creates a LiveKit room and dispatches an agent
  2. call-use worker joins the room, dials via SIP, runs the conversation, and publishes the outcome

Quick start

Prerequisites

  • Python 3.11+
  • LiveKit Cloud or self-hosted LiveKit server
  • Twilio SIP trunk connected to LiveKit
  • Deepgram API key (for STT)
  • OpenAI API key (for LLM + TTS)

Install

pip install call-use

Configure

cp .env.example .env
# Fill in your keys

Required environment variables:

Variable Description
LIVEKIT_URL LiveKit server URL (wss://...)
LIVEKIT_API_KEY LiveKit API key
LIVEKIT_API_SECRET LiveKit API secret
SIP_TRUNK_ID Twilio SIP trunk ID in LiveKit
DEEPGRAM_API_KEY Deepgram API key (STT)
OPENAI_API_KEY OpenAI API key (LLM + TTS)

Run the worker

call-use-worker start

Make a call

import asyncio
from call_use import CallAgent

async def main():
    agent = CallAgent(
        phone="+18001234567",
        instructions="Ask about store hours",
        approval_required=False,
    )
    outcome = await agent.call()
    print(f"Done: {outcome.disposition.value}")

asyncio.run(main())

SDK usage

CallAgent

agent = CallAgent(
    phone="+18001234567",           # US/Canada number (required)
    instructions="Your task...",     # What the agent should do (required)
    user_info={"name": "Alice"},     # Info the agent can reference
    caller_id="+15551234567",        # Outbound caller ID
    voice_id="alloy",                # TTS voice (alloy/echo/fable/onyx/nova/shimmer)
    approval_required=True,          # Agent asks before sensitive actions
    timeout_seconds=600,             # Max call duration
    on_event=my_event_handler,       # Real-time event callback
    on_approval=my_approval_handler, # Approval decision callback
    recording_disclaimer="This call may be recorded.",
)

Events

The on_event callback receives CallEvent objects:

Event type Description
state_change Call state changed (connected, human_takeover, etc.)
transcript New speech transcript (speaker + text)
dtmf DTMF tone detected
approval_request Agent needs user approval
call_complete Call finished with outcome

Human takeover

# Pause agent, get token to join as human
token = await agent.takeover()
# ... join LiveKit room with token, talk to callee ...
await agent.resume()  # Hand back to agent

CallOutcome

outcome = await agent.call()
outcome.task_id          # Unique call identifier
outcome.disposition      # completed | failed | voicemail | no_answer | busy | timeout | cancelled
outcome.duration_seconds # Call duration
outcome.transcript       # List of {speaker, text} dicts
outcome.events           # List of CallEvent dicts

CLI

Any agent that can run bash can make phone calls:

pip install call-use
call-use dial "+18001234567" -i "Ask about store hours"

Events stream to stderr, structured JSON result goes to stdout:

call-use dial "+18001234567" -i "Cancel subscription" -u '{"account": "12345"}'
# stdout: {"task_id": "...", "disposition": "completed", "transcript": [...]}

MCP Server

Native tool integration for Claude Code, Codex, and other MCP-compatible agents:

{
  "mcpServers": {
    "call-use": {
      "command": "call-use-mcp",
      "env": {
        "LIVEKIT_URL": "wss://...",
        "LIVEKIT_API_KEY": "...",
        "LIVEKIT_API_SECRET": "...",
        "SIP_TRUNK_ID": "...",
        "OPENAI_API_KEY": "..."
      }
    }
  }
}

4 async tools: dial (non-blocking, returns task_id), status, cancel, result.

REST API

For multi-tenant or server deployments:

from call_use import create_app

app = create_app(api_key="your-secret-key")
# Run with: uvicorn your_module:app

Endpoints

Method Path Description
POST /calls Create a new outbound call
GET /calls/{id} Get call status and room state
POST /calls/{id}/inject Inject a message into the call
POST /calls/{id}/takeover Human takeover
POST /calls/{id}/resume Resume agent after takeover
POST /calls/{id}/approve Approve pending action
POST /calls/{id}/reject Reject pending action
POST /calls/{id}/cancel Cancel the call

All endpoints require X-API-Key header.

Examples

Development

git clone https://github.com/agent-next/call-use.git
cd call-use
pip install -e ".[dev]"
pytest

Known Limitations

  • In-memory state: The REST API server stores call state in memory. State is lost on restart. For production, consider using LiveKit room metadata for call recovery, or contribute a persistence backend.
  • Caller ID: v0.1 validates caller ID format only. Ownership verification (via Twilio Lookup API) is planned for v0.2.
  • Single worker: The agent worker is designed for single-instance deployment. Horizontal scaling requires a shared state backend.
  • PSTN only: Currently supports outbound PSTN calls via Twilio SIP. WebRTC-to-WebRTC calls are not yet supported.

Legal Notice

call-use is a developer tool for legitimate business automation. Users are solely responsible for complying with all applicable telecommunications laws, including but not limited to:

  • TCPA (Telephone Consumer Protection Act) — Obtain prior express consent before automated calls
  • FCC regulations — AI-generated voices in calls are subject to full TCPA restrictions (FCC 24-17)
  • Do Not Call Registry — Honor opt-out requests and scrub against the National DNC Registry
  • Recording consent — Comply with federal and state recording laws (13 US states require two-party consent)
  • Caller ID — Display accurate caller ID; spoofing for fraudulent purposes is illegal
  • State and local laws — Additional restrictions may apply in your jurisdiction

call-use includes built-in safeguards (premium-rate number blocking, rate limiting, phone validation) but these do not guarantee legal compliance. Consult legal counsel before deploying automated calling systems.

This software is provided "AS IS" under the MIT License without warranty. See LICENSE for details.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

call_use-0.1.0.tar.gz (66.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

call_use-0.1.0-py3-none-any.whl (30.2 kB view details)

Uploaded Python 3

File details

Details for the file call_use-0.1.0.tar.gz.

File metadata

  • Download URL: call_use-0.1.0.tar.gz
  • Upload date:
  • Size: 66.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for call_use-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b279d57cdc2114897d60a17fefdce44e740d8a79e0ccd285f4f11e50e110e068
MD5 68bc150b523c6290d0cb43a021ead527
BLAKE2b-256 52f4722d5b7b10334167c77e4f3dac7445698a058cc19a4491c8cc0d7cbf5377

See more details on using hashes here.

File details

Details for the file call_use-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: call_use-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 30.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for call_use-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3b835d496961af338d33ac46e0cc19c3a2167a66d91869c092cb59819c31014b
MD5 1fb6d83d82bafd7486efbd0a15b592f9
BLAKE2b-256 72772b53f53cd851efcef174cacc9f051890f7243342f4eb468f8ce4091dcbdc

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page