diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 3b884b3..f0baca8 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -5,7 +5,7 @@ }, "metadata": { "description": "Phone skills for voice tasks (restaurant booking first). Need: Telnyx KYC + one US number, xAI team with ZDR off, API keys, Voice Agent Builder.", - "version": "0.4.2" + "version": "0.4.3" }, "plugins": [ { diff --git a/AGENTS.md b/AGENTS.md index 7d1bf90..314adfb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,21 +29,27 @@ Need: Telnyx KYC + US DID + Telnyx key; xAI team **ZDR off** + that team’s key ### 1. Call identity — ask in chat, wait -Do **not** silently keep defaults. “Set this up” is not consent to these. Show this card and wait for a reply. **Do not ask for destination countries** — those live on Telnyx (step 6). +Do **not** silently keep PhoneZero. “Set this up” is not a spoken name. **Always ask** what Agent Name the callee should hear, and wait. PhoneZero is an example they may choose, not a default you apply without a reply. **Do not ask for destination countries** — those live on Telnyx (step 6). ``` -Call settings (defaults — change any now) +Call settings — reply before we continue -1. Spoken name the callee hears: PhoneZero - “Hello, this is {name}…” — keep PhoneZero, or set your name / an alias. +1. Spoken name (required): what should the callee hear after “Hello, this is …”? + Your name, an alias, or PhoneZero — you pick. Do not skip. -2. AI disclaimer in the opener: ON +2. Always use that name on later calls in this Bot? + Yes → remember it (session + memory if available) and do not re-ask. + No → ask again before every call. + +3. AI disclaimer in the opener: ON ON → “…{name}, an automated assistant, calling on a recorded line…” OFF → omit “, an automated assistant,” You may turn this OFF. ``` -Keep their answers in session and put them on each `phonezero-task` (`spoken_name`, `disclose_ai`). Do **not** put name or disclose on the Configure / Edit Values card. If they turn disclaimer OFF and the Builder agent already exists, re-paste `prompts/voice-agent.md` once with `{disclosure_clause}` empty — that paste is the only way to change a baked prompt. Per-call they may still pick a different spoken name. +Keep their answers in session and put the name on each `phonezero-task` (`spoken_name`, `disclose_ai`). Do **not** put name or disclose on the Configure / Edit Values card. If they turn disclaimer OFF and the Builder agent already exists, re-paste `prompts/voice-agent.md` once with `{disclosure_clause}` empty — that paste is the only way to change a baked prompt. + +Before **every later call**, ask the Agent Name again unless they already said to always use one. Then reuse it and show it as Spoken as on the plan. ### 2. Uninstall the wrong plugin @@ -122,7 +128,7 @@ xAI: `list_phone_numbers` → `register_byo_number` if the DID is not `byo_trunk ### 8. Calls -You already have SID, TeXML id, From, spoken name, disclose, and the Telnyx destination list. Read `phonezero-runtime` (plan-first, two attempts, `succeeded` / `booked` only with a live-person confirmation in the transcript). Match a shipped skill, or **interview into a `phonezero-task`** — do not ask them to paste a `SKILL.md` or write `~/.cursor/skills`. Owner setup-test to **their own confirmed number** may skip the hours guard — restaurants may not. The call plan must show Spoken as and only dial countries on that Telnyx whitelist. Per-call they may still override the spoken name. If they ask to save the shape as a template, pick memory or `put_template` and say where it went. +You already have SID, TeXML id, From, disclose, and the Telnyx destination list. **Ask the Agent Name** before the call plan unless they already said to always use the same name. Read `phonezero-runtime` (plan-first, two attempts, `succeeded` / `booked` only with a live-person confirmation in the transcript). Match a shipped skill, or **interview into a `phonezero-task`** — do not ask them to paste a `SKILL.md` or write `~/.cursor/skills`. Owner setup-test to **their own confirmed number** may skip the hours guard — restaurants may not. The call plan must show Spoken as and only dial countries on that Telnyx whitelist. If they ask to save the shape as a template, pick memory or `put_template` and say where it went. On explicit yes, in this order — do not resolve SID again: diff --git a/README.md b/README.md index 601a636..5061b49 100644 --- a/README.md +++ b/README.md @@ -30,24 +30,25 @@ You were pointed at `https://github.com/function1st/PhoneZero`. Drive the UI. Do - Do **not** take keys in chat. Do **not** `source ~/.phonezero/env`. Do **not** run `scripts/provision.sh` here. - Do **not** search the Telnyx MCP catalog for `whoami` or `/v2/whoami`. Those are not tools. SID is `list_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 / AI-disclaimer ON. Ask (step 1) and wait. +- 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). ### 0. Vendor gate Need: Telnyx KYC + US DID + Telnyx key; xAI team **ZDR off** + that team’s key; Builder at [console.x.ai](https://console.x.ai) unless they already said xAI is set up. If missing, stop. -### 1. Ask in chat — name and AI disclaimer (wait) +### 1. Ask in chat — Agent Name and AI disclaimer (wait) -Do **not** keep defaults silently. Show this and wait. **Do not ask for countries** — those are Telnyx (step 6). +**Always ask** the spoken name. Do not apply PhoneZero without a reply. **Do not ask for countries** — those are Telnyx (step 6). ``` -Call settings (defaults — change any now) -1. Spoken name: PhoneZero -2. AI disclaimer: ON (you may turn this OFF) +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) ``` -Write answers into Edit Values / xAI env. If they turn disclaimer OFF and Builder already exists, re-paste the prompt once with `{disclosure_clause}` empty. +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. ### 2. Uninstall Cursor PhoneZero if it is installed @@ -86,7 +87,7 @@ If app **PhoneZero** already has an outbound voice profile attached and the DID ### 8. First call -Plan-first. 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](docs/SKILLS.md)). If they say save as a template, pick memory or `put_template` and tell them where it went. +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](docs/SKILLS.md)). If they say save as a template, pick memory or `put_template` and tell them where it went. --- @@ -148,7 +149,7 @@ This sample ships with: - **Destinations:** whichever Telnyx outbound voice profile is attached to the PhoneZero TeXML app (`whitelisted_destinations`; default `US` only 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:** `PhoneZero` +- **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`](plugins/phonezero/skills/phonezero-runtime/SKILL.md)) diff --git a/docs/SETUP.md b/docs/SETUP.md index 1694c49..ff97202 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -33,7 +33,7 @@ The Telnyx MCP cannot run until `TELNYX_API_KEY` is saved as a plugin variable. After any update: re-enter **every** required field on the Configure card (a field left blank is cleared on save — see step 9) and start a **new** conversation (existing chats do not pick up a newly installed or updated plugin). - **Grok Bot** (point at `https://github.com/function1st/PhoneZero` and say *set this up*): the Bot follows [AGENTS.md](../AGENTS.md) **Grok Bot — set this up**. It must ask spoken name and AI disclaimer ON/OFF. Destination countries are the Telnyx voice-profile whitelist (not a PhoneZero field). Do not Customize → + Add this repo as the Cursor plugin. Add Telnyx as HTTP MCP `https://api.telnyx.com/v2/mcp` with `Authorization: Bearer` in the MCP form. Add/use the PhoneZero xAI stdio MCP. Resolve SID via `list_billing_groups` (not `whoami`). Do not click Authenticate. + **Grok Bot** (point at `https://github.com/function1st/PhoneZero` and say *set this up*): the Bot follows [AGENTS.md](../AGENTS.md) **Grok Bot — set this up**. It must **always ask** the Agent Name (and whether to always use it) plus AI disclaimer ON/OFF — do not silently keep PhoneZero. Destination countries are the Telnyx voice-profile whitelist (not a PhoneZero field). Do not Customize → + Add this repo as the Cursor plugin. Add Telnyx as HTTP MCP `https://api.telnyx.com/v2/mcp` with `Authorization: Bearer` in the MCP form. Add/use the PhoneZero xAI stdio MCP. Resolve SID via `list_billing_groups` (not `whoami`). Do not click Authenticate. If none of those are available on Cursor IDE: `"telnyx": {"command":"npx","args":["-y","@telnyx/mcp"],"env":{"TELNYX_API_KEY":"${env:TELNYX_API_KEY}"}}`. A masked secret card alone does **not** authenticate an MCP. @@ -56,7 +56,7 @@ To add a country (e.g. Japan): change that Telnyx whitelist in Mission Control, | `TELNYX_API_KEY` | plugin variable (secret) | A | Env for Telnyx stdio MCP (`npx @telnyx/mcp`). Never in chat. | | `PHONEZERO_FROM_NUMBER` | plugin variable | A | Telnyx US DID (E.164): outbound caller ID and SIP bridge target (`sip:{PHONEZERO_FROM_NUMBER}@sip.voice.x.ai;transport=tls`). | | `XAI_API_KEY` | plugin variable (secret) | A | From a team with **ZDR off**. Injected into the PhoneZero xAI MCP only (Files, collections, STT, phone-numbers). Not in the agent shell. | -| Spoken name / disclose | per-task (`phonezero-task.json`) | chat | `spoken_name` and `disclose_ai`. Default PhoneZero / true. Not on the Configure card. `{disclosure_clause}` is pasted once into the Builder prompt. | +| Spoken name / disclose | per-task (`phonezero-task.json`) | chat | `spoken_name` and `disclose_ai`. Grok always asks the name unless they said always use one. Cursor default PhoneZero / true. Not on the Configure card. `{disclosure_clause}` is pasted once into the Builder prompt. | | Destinations | Telnyx voice profile on the PhoneZero TeXML app | Telnyx | `whitelisted_destinations` of whatever profile is attached (`outbound.outbound_voice_profile_id`). Any name, any country list. Mission Control → Voice → Outbound voice profiles. Not a PhoneZero plugin variable. | | `TELNYX_ACCOUNT_SID` | resolved in session | B | TeXML REST account SID. MCP: `list_billing_groups` → `data[].organization_id` (no `whoami` tool). Developer curl: `GET /v2/whoami` → `data.organization_id`. Not on the Configure card. | | `PHONEZERO_TEXML_APP_ID` | resolved in session | B | TeXML application SID. Not on the Configure card. | diff --git a/plugins/phonezero-grok/.grok-plugin/plugin.json b/plugins/phonezero-grok/.grok-plugin/plugin.json index 146014d..2b890bf 100644 --- a/plugins/phonezero-grok/.grok-plugin/plugin.json +++ b/plugins/phonezero-grok/.grok-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "phonezero-grok", "displayName": "PhoneZero (Grok)", - "version": "0.4.2", + "version": "0.4.3", "description": "Grok Bot: phone skills (restaurant first). Telnyx hosted HTTP + PhoneZero xAI stdio. Edit Values for keys. Do not click Authenticate on Telnyx.", "author": { "name": "Function1st" diff --git a/plugins/phonezero-grok/commands/setup-phone-calling.md b/plugins/phonezero-grok/commands/setup-phone-calling.md index a1a21ea..3a83fd6 100644 --- a/plugins/phonezero-grok/commands/setup-phone-calling.md +++ b/plugins/phonezero-grok/commands/setup-phone-calling.md @@ -7,9 +7,10 @@ description: Grok Bot — ask name / AI disclaimer, then wire Telnyx HTTP + xAI You are a computer-use agent. Run **Grok Bot — set this up** in repo-root `AGENTS.md` (same steps in `README.md`) **in order**. Do not install Cursor PhoneZero. Do not click Authenticate. Do not take keys in chat. -After the vendor gate, **ask in chat and wait** before wiring. Do not silently keep defaults: +After the vendor gate, **ask in chat and wait** before wiring. **Always ask** the Agent Name (spoken name). Do not silently use PhoneZero. -- Spoken name (default PhoneZero) — what the callee hears +- Spoken name (required) — what the callee hears. PhoneZero is an example they may pick, not a default you apply without a reply. +- Always use that name on later calls? If yes, remember it and do not re-ask. If no, ask again before every call. - AI disclaimer ON or OFF — they may turn it OFF **Do not ask for destination countries.** Read them from Telnyx after the HTTP MCP is proven: the outbound voice profile **attached to the PhoneZero TeXML app** (any name) → `whitelisted_destinations`. `list_outbound_voice_profiles` with **no name filter**; pick the id on that TeXML app. Show the actual name + codes. That setting is Telnyx Mission Control → Voice → Outbound voice profiles. PATCH only if they ask to add or remove countries. Do not give legal advice. diff --git a/plugins/phonezero-grok/skills/phonezero-telnyx-canary/SKILL.md b/plugins/phonezero-grok/skills/phonezero-telnyx-canary/SKILL.md index 4823802..bf8b3e3 100644 --- a/plugins/phonezero-grok/skills/phonezero-telnyx-canary/SKILL.md +++ b/plugins/phonezero-grok/skills/phonezero-telnyx-canary/SKILL.md @@ -8,7 +8,7 @@ description: Grok Bot PhoneZero setup when pointed at https://github.com/functio Computer-use. Drive the UI. Do these steps **in order**. Same playbook: repo-root [README.md](../../../../README.md) and [AGENTS.md](../../../../AGENTS.md). After ids are in session: [plugins/phonezero/skills/phonezero-runtime/SKILL.md](../../../phonezero/skills/phonezero-runtime/SKILL.md) and the matching phone skill (or interview a custom `phonezero-task` — do not ask for a `SKILL.md` paste). 1. **Not** Cursor + Add. **Not** Authenticate. **Not** keys in chat. **Not** `source ~/.phonezero/env`. **Not** `scripts/provision.sh`. -2. Vendor gate, then **ask in chat and wait** — spoken name and AI disclaimer ON/OFF only. Do **not** ask for destination countries. +2. Vendor gate, then **ask in chat and wait** — Agent Name (required; do not silently use PhoneZero) and whether to always use that name, plus AI disclaimer ON/OFF. Do **not** ask for destination countries. Before every later call, ask the name again unless they said to always use one. 3. HTTP MCP: `https://api.telnyx.com/v2/mcp` + `Authorization: Bearer` in the form. Edit Values: keys + From only. Name / disclose stay in chat. 4. `list_api_endpoints` — real list or stop. “6 tools” proves nothing. There is **no** MCP tool named `whoami`. 5. If `put_task` / `put_booking` is missing: add stdio `xai` from [`plugins/phonezero/mcp.json`](../../../phonezero/mcp.json) with **real** env (not `${…}`). Then `get_call_config` + `ensure_collection`. If they said xAI is already set up, do not open the Builder. Ignore the wizard number. If they turned disclaimer OFF and Builder already exists, or the agent still searches `phonezero-booking.json`, re-paste `prompts/voice-agent.md` and `prompts/end_call.md` once. diff --git a/plugins/phonezero/.cursor-plugin/plugin.json b/plugins/phonezero/.cursor-plugin/plugin.json index 218e326..369501b 100644 --- a/plugins/phonezero/.cursor-plugin/plugin.json +++ b/plugins/phonezero/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "phonezero", "displayName": "PhoneZero", - "version": "0.4.2", + "version": "0.4.3", "description": "Phone skills for voice tasks (restaurant booking first). Need: Telnyx KYC + one US number, xAI team with ZDR off, API keys, Voice Agent Builder. Then /setup-phone-calling.", "author": { "name": "Function1st" diff --git a/plugins/phonezero/scripts/xai-mcp.mjs b/plugins/phonezero/scripts/xai-mcp.mjs index 05a0cfb..90c5161 100755 --- a/plugins/phonezero/scripts/xai-mcp.mjs +++ b/plugins/phonezero/scripts/xai-mcp.mjs @@ -808,7 +808,7 @@ async function handle(msg) { ok(id, { protocolVersion: params?.protocolVersion || "2024-11-05", capabilities: { tools: {} }, - serverInfo: { name: "phonezero-xai", version: "0.4.2" }, + serverInfo: { name: "phonezero-xai", version: "0.4.3" }, }); return; } diff --git a/plugins/phonezero/skills/book-restaurant/SKILL.md b/plugins/phonezero/skills/book-restaurant/SKILL.md index e571299..4a4b0aa 100644 --- a/plugins/phonezero/skills/book-restaurant/SKILL.md +++ b/plugins/phonezero/skills/book-restaurant/SKILL.md @@ -17,7 +17,7 @@ Read `phonezero-runtime` for Setup, preconditions, plan-first, hours hard cap, d | Restaurant-local hours when hours unknown | 10:30–20:30 restaurant-local (user TZ if unknown) | user-stated hours | | Window if they said “around 7” | propose preferred ± 30–60 min + ranked in-window slots | user-supplied window | | Calendar offer after `succeeded` | offer ~90 minutes | skip | -| Spoken name | PhoneZero | per-call (`spoken_name` in the brief) | +| Spoken name | Cursor: PhoneZero. **Grok: ask every call** unless they said always use one. | per-call (`spoken_name` in the brief) | ## Collect diff --git a/plugins/phonezero/skills/confirm-business-hours/SKILL.md b/plugins/phonezero/skills/confirm-business-hours/SKILL.md index 60d546e..674dd9f 100644 --- a/plugins/phonezero/skills/confirm-business-hours/SKILL.md +++ b/plugins/phonezero/skills/confirm-business-hours/SKILL.md @@ -16,7 +16,7 @@ Collect who to call and what we need confirmed. No OpenTable step. Hand off to [ | Callback | E.164. Default to the user's phone; confirm it. | | Expected hours (optional) | What we think the hours are, or a specific question (“open Saturday?”, “today’s holiday hours?”). | -Spoken name defaults to PhoneZero; override per call. Fail closed if there is no business or no number after one clarifying turn. +Spoken name: Cursor defaults PhoneZero; **Grok always asks** unless they said to always use one. Fail closed if there is no business or no number after one clarifying turn. ## Call plan diff --git a/plugins/phonezero/skills/phonezero-runtime/SKILL.md b/plugins/phonezero/skills/phonezero-runtime/SKILL.md index 28c46e3..5df0618 100644 --- a/plugins/phonezero/skills/phonezero-runtime/SKILL.md +++ b/plugins/phonezero/skills/phonezero-runtime/SKILL.md @@ -9,7 +9,7 @@ Shared outbound loop for every phone skill. First-party skills (`book-restaurant Destinations must be in the Telnyx outbound voice profile **attached to the PhoneZero TeXML app** (`whitelisted_destinations`, ISO 3166-1 alpha-2). Read that list via Telnyx MCP — it is **not** a PhoneZero plugin variable. The profile may have **any name** and any country list the user set. Never filter by a hardcoded name such as `PhoneZero US-only`. Never place a call to a country not on that list. Never place bulk or multi-destination calls. Never auto-dial. -**Defaults (not compliance advice).** Destinations default `US` on a new Telnyx profile. Disclose defaults on (per-task `disclose_ai`, and the one-time Builder `{disclosure_clause}`). Every call is recorded (dual-channel); the opener says so. Spoken name defaults to PhoneZero per task. Task JSON is English; after pickup the voice agent speaks the answerer’s language. The person using this sample is solely responsible for complying with all applicable laws and vendor terms — see repo [DISCLAIMER.md](../../../../DISCLAIMER.md). Do not give legal guidance in chat. +**Defaults (not compliance advice).** Destinations default `US` on a new Telnyx profile. Disclose defaults on (per-task `disclose_ai`, and the one-time Builder `{disclosure_clause}`). Every call is recorded (dual-channel); the opener says so. Spoken name: **Grok always asks** unless they said to always use one; Cursor defaults PhoneZero. Task JSON is English; after pickup the voice agent speaks the answerer’s language. The person using this sample is solely responsible for complying with all applicable laws and vendor terms — see repo [DISCLAIMER.md](../../../../DISCLAIMER.md). Do not give legal guidance in chat. **Bootstrap from repo.** `AGENTS.md` at the repo root is the hook. **Grok Bot** (pointed at `https://github.com/function1st/PhoneZero` or “set this up”): execute **Grok Bot — set this up** in `AGENTS.md` first — do not + Add the Cursor plugin. **Cursor IDE:** this file’s Setup, after the Cursor package is installed. After install or update, start a **new** conversation. @@ -27,9 +27,9 @@ Before collecting a task or touching Telnyx, verify these variables are present. | `TELNYX_ACCOUNT_SID` | **Not on the Configure card.** Telnyx MCP has **no** `whoami` tool. `invoke_api_endpoint` `list_billing_groups` → first `data[].organization_id`. Developer curl `GET /v2/whoami` is the same value. TeXML paths: `/v2/texml/Accounts/{TELNYX_ACCOUNT_SID}/…`. | | `PHONEZERO_TEXML_APP_ID` | **Not on the Configure card.** Resolve with Telnyx MCP: list TeXML apps, use the one named `PhoneZero`. | | `PHONEZERO_XAI_COLLECTION_ID` | **Not on the Configure card.** Find-or-create collection name `PhoneZero bookings`. Attach it to the Builder agent (knowledge / file search). | -| Spoken name / disclose | **Not on the Configure card.** Per-task: `spoken_name` and `disclose_ai` in `phonezero-task.json`. Default PhoneZero / true if they do not say otherwise. `{disclosure_clause}` is substituted once when pasting the Builder prompt. | +| Spoken name / disclose | **Not on the Configure card.** Per-task: `spoken_name` and `disclose_ai` in `phonezero-task.json`. **Grok:** always ask the spoken name unless they said to always use one (see §2). Cursor: default PhoneZero / true if they do not say otherwise. `{disclosure_clause}` is substituted once when pasting the Builder prompt. | -Call-time required: working Telnyx MCP, working PhoneZero xAI MCP, a From number from `get_call_config` or Telnyx list. Resolve `TELNYX_ACCOUNT_SID` and `PHONEZERO_TEXML_APP_ID` **before** the call plan — not after `put_task`. SID: `invoke_api_endpoint` `list_billing_groups` `{ "jq_filter": "[.data[].organization_id] | unique" }`. TeXML id: `invoke_api_endpoint` `list_texml_applications` `{ "filter": { "friendly_name": "PhoneZero" }, "jq_filter": ".data[] | {id, friendly_name, outbound}" }`. Destinations: that app’s `outbound.outbound_voice_profile_id`, then `invoke_api_endpoint` `list_outbound_voice_profiles` `{ "jq_filter": ".data[] | {id, name, whitelisted_destinations}" }` and pick the matching `id`. **No name filter.** Spoken name / disclose come from this call’s collect (defaults PhoneZero / true). Collection via xAI MCP `ensure_collection`. +Call-time required: working Telnyx MCP, working PhoneZero xAI MCP, a From number from `get_call_config` or Telnyx list. Resolve `TELNYX_ACCOUNT_SID` and `PHONEZERO_TEXML_APP_ID` **before** the call plan — not after `put_task`. SID: `invoke_api_endpoint` `list_billing_groups` `{ "jq_filter": "[.data[].organization_id] | unique" }`. TeXML id: `invoke_api_endpoint` `list_texml_applications` `{ "filter": { "friendly_name": "PhoneZero" }, "jq_filter": ".data[] | {id, friendly_name, outbound}" }`. Destinations: that app’s `outbound.outbound_voice_profile_id`, then `invoke_api_endpoint` `list_outbound_voice_profiles` `{ "jq_filter": ".data[] | {id, name, whitelisted_destinations}" }` and pick the matching `id`. **No name filter.** Spoken name / disclose: Grok asks the name unless they said always use one; Cursor defaults PhoneZero / true. Collection via xAI MCP `ensure_collection`. If Telnyx MCP or xAI MCP is missing / 401s, or From cannot be resolved: **stop. Do not dial.** Tell the user to re-save Plugins → Configure and start a **new** conversation, then `/setup-phone-calling`. Never paste keys in chat. Never `source ~/.phonezero/env`. An old chat not seeing new MCP tools is not a failure. @@ -37,7 +37,7 @@ Do not invent `{TELNYX_ACCOUNT_SID}`. ## Setup (when the user says *Set up phone calling* or runs `/setup-phone-calling`) -Human/developer mirrors: `docs/SETUP.md`, and `scripts/provision.sh` — developer-only, run on a personal machine that may hold keys, never on this computer. Never `source ~/.phonezero/env`. Telnyx account + KYC + buying the DID stay manual. Telnyx API steps go through the Telnyx MCP. xAI Files / collections / STT / phone-numbers go through the PhoneZero xAI MCP on **both** hosts. **Grok Bot:** add that stdio `xai` server if `put_task` / `put_booking` is missing (`AGENTS.md` / README). REST on `api.x.ai` is fallback only. Do not take the key from chat. **Grok must ask** spoken name and AI disclaimer ON/OFF — do not silently keep PhoneZero / true. Destination countries are the Telnyx profile whitelist; read and show them, do not ask as a PhoneZero field. +Human/developer mirrors: `docs/SETUP.md`, and `scripts/provision.sh` — developer-only, run on a personal machine that may hold keys, never on this computer. Never `source ~/.phonezero/env`. Telnyx account + KYC + buying the DID stay manual. Telnyx API steps go through the Telnyx MCP. xAI Files / collections / STT / phone-numbers go through the PhoneZero xAI MCP on **both** hosts. **Grok Bot:** add that stdio `xai` server if `put_task` / `put_booking` is missing (`AGENTS.md` / README). REST on `api.x.ai` is fallback only. Do not take the key from chat. **Grok must ask** the Agent Name (spoken name) and wait — do not silently keep PhoneZero. Skip that question only if they already said to always use a specific name. Also ask AI disclaimer ON/OFF. Destination countries are the Telnyx profile whitelist; read and show them, do not ask as a PhoneZero field. **First message, before any API call:** @@ -63,7 +63,7 @@ If any of those are missing, **stop**. - Fallback (no plugin, Cursor IDE): `"telnyx": {"command":"npx","args":["-y","@telnyx/mcp"],"env":{"TELNYX_API_KEY":"${env:TELNYX_API_KEY}"}}`. Never the literal key in the file or chat. - **Verify with a `tools/call`, never the tool count.** Call `list_api_endpoints`. If `get_call_config.from_wired` is false, take From from Telnyx `list_phone_numbers` (PhoneZero TeXML DID). -**Keys first.** Required on the Configure card: `TELNYX_API_KEY`, `PHONEZERO_FROM_NUMBER`, `XAI_API_KEY`. Spoken name and disclose are **not** on the card — ask in chat (Grok: the `AGENTS.md` call-settings card; Cursor: per task, default PhoneZero / true) and write them into `phonezero-task.json`. Destinations are **not** on the card. Read destinations from Telnyx (the profile attached to the PhoneZero TeXML app → `whitelisted_destinations`) and show the **actual profile name** plus the codes. PATCH that profile only if they ask to add/remove countries (Mission Control → Voice → Outbound voice profiles is the same setting). Account SID, TeXML app id, and collection id are **not** on the card. If Telnyx MCP or the PhoneZero xAI MCP is unwired, send the user to Plugins → Configure and a **new** conversation. Then, field-for-field: +**Keys first.** Required on the Configure card: `TELNYX_API_KEY`, `PHONEZERO_FROM_NUMBER`, `XAI_API_KEY`. Spoken name and disclose are **not** on the card — ask in chat (Grok: always ask the Agent Name unless they said to always use one; Cursor: per task, default PhoneZero / true) and write them into `phonezero-task.json`. Destinations are **not** on the card. Read destinations from Telnyx (the profile attached to the PhoneZero TeXML app → `whitelisted_destinations`) and show the **actual profile name** plus the codes. PATCH that profile only if they ask to add/remove countries (Mission Control → Voice → Outbound voice profiles is the same setting). Account SID, TeXML app id, and collection id are **not** on the card. If Telnyx MCP or the PhoneZero xAI MCP is unwired, send the user to Plugins → Configure and a **new** conversation. Then, field-for-field: 1. `TELNYX_ACCOUNT_SID` via Telnyx MCP `invoke_api_endpoint` `list_billing_groups` (`data[].organization_id`). Do not search the catalog for `whoami`. 2. Outbound voice profile — **do not require a specific name.** Resolve in this order: (a) the profile already attached to the PhoneZero TeXML app (`outbound.outbound_voice_profile_id`); (b) if they have exactly one outbound voice profile, use it; (c) if they have several, list `{id, name, whitelisted_destinations}` and ask which to attach; (d) if they have none, create one. Create defaults: name `PhoneZero` unless they pick another, `traffic_type=conversational`, `service_plan=global`, `usage_payment_method=rate-deck`, `whitelisted_destinations` default `["US"]` **on create only**, `daily_spend_limit="5.00"`, `daily_spend_limit_enabled=true` (`POST /v2/outbound_voice_profiles`; any other combo → Telnyx error 10015). **This Telnyx profile is the destination enforcement** — Telnyx rejects calls outside `whitelisted_destinations`. Keep an existing whitelist and name. `PATCH` only when the user asks to add or remove countries. They may name the profile anything and set any region list in Telnyx Mission Control → Voice → Outbound voice profiles. @@ -96,6 +96,8 @@ Match the user ask: Do not dial until the bound skill (or ad-hoc interview) has every required field. Fail closed after one clarifying turn if the task stays vague. +**Grok Bot — spoken name.** Always ask what Agent Name the callee should hear (`spoken_name`). Wait for a reply. Do **not** silently use PhoneZero or any leftover default. PhoneZero is an example they may choose, not a name you apply without asking. **Exception:** if they have already instructed you to **always use the same name** (this chat, or Grok memory), reuse it, show it as Spoken as on the plan, and do not re-ask unless they change it. A one-call name does not stick — ask again next call. If they say “always use {name},” keep it in session and write it to Grok memory when the host has it. Not a Configure / Edit Values field. Cursor IDE may still default to PhoneZero. + ## 3. Plan-first confirmation Present the plan in chat. Do not dial in the same turn as the plan. Use the skill’s plan template if it has one; otherwise: @@ -165,7 +167,7 @@ Envelope (no extra top-level keys except `kind`): } ``` -`disclose_ai` defaults true unless they turned it off for this call (or at setup, for the Builder paste). `{agent_name}` is this call's spoken name (default PhoneZero). Keep `playbook` short — collection search truncates. +`disclose_ai` defaults true unless they turned it off for this call (or at setup, for the Builder paste). `{agent_name}` is this call's spoken name (Grok: they answered, or the always-use name; Cursor: default PhoneZero). Keep `playbook` short — collection search truncates. **Both hosts:** PhoneZero xAI MCP `put_task` (or `put_booking` alias). **Grok Bot:** if those tools are missing, add stdio `xai` from `plugins/phonezero/mcp.json` (secure-field env, not `${…}`) — do not say upload is impossible. Fallback: `https://api.x.ai/v1` Bearer; sequence is `putTask` / `putBooking` in `scripts/xai-mcp.mjs`. Never echo the key. If the user said xAI is already set up, do not open the Builder. @@ -316,7 +318,7 @@ Do **not** ask them to paste a `SKILL.md`, clone a gist, or write a skill folder | What must a **live person** say before we call this a win? | `success` | | What to leave on voicemail | `voicemail` | | Any extra facts | `facts` | -| Spoken name override | `spoken_name` | +| Spoken name (Grok: always ask unless they said always use one) | `spoken_name` | 4. Same safety as shipped skills. Show the JSON in the call plan. Dial only on yes. Classify with §8 + this brief’s `success` / `constraints`. 5. Do not open the Builder. The JSON is the shape of the call. @@ -337,6 +339,7 @@ Cursor may save a template as a local skill folder when they ask. That is not th ## Hard rules - No call without §1 call-time variables, a complete collect (skill or ad-hoc), an hours check, and an explicit yes to the current plan. +- Grok Bot: no call plan until they have answered the Agent Name, unless they already said to always use a specific name. - No `succeeded` / `booked` unless all five gates in §8 hold. - No secrets, no keys in chat, no non-fixture numbers written into skills or examples. - One callee, one task, max two attempts, 20 minutes apart.