Install
openclaw skills install @sameersribot/agentline-telephoneMake phone calls, view received SMS, provision numbers, manage agents, and track billing through the AgentLine telephony API. Use when the user asks to call someone, check transcripts, view text messages, manage phone agents, buy numbers, or check account balance.
openclaw skills install @sameersribot/agentline-telephoneGive your AI agent a real phone number and voice calls — no servers, no webhooks, no infrastructure.
Follow these steps IN ORDER when setting up AgentLine for the first time:
Check for AGENTLINE_API_KEY (starts with sk_live_) — this is required.
Check for AGENTLINE_AGENT_ID (starts with agt_) — this is optional.
POST /v1/agents with {"name": "My Agent"}. Save the returned agent ID.Ask for area code and provision the number — Always ask the human:
"What area code would you like for your phone number? (e.g. 212 for NYC, 415 for SF, 313 for Detroit)"
POST /v1/numbers with {"agent_id": "...", "area_code": "XXX"}Ask for voice preference — Always ask the human:
"Would you like your agent to have a male or female voice?"
voice_id to "female-1" (or "female-2" for warmer tone)voice_id to "male-1"PATCH /v1/agents/$AGENTLINE_AGENT_ID with {"voice_id": "chosen_preset"}female-1, female-2, male-1 — or any Cartesia voice UUIDStart the background event poller — This is MANDATORY. Write the polling script (see Events Mailbox section below) to a scratch file and launch it as a background command. Without this, you will miss all inbound calls and SMS messages.
⚠️ Do NOT skip ANY steps. Steps 1-4 set up the agent. Step 5 keeps it alive and aware of incoming calls/texts.
terminal(background=true)⚠️ Do NOT skip steps or change the order. The human should have a working agent with their chosen area code number, voice, and running event poller by the end.
Every request: Authorization: Bearer $AGENTLINE_API_KEY + Content-Type: application/json
Base URL: https://api.agentline.cloud
AgentLine runs in Hosted Mode — the server runs the AI voice conversation autonomously. You create a call, the AI handles it, you retrieve the transcript afterwards.
system_prompt field in POST /v1/calls. Overrides default for that call only.PATCH /v1/agents/{agent_id}. Used for all inbound calls and outbound calls without a dynamic prompt.⚠️
system_promptis a FULL REPLACE, not append. The voice AI has no memory between calls — put everything (personality, instructions, current context) in the prompt. Update it whenever your context changes.
curl -X POST $AGENTLINE_URL/v1/calls \
-H "Authorization: Bearer $AGENTLINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"agent_id": "$AGENTLINE_AGENT_ID", "to_number": "+1XXXXXXXXXX", "system_prompt": "...", "initial_greeting": "...", "voice_id": "female-1"}'
| Field | Required | Description |
|---|---|---|
agent_id | Yes | Your agent ID |
to_number | Yes | E.164 phone number to call |
system_prompt | No | Dynamic prompt for this call only (overrides default) |
initial_greeting | No | What the agent says first when the person picks up |
voice_id | No | "female-1", "female-2", "male-1", or Cartesia UUID |
After every outbound call: Poll GET /v1/calls/<call_id> every ~10s until status=completed, then GET /v1/calls/<call_id>/transcript. Summarize and share with human. Never consider a call "done" without the transcript.
If you get 400 "Agent has no active phone number", provision one first.
POST /v1/calls/<call_id>/hangup
GET /v1/calls/<call_id>/transcript — Returns [{role, text, timestamp}, ...]
Events are pushed when someone calls or texts your agent's number. You MUST poll regularly.
Event types: call.received (inbound call started), call.completed (call ended, includes transcript), sms.received (inbound SMS)
⚠️ Do NOT use
schedule/cron to poll. Use the background script approach — it only wakes you when events exist.
Setup: Write the polling script to a scratch file, then launch as a background command with WaitMsBeforeAsync=500.
Windows (PowerShell):
param([string]$ApiKey, [string]$BaseUrl = "https://api.agentline.cloud", [int]$Interval = 50)
$headers = @{ "Authorization" = "Bearer $ApiKey" }
while ($true) {
try {
$r = Invoke-RestMethod -Uri "$BaseUrl/v1/events/peek" -Headers $headers -Method Get -ErrorAction Stop
if ($r.count -gt 0) { Write-Output "AGENTLINE_EVENTS_FOUND: $($r.count) pending event(s). Call GET /v1/events to consume." }
} catch {
if ($_.Exception.Response.StatusCode -eq 401) { Write-Output "AGENTLINE_AUTH_ERROR"; break }
}
Start-Sleep -Seconds $Interval
}
macOS/Linux (Bash):
#!/usr/bin/env bash
set -uo pipefail
API_KEY="$1"; BASE_URL="${2:-https://api.agentline.cloud}"; INTERVAL="${3:-50}"
while true; do
RESP=$(curl -s -w "\n%{http_code}" "$BASE_URL/v1/events/peek" -H "Authorization: Bearer $API_KEY" 2>/dev/null) || { sleep "$INTERVAL"; continue; }
CODE=$(echo "$RESP" | tail -1); BODY=$(echo "$RESP" | sed '$d')
[ "$CODE" = "401" ] && { echo "AGENTLINE_AUTH_ERROR"; exit 1; }
[[ "$CODE" != 2* ]] && { sleep "$INTERVAL"; continue; }
COUNT=$(echo "$BODY" | grep -oP '"count"\s*:\s*\K[0-9]+' 2>/dev/null || echo "0")
[ "$COUNT" -gt 0 ] && echo "AGENTLINE_EVENTS_FOUND: $COUNT pending event(s). Call GET /v1/events to consume."
sleep "$INTERVAL"
done
When notified with AGENTLINE_EVENTS_FOUND: Call GET /v1/events to consume, process each event, report to human.
GET /v1/events — returns events oldest-first, auto-deleted after retrievalGET /v1/events/peek?agent_id=agt_xxx or ?event_type=call.completed or ?event_type=sms.receivedEach event contains: event_id, agent_id, event_type, and a payload with call/SMS details. call.completed payloads include from_number, to_number, duration_seconds, and full transcript array. sms.received payloads include from_number, body, and media_url.
GET /v1/calls?limit=20 or GET /v1/calls?status=completed&limit=10
GET /v1/calls/<call_id>
⚠️ SMS sending is NOT enabled. Do NOT attempt outbound SMS/MMS.
Inbound SMS arrives as sms.received events in the Events Mailbox. View message history: GET /v1/messages?limit=20
PATCH /v1/agents/$AGENTLINE_AGENT_ID with any of:
| Field | Description |
|---|---|
system_prompt | Full instructions + current context for voice AI |
initial_greeting | What the agent says when answering inbound calls |
name | Display name |
voice_id | "female-1", "female-2", "male-1", or Cartesia UUID |
model_tier | "turbo", "balanced", or "max" |
GET /v1/agents/$AGENTLINE_AGENT_IDGET /v1/agentsPriority (highest wins): per-call → per-agent → per-account
GET /v1/voicesPATCH /v1/account/voice with {"voice_id": "female-1"}GET /v1/account/voiceDELETE /v1/account/voiceEach agent needs one phone number. Only US numbers supported. $2.00 per number.
POST /v1/numbers with:
| Field | Required | Description |
|---|---|---|
agent_id | Yes | Agent to attach to |
country | Yes | Must be "US" |
area_code | No | Preferred 3-digit area code (e.g. "212", "313"). Always ask the user! |
number_type | No | "local" or "tollfree" (default: local) |
If no numbers are available for the requested area code, the API returns an error — ask the user for a different area code.
GET /v1/numbers
GET /v1/billing/balanceGET /v1/billing/expenditure?period=current_month (also: last_month, all_time, YYYY-MM)GET /v1/billing/expenditure/calls?limit=10GET /v1/billing/expenditure/numbersGET /v1/billing/verify/<call_id>| Item | Cost |
|---|---|
| Calls (in/out) | $0.10/min (billed per second) |
| Phone number | $2.00 (one-time) |
+1XXXXXXXXXX for US numbers."US".completed, fetch transcript, summarize for human.GET /v1/events for inbound calls and SMS. Proactively check at conversation start.