Enable voice-to-voice tasks in Grok Bot and Cursor. PhoneZero is a runtime plus phone skills. The first skill books a restaurant table by phone; chat reports exactly one outcome: succeeded (booked alias) | unavailable | no_answer | needs_user | unknown | failed. Custom asks: Cursor local skill folder, or Grok interviews into a task JSON. Zero infrastructure. MIT. Sample implementation — use is on you; see Disclaimer. No product support. YMMV. How-to: docs/SKILLS.md.
Setup stops without all of these:
- Telnyx: KYC done, one US number, API key
- xAI: team with Zero Data Retention off, that team’s API key, Voice Agent Builder at console.x.ai
Not on the Cursor Marketplace yet. Grok Bot: point it at this repo and say set this up. Cursor IDE: Customize → Plugins → + Add this repo root.
You were pointed at https://github.com/function1st/PhoneZero. Drive the UI. Do these steps in order. Same playbook: AGENTS.md. After the ids are in session: plugins/phonezero/skills/phonezero-runtime/SKILL.md and the matching phone skill (book-restaurant, or interview a custom phonezero-task — do not ask for a SKILL.md paste).
- Do not Customize → + Add this repo as a Cursor plugin. Stdio Telnyx on Grok → 10009.
- Do not click Authenticate on Telnyx. There is no sign-in.
- Do not take keys in chat. Do not
source ~/.phonezero/env. Do not runscripts/provision.shhere. - Do not search the Telnyx MCP catalog for
whoamior/v2/whoami. Those are not tools. SID islist_billing_groups(step 6). - Do not treat “no Grok xAI package” as “cannot upload.” Add/use the PhoneZero xAI MCP (step 5).
- Do not silently keep PhoneZero as the spoken name. Always ask the Agent Name (step 1, and before each later call unless they said always use one).
- Do not collect destination countries as a PhoneZero setting. They live on the Telnyx outbound voice profile (step 6).
Need: Telnyx KYC + US DID + Telnyx key; xAI team ZDR off + that team’s key; Builder at console.x.ai unless they already said xAI is set up. If missing, stop.
Always ask the spoken name. Do not apply PhoneZero without a reply. Do not ask for countries — those are Telnyx (step 6).
Call settings — reply before we continue
1. Spoken name (required): what the callee hears after “Hello, this is …”
2. Always use that name on later calls? (yes = remember; no = ask every call)
3. AI disclaimer: ON (you may turn this OFF)
Keep answers in session / each phonezero-task. Do not put the name on Edit Values. If they turn disclaimer OFF and Builder already exists, re-paste the prompt once with {disclosure_clause} empty. Before every later call, ask the name again unless they said to always use one.
| Field | Value |
|---|---|
| Name | telnyx |
| URL | https://api.telnyx.com/v2/mcp |
| Header | Authorization = Bearer + the key in that form |
Not stdio, not npx. If Grok-native phonezero-grok exists: install it, Edit Values (keys + From only). Name / disclose stay in chat, per task. .grok/config.toml is the same HTTP Telnyx if this Bot already loads project Grok MCP.
list_api_endpoints → real list, or stop. 401 / 10009 → fix the header. “6 tools” / Needs auth prove nothing.
If put_task or put_booking is already listed, skip. Else Customize → MCPs → stdio xai: copy xai from plugins/phonezero/mcp.json. Real secrets in env, not ${…}. Prove: get_call_config + ensure_collection (PhoneZero bookings). If they said xAI is already set up: do not open the Builder. Ignore the wizard xAI number. Existing Builder agents need a one-time re-paste of prompts/voice-agent.md and prompts/end_call.md before custom skills will speak correctly.
Fallback only if stdio will not start: Bearer on https://api.x.ai/v1 and /v2 (putBooking in plugins/phonezero/scripts/xai-mcp.mjs). 403 + ZDR → stop.
Keep in session. Do not look these up after yes.
TELNYX_ACCOUNT_SID—invoke_api_endpointlist_billing_groupsargs{ "jq_filter": "[.data[].organization_id] | unique" }PHONEZERO_TEXML_APP_ID—invoke_api_endpointlist_texml_applicationsargs{ "filter": { "friendly_name": "PhoneZero" }, "jq_filter": ".data[] | {id, friendly_name, outbound}" }- From —
get_call_config(last-4 in chat) - Destinations — the profile attached to the PhoneZero TeXML app (any name).
list_texml_applications→outbound.outbound_voice_profile_id, theninvoke_api_endpointlist_outbound_voice_profiles{ "jq_filter": ".data[] | {id, name, whitelisted_destinations}" }and pick thatid. No name filter. Show the actual name + codes. This is Telnyx (Mission Control → Voice → Outbound voice profiles), not a PhoneZero field. PATCH only if they ask to add/remove countries.
If app PhoneZero already has an outbound voice profile attached and the DID is on that app: skip create. Use that profile’s name and whitelist as-is. Do not overwrite an existing whitelist unless they asked. Else skill Setup via MCP names: list_outbound_voice_profiles (no name filter) / create_outbound_voice_profiles only if they have none (create-default name PhoneZero unless they pick another; whitelist default ["US"] on create), create_texml_applications (voice_url = https://raw.githubusercontent.com/function1st/PhoneZero/main/texml/inbound.xml, verify 200, attach the chosen profile), update_phone_numbers connection_id. xAI: register_byo_number + attach_agent on your DID if needed.
Plan-first. Ask the Agent Name unless they said always use one. Show Spoken as. Only dial countries on the Telnyx profile whitelist. On yes: put_task (or put_booking alias; wait processed) → calls_accounts_texml_calls with the session ids → poll retrieve_calls_accounts_texml_calls → retrieve_recordings_json_calls_accounts_texml_recordings_json → transcribe → classify → delete_booking (live brief only). Keep the Telnyx recording. Do not paste the audio URL. Owner setup-test to their own confirmed number may skip the hours guard. Custom task: interview into a phonezero-task (docs/SKILLS.md). If they say save as a template, pick memory or put_template and tell them where it went.
- Telnyx KYC + US DID; xAI team ZDR off; keys. docs/SETUP.md.
- Install the Cursor package (
.cursor-plugin/marketplace.json→plugins/phonezero/): Marketplace, Customize → + Add this repo root, orrsync -a plugins/phonezero/ ~/.cursor/plugins/local/phonezero/then Reload Window. - Plugins → Configure:
TELNYX_API_KEY,PHONEZERO_FROM_NUMBER,XAI_API_KEYonly. Spoken name and disclose are per-task. Destinations are Telnyx, not this card. Not SID / TeXML / collection ids. New chat.list_api_endpoints+get_call_config. /setup-phone-callingthen/book-table(or/book-restaurant,/confirm-business-hours). Local private skills: docs/SKILLS.md.
Cursor Telnyx is stdio (npx @telnyx/mcp). Do not add hosted-HTTP Telnyx in the Cursor plugin (SSE GET 404 tombstone). scripts/provision.sh is developer-only on a personal machine — never on the Bot.
Two hosted platforms provide every runtime piece; PhoneZero itself is a skill, prompts, and config.
Me: "Book Joe's Pizza, Friday 7pm, party of 2" (or a custom skill / Grok interview)
▼
Cursor / Grok Bot
│ 1. tries online booking first (OpenTable/Resy via browser); if none:
│ 2. presents the call plan in chat; on my yes:
│ 3. places the call via the Telnyx hosted MCP tool
▼
Telnyx To = sip:{PHONEZERO_FROM_NUMBER}@sip.voice.x.ai;transport=tls (agent answers)
▼
Inline Texml: <Pause length="3"/><Dial>{restaurant}</Dial>
▼
Agent loads phonezero-task.json during the pause, hears ringback, talks to the host
negotiates within the window · classify from the transcript
▼
Chat polls for call completion, fetches recording media_url
(Telnyx MCP) → transcribes with xAI STT (POST /v1/stt, multichannel)
──▶ confirms outcome in chat · books my calendar if asked
(keep the Telnyx recording; delete the live brief)
Verified (Aug 2026): MCP dial → agent answers → collection JSON brief → Pause then callee Dial → dual-channel recording → xAI STT. Keep the Telnyx recording.
| Item | Cost |
|---|---|
| Infrastructure | $0 |
| Telnyx DID | ~$1/mo |
| Telnyx outbound + SIP leg + recording | ~$0.01/min |
| Grok voice agent audio (xAI) | $0.05–0.08/min |
| A 6-minute booking | ≈ $0.40–0.55 |
The agent plans the call in chat and waits for your yes. Facts go in phonezero-task.json in the xAI file collection. One Telnyx MCP call sets To to sip:{PHONEZERO_FROM_NUMBER}@sip.voice.x.ai;transport=tls. Inline TeXML (plugins/phonezero/texml/bridge.xml) pauses 3s then dials the callee. Dual-channel recording is call-level. Telnyx cannot transcribe Dial-verb recordings — fetch media_url, then xAI POST /v1/stt. Keep the recording; delete the live brief after classify (keep templates).
Keys live in Configure / MCP headers only — not the agent shell.
This sample ships with:
- Destinations: whichever Telnyx outbound voice profile is attached to the PhoneZero TeXML app (
whitelisted_destinations; defaultUSonly when PhoneZero creates a new profile). Name and country list are the user’s. Mission Control → Voice → Outbound voice profiles. - AI disclosure: default on in each task (
disclose_ai) and in the one-time Builder paste - Spoken name: Grok always asks (unless they said always use one). Cursor default
PhoneZero. - Recording: dual-channel Telnyx recording on every call; the opener says the call is on a recorded line
- Hours / attempts: runtime + skill defaults (see
plugins/phonezero/skills/phonezero-runtime/SKILL.md)
These are product defaults, not a compliance program.
This repository is a sample implementation and plugin. It is provided AS IS under the MIT License, without warranty of any kind.
You are solely responsible for whether and how you use PhoneZero — including all applicable laws, regulations, and third-party terms (Telnyx, xAI, calling, recording, AI disclosure, privacy). Function1st and the authors/contributors accept no liability for your use, configuration, or implementation.
See also the Disclaimer. Nothing here is legal advice.
