{
  "schemaVersion": "1.0",
  "item": {
    "slug": "clawdtalk-client",
    "name": "ClawdTalk",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/dcasem/clawdtalk-client",
    "canonicalUrl": "https://clawhub.ai/dcasem/clawdtalk-client",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/clawdtalk-client",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=clawdtalk-client",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "setup.sh",
      "CHANGELOG.md",
      "uninstall.sh",
      "SETUP.md",
      "skill-config-sample.md",
      "status.sh"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/clawdtalk-client"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/clawdtalk-client",
    "agentPageUrl": "https://openagent3.xyz/skills/clawdtalk-client/agent",
    "manifestUrl": "https://openagent3.xyz/skills/clawdtalk-client/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/clawdtalk-client/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "ClawdTalk",
        "body": "⚠️ First time setup? Read SETUP.md in this directory before anything else. It walks you through the complete configuration flow step by step.\n\nVoice calling, SMS messaging, and AI Missions for Clawdbot. Call your bot by phone, send texts, or run autonomous multi-step outreach campaigns — powered by ClawdTalk.\n\nTrust: By using this skill, voice transcripts, SMS messages, and mission data are sent to clawdtalk.com (operated by Telnyx). Only install if you trust this service with your conversation data."
      },
      {
        "title": "External Endpoints",
        "body": "EndpointUsed byData senthttps://clawdtalk.com (WebSocket)ws-client.jsVoice transcripts, tool results, conversation statehttps://clawdtalk.com/v1/*telnyx_api.pyMission state, events, scheduled calls/SMS, assistant configshttp://127.0.0.1:<port>ws-client.jsTranscribed speech (local gateway only)https://raw.githubusercontent.com/team-telnyx/clawdtalk-client/...update.shNone (download only)"
      },
      {
        "title": "Security & Privacy",
        "body": "Voice transcripts and SMS content are transmitted to clawdtalk.com.\nMission state and events are stored server-side for tracking and insights.\nsetup.sh reads gateway config to extract connection details; with confirmation it adds sessions_send to gateway.tools.allow.\nAPI key is stored in skill-config.json — use env var CLAWDTALK_API_KEY or a ${CLAWDTALK_API_KEY} reference to avoid plaintext storage."
      },
      {
        "title": "⚠️ CRITICAL: SLUG CONSISTENCY",
        "body": "init auto-generates a slug from the mission name (lowercased, spaces → hyphens).\nEvery command that takes a slug (setup-agent, save-memory, complete) MUST use the EXACT same slug.\n\nMismatched slugs = agent not linked = scheduled events invisible on the frontend.\n\n# After init, ALWAYS confirm the slug:\npython scripts/telnyx_api.py list-state\n# Output: find-window-washing-contractors: Find window washing contractors [running]\n#         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ COPY-PASTE THIS. NEVER ABBREVIATE."
      },
      {
        "title": "⚠️ CRITICAL: YOU OWN THE MISSION LIFECYCLE",
        "body": "The server does NOT automatically update plan steps or mission status. That is YOUR job as the bot. If you don't update steps and complete the mission, the UI will show \"Running\" forever with all steps \"Pending\"."
      },
      {
        "title": "Your Responsibilities",
        "body": "For every mission, YOU must:\n\nUpdate plan steps — mark each step in_progress → completed (or failed)\nLog events — after every significant action\nPoll for completion — check if scheduled calls/SMS finished\nComplete the mission — mark the run as succeeded or failed\nClean up — remove any polling cron jobs when the mission ends\n\nThe UI reflects exactly what you tell it. No updates from you = no updates on screen."
      },
      {
        "title": "🚨 MANDATORY: SAVE TO MEMORY AFTER EVERY ACTION",
        "body": "Every significant action MUST be persisted using save-memory or append-memory IMMEDIATELY after the action succeeds. The frontend reads from server memory. If you don't save it, it doesn't show up. log-event alone is NOT enough.\n\nRule: If you did something, save it to memory. No exceptions. No \"I'll do it later.\" Do it NOW.\n\nExample (scheduling an SMS):\n\n# 1. Schedule it\npython scripts/telnyx_api.py schedule-sms $AID \"$TO\" \"$FROM\" \"$DATETIME\" \"$MESSAGE\" $MID $RID $STEP_ID\n\n# 2. IMMEDIATELY save to memory\npython scripts/telnyx_api.py append-memory \"$SLUG\" \"scheduled_events\" \\\n  '{\"event_id\": \"<id>\", \"type\": \"sms\", \"to\": \"<to>\", \"message\": \"<msg>\", \"scheduled_at\": \"<dt>\", \"step_id\": \"<step>\"}'\n\n# 3. Then log the event\npython scripts/telnyx_api.py log-event $MID $RID custom \"Scheduled SMS event_id=<id>\" $STEP_ID\n\nSkipping step 2 is the #1 cause of \"nothing shows on the frontend\" bugs."
      },
      {
        "title": "🚨 MANDATORY: CHECK MISSION STATUS AFTER EVERY STEP",
        "body": "After completing or failing ANY step, you MUST check whether the mission should be completed or failed. Never leave a mission in \"running\" state when it's actually done or dead.\n\nRule: After every step change, ask yourself: is this mission finished?"
      },
      {
        "title": "Decision tree (run after EVERY step):",
        "body": "Step finished →\n  ├── Succeeded?\n  │     ├── All steps done? → COMPLETE MISSION (update-run succeeded)\n  │     ├── More steps remain? → Continue to next step\n  │     └── Only verify left? → Set up polling cron\n  └── Failed?\n        ├── Recoverable (retry/reschedule)? → Retry\n        └── Unrecoverable? → FAIL MISSION NOW:\n              1. update-step <step_id> failed\n              2. log-event error \"Failed: <reason>\" <step_id>\n              3. save-memory \"$SLUG\" \"error_<step_id>\" '{\"error\": \"...\", \"recoverable\": false}'\n              4. update-run $MID $RID failed\n              5. save-memory \"$SLUG\" \"result\" '{\"status\": \"failed\", \"reason\": \"...\", \"failed_step\": \"...\"}'\n              6. Clean up any polling cron jobs\n\nA mission stuck in \"running\" when it's actually done or dead is a bug. The user sees it and thinks work is still happening."
      },
      {
        "title": "How It Fits Together",
        "body": "┌──────────────┐     ┌──────────────────┐     ┌──────────────┐\n│  You (Bot)   │────▶│  ClawdTalk Server │────▶│  Telnyx API  │\n│              │     │  (dev/prod)       │     │  (cloud)     │\n│ telnyx_api.py│     │  Local DB + proxy │     │  Executes    │\n│              │     │  to Telnyx        │     │  calls/SMS   │\n└──────────────┘     └──────────────────┘     └──────────────┘\n\ntelnyx_api.py — Python CLI script. Every command you run goes through this. It talks to the ClawdTalk server, never directly to Telnyx.\nClawdTalk Server — Node.js backend. Stores missions, assistants, and events in a local Postgres DB. Proxies requests to the Telnyx API.\nTelnyx API — Cloud service. Actually makes the calls and sends the SMS at the scheduled time."
      },
      {
        "title": "Key Files",
        "body": "FilePurposescripts/telnyx_api.pyCLI tool for all mission/assistant/event operationsscripts/connect.shWebSocket client for inbound voice call routingskill-config.jsonAPI key and server URL.missions_state.jsonLocal state tracking for active missions.connect.logWebSocket connection logs"
      },
      {
        "title": "Two Sets of IDs",
        "body": "Every entity exists in two places with different IDs:\n\nLocal DB ID — what the ClawdTalk server returns (e.g. 3df24dde-...)\nTelnyx ID — what the Telnyx API uses internally\n\nThe script always works with local IDs. You don't need to worry about Telnyx IDs."
      },
      {
        "title": "Quick Start",
        "body": "Sign up at clawdtalk.com\nAdd your phone in Settings\nGet API key from Dashboard\nRun setup: ./setup.sh\n\nsetup.sh reads your gateway config to extract connection details and (with confirmation) adds sessions_send to gateway.tools.allow. Gateway config is at ~/.openclaw/openclaw.json or ~/.clawdbot/clawdbot.json.\n\n\nStart connection: ./scripts/connect.sh start"
      },
      {
        "title": "Voice Calls",
        "body": "The WebSocket client routes calls to your gateway's main agent session, giving full access to memory, tools, and context.\n\n./scripts/connect.sh start     # Start connection\n./scripts/connect.sh stop      # Stop\n./scripts/connect.sh status    # Check status"
      },
      {
        "title": "Outbound Calls",
        "body": "Have the bot call you or others:\n\n./scripts/call.sh                              # Call your phone\n./scripts/call.sh \"Hey, what's up?\"            # Call with greeting\n./scripts/call.sh --to +15551234567            # Call external number*\n./scripts/call.sh --to +15551234567 \"Hello!\"   # External with greeting\n./scripts/call.sh status <call_id>             # Check call status\n./scripts/call.sh end <call_id>                # End call\n\n*External calls require a paid account with a dedicated number. The AI will operate in privacy mode when calling external numbers (won't reveal your private info)."
      },
      {
        "title": "SMS",
        "body": "Send and receive text messages:\n\n./scripts/sms.sh send +15551234567 \"Hello!\"\n./scripts/sms.sh list\n./scripts/sms.sh conversations"
      },
      {
        "title": "AI Missions (Full Tracking via Python)",
        "body": "For complex, multi-step missions with full tracking, state persistence, retries, and conversation insights, use the Python-based missions API.\n\nRequired: Python 3.7+, CLAWDTALK_API_KEY environment variable. Optionally set CLAWDTALK_API_URL to override the default endpoint (defaults to https://clawdtalk.com/v1).\n\npython scripts/telnyx_api.py check-key    # Verify setup"
      },
      {
        "title": "CRITICAL: SAVE STATE FREQUENTLY",
        "body": "You MUST save your progress after EVERY significant action. If the session crashes or restarts, unsaved work is LOST."
      },
      {
        "title": "Two-Layer Persistence: Memory + Events",
        "body": "Always save to BOTH:\n\nLocal Memory (.missions_state.json) - Fast, survives restarts\nEvents API (cloud) - Permanent audit trail, survives local file loss"
      },
      {
        "title": "When to Save (After EVERY action!)",
        "body": "ActionSave MemoryLog EventWeb search returns resultsappend-memorylog-event (tool_call)Found a contractor/leadappend-memorylog-event (custom)Created assistantsave-memorylog-event (custom)Assigned phone numbersave-memorylog-event (custom)Scheduled a call/SMSappend-memorylog-event (custom)Call completedsave-memorylog-event (custom)Got quote/insightsave-memorylog-event (custom)Made a decisionsave-memorylog-event (message)Step startedsave-memoryupdate-step (in_progress) + log-event (step_started)Step completedsave-memoryupdate-step (completed) + log-event (step_completed)Step failedsave-memoryupdate-step (failed) + log-event (error)Error occurredsave-memorylog-event (error)"
      },
      {
        "title": "Memory Commands (Local Backup)",
        "body": "# Save a single value\npython scripts/telnyx_api.py save-memory \"<slug>\" \"key\" '{\"data\": \"value\"}'\n\n# Append to a list (great for collecting multiple items)\npython scripts/telnyx_api.py append-memory \"<slug>\" \"contractors\" '{\"name\": \"ABC Co\", \"phone\": \"+1234567890\"}'\n\n# Retrieve memory\npython scripts/telnyx_api.py get-memory \"<slug>\"           # Get all memory\npython scripts/telnyx_api.py get-memory \"<slug>\" \"key\"     # Get specific key"
      },
      {
        "title": "Event Commands (Cloud Backup)",
        "body": "# Log an event (step_id is REQUIRED - links event to a plan step)\npython scripts/telnyx_api.py log-event <mission_id> <run_id> <type> \"<summary>\" <step_id> '[payload_json]'\n\n# Event types: tool_call, custom, message, error, step_started, step_completed\n# step_id: Use the step_id from your plan (e.g., \"research\", \"setup\", \"calls\")\n#          Use \"-\" if event doesn't belong to a specific step"
      },
      {
        "title": "When to Use Missions",
        "body": "This skill has two modes: full missions (tracked, multi-step) and simple calls (one-off, no mission overhead). Pick the right one."
      },
      {
        "title": "Use a Full Mission When:",
        "body": "The task involves multiple calls or SMS (batch outreach, surveys, sweeps)\nYou need a complete audit trail with events, plans, and state tracking\nThe task is multi-step and takes significant effort across phases\nRetries and failure tracking matter\nYou need to compare results across multiple calls\n\nExamples:\n\n\"Find me window washing contractors in Chicago, call them and negotiate rates\"\n\"Contact all leads in this list and schedule demos\"\n\"Call 10 weather stations and find the hottest one\""
      },
      {
        "title": "Do NOT Use a Mission When:",
        "body": "The task is a single outbound call — just create an assistant (or reuse one) and schedule the call directly\nIt's a one-off SMS — schedule it and done\nThe task doesn't need tracking, plans, or state recovery\nYou'd be creating a mission with one step and one call — that's overengineering\n\nFor simple calls, just:\n\n# Reuse or create an assistant\npython scripts/telnyx_api.py list-assistants --name=<relevant>\n# Schedule the call\npython scripts/telnyx_api.py schedule-call <assistant_id> <to> <from> <datetime> <mission_id> <run_id>\n# Poll for completion\npython scripts/telnyx_api.py get-event <assistant_id> <event_id>\n# Get insights\npython scripts/telnyx_api.py get-insights <conversation_id>\n\nNo mission, no run, no plan. Keep it simple."
      },
      {
        "title": "State Persistence",
        "body": "The script automatically manages state in .missions_state.json. This survives restarts and supports multiple concurrent missions.\n\npython scripts/telnyx_api.py list-state                              # List all active missions\npython scripts/telnyx_api.py get-state \"find-window-washing-contractors\"  # Get state for specific mission\npython scripts/telnyx_api.py remove-state \"find-window-washing-contractors\" # Remove mission from state"
      },
      {
        "title": "Step 1.1: Create a Mission",
        "body": "python scripts/telnyx_api.py create-mission \"Brief descriptive name\" \"Full description of the task\"\n\nSave the returned mission_id - you'll need it for all subsequent calls."
      },
      {
        "title": "Step 1.2: Start a Run",
        "body": "python scripts/telnyx_api.py create-run <mission_id> '{\"original_request\": \"The exact user request\", \"context\": \"Any relevant context\"}'\n\nSave the returned run_id."
      },
      {
        "title": "Step 1.3: Create a Plan",
        "body": "Before executing, outline your plan:\n\npython scripts/telnyx_api.py create-plan <mission_id> <run_id> '[\n  {\"step_id\": \"step_1\", \"description\": \"Research contractors online\", \"sequence\": 1},\n  {\"step_id\": \"step_2\", \"description\": \"Create voice agent for calls\", \"sequence\": 2},\n  {\"step_id\": \"step_3\", \"description\": \"Schedule calls to each contractor\", \"sequence\": 3},\n  {\"step_id\": \"step_4\", \"description\": \"Monitor call completions\", \"sequence\": 4},\n  {\"step_id\": \"step_5\", \"description\": \"Analyze results and select best options\", \"sequence\": 5}\n]'"
      },
      {
        "title": "Step 1.4: Set Run to Running",
        "body": "python scripts/telnyx_api.py update-run <mission_id> <run_id> running"
      },
      {
        "title": "High-Level Alternative: Initialize Everything at Once",
        "body": "Use the init command to create mission, run, plan, and set status in one step:\n\npython scripts/telnyx_api.py init \"Find window washing contractors\" \"Find contractors in Chicago, call them, negotiate rates\" \"User wants window washing quotes\" '[\n  {\"step_id\": \"research\", \"description\": \"Find contractors online\", \"sequence\": 1},\n  {\"step_id\": \"setup\", \"description\": \"Create voice agent\", \"sequence\": 2},\n  {\"step_id\": \"calls\", \"description\": \"Schedule and make calls\", \"sequence\": 3},\n  {\"step_id\": \"analyze\", \"description\": \"Analyze results\", \"sequence\": 4}\n]'\n\nThis also automatically resumes if a mission with the same name already exists.\n\n⚠️ Immediately after init, run list-state and copy the exact slug. Use it for ALL subsequent commands."
      },
      {
        "title": "Phase 2: Voice/SMS Agent Setup",
        "body": "When your task requires making calls or sending SMS, create an AI assistant first."
      },
      {
        "title": "Step 2.1: Create a Voice/SMS Assistant",
        "body": "For phone calls:\n\npython scripts/telnyx_api.py create-assistant \"Contractor Outreach Agent\" \"You are calling on behalf of [COMPANY]. Your goal is to [SPECIFIC GOAL]. Be professional and concise. Collect: [WHAT TO COLLECT]. If they cannot talk now, ask for a good callback time.\" \"Hi, this is an AI assistant calling on behalf of [COMPANY]. Is this [BUSINESS NAME]? I am calling to inquire about your services. Do you have a moment?\" '[\"telephony\", \"messaging\"]'\n\nFor SMS:\n\npython scripts/telnyx_api.py create-assistant \"SMS Outreach Agent\" \"You send SMS messages to collect information. Keep messages brief and professional.\" \"Hi! I am reaching out on behalf of [COMPANY] regarding [PURPOSE]. Could you please reply with [REQUESTED INFO]?\" '[\"telephony\", \"messaging\"]'\n\nSave the returned assistant_id."
      },
      {
        "title": "Step 2.2: Find and Assign a Phone Number",
        "body": "python scripts/telnyx_api.py get-available-phone                          # Get first available\npython scripts/telnyx_api.py get-connection-id <assistant_id> telephony   # Get connection ID\npython scripts/telnyx_api.py assign-phone <phone_number_id> <connection_id> voice  # Assign"
      },
      {
        "title": "High-Level Alternative: Setup Agent in One Step",
        "body": "python scripts/telnyx_api.py setup-agent \"find-window-washing-contractors\" \"Contractor Caller\" \"You are calling to get quotes for commercial window washing. Ask about: rates per floor, availability, insurance. Be professional.\" \"Hi, I am calling to inquire about your commercial window washing services. Do you have a moment to discuss rates?\"\n\nThis automatically creates the assistant, links it to the mission run, finds an available phone number, assigns it, and saves all IDs to the state file.\n\n⚠️ The slug MUST match what init created. If it doesn't, the agent won't be linked and scheduled events won't appear on the frontend.\n\nVerify linking worked immediately after:\n\npython scripts/telnyx_api.py list-linked-agents <mission_id> <run_id>\n# Must show your assistant_id. If empty → slug was wrong. Fix with:\npython scripts/telnyx_api.py link-agent <mission_id> <run_id> <assistant_id>"
      },
      {
        "title": "Step 2.3: Link Agent to Mission Run",
        "body": "If using setup-agent: Linking is done automatically (only if slug matches init).\n\nIf setting up manually:\n\npython scripts/telnyx_api.py link-agent <mission_id> <run_id> <assistant_id>\npython scripts/telnyx_api.py list-linked-agents <mission_id> <run_id>\npython scripts/telnyx_api.py unlink-agent <mission_id> <run_id> <assistant_id>"
      },
      {
        "title": "Business Hours Consideration",
        "body": "CRITICAL: Before scheduling calls, consider business hours (9 AM - 5 PM local time). scheduled_at must be in the future (at least 1 minute from now).\n\npython scripts/telnyx_api.py schedule-call <assistant_id> \"+15551234567\" \"+15559876543\" \"2024-12-01T14:30:00Z\" <mission_id> <run_id>\npython scripts/telnyx_api.py schedule-sms <assistant_id> \"+15551234567\" \"+15559876543\" \"2024-12-01T14:30:00Z\" \"Your message here\"\n\nSave the returned event id."
      },
      {
        "title": "⚠️ THIS IS THE MOST IMPORTANT PART",
        "body": "After scheduling a call or SMS, Telnyx executes it autonomously at the scheduled time. You need to poll to find out when it's done, then update the mission accordingly."
      },
      {
        "title": "Check Scheduled Event Status",
        "body": "python scripts/telnyx_api.py get-event <assistant_id> <event_id>"
      },
      {
        "title": "Use Cron Jobs to Poll",
        "body": "Use your bot's cron system to schedule polling. Do NOT block the main session waiting. Match the poll interval to the expected wait time:\n\nExpected completionPoll intervalExample< 5 minutesEvery 30 secondsSMS sent 1 min from now5–30 minutesEvery 2–5 minutesCall scheduled in 15 min1–24 hoursEvery 15–30 minutesCall scheduled for tonightDays/weeksEvery 4–8 hoursCall scheduled for next week\n\nIf you know the exact scheduled time, don't start polling until after that time. Schedule your first poll for scheduled_time + 2 minutes."
      },
      {
        "title": "Cron Job Pattern",
        "body": "When you schedule a call/SMS, create a cron job to poll for it:\n\nCreate cron: poll at appropriate interval\n  → Run get-event <assistant_id> <event_id>\n  → If completed: update step, log event, complete mission if last step, DELETE THIS CRON\n  → If failed: update step as failed, log error, DELETE THIS CRON\n  → If pending/in_progress: do nothing, cron runs again at next interval\n\n⚠️ ALWAYS clean up cron jobs when a mission reaches a terminal state (completed, failed, cancelled). Never leave polling crons running after a mission ends."
      },
      {
        "title": "Adjusting Poll Frequency",
        "body": "You can update the cron interval as circumstances change:\n\nScheduled for 2 weeks from now? Start with 8-hour polling.\nAs the scheduled time approaches (within 1 hour), tighten to 5-minute intervals.\nAfter the scheduled time passes, tighten to 30-second intervals."
      },
      {
        "title": "Event Status Values",
        "body": "StatusMeaningActionpendingWaiting for scheduled timeKeep pollingin_progressCall/SMS in progressKeep pollingcompletedFinished successfullyUpdate step, get insights if callfailedFailed after retriesUpdate step as failed, consider retry"
      },
      {
        "title": "Call Status Values (Phone Calls Only)",
        "body": "call_statusMeaningActionringingPhone is ringingPoll again in 1-2 minutesin-progressCall is activePoll again in 2-3 minutescompletedCall finished normallyGet insightsno-answerNobody picked upRetryable — reschedulebusyLine is busyRetryable — retry in 10-15 mincanceledCall was canceledCheck if intentionalfailedNetwork/system errorRetryable — retry in 5-10 min"
      },
      {
        "title": "Phase 5: Getting Conversation Insights",
        "body": "Once a call completes with a conversation_id, retrieve insights. Poll until status is \"completed\" (wait 10 seconds between retries).\n\npython scripts/telnyx_api.py get-insights <conversation_id>\n\nTelnyx automatically creates default insight templates when an assistant is created. You don't need to manage these — just read the results."
      },
      {
        "title": "Phase 6: Complete the Mission",
        "body": "python scripts/telnyx_api.py update-run <mission_id> <run_id> succeeded\n\n# Or with full results:\npython scripts/telnyx_api.py complete \"find-window-washing-contractors\" <mission_id> <run_id> \"Summary of results\" '{\"key\": \"payload\"}'"
      },
      {
        "title": "Event Logging Reference",
        "body": "Log EVERY action as an event. Always update step status via update-step AND log corresponding events.\n\n# When STARTING a step:\npython scripts/telnyx_api.py update-step \"$MISSION_ID\" \"$RUN_ID\" \"research\" \"in_progress\"\npython scripts/telnyx_api.py log-event \"$MISSION_ID\" \"$RUN_ID\" step_started \"Starting: Research\" \"research\"\n\n# When COMPLETING a step:\npython scripts/telnyx_api.py update-step \"$MISSION_ID\" \"$RUN_ID\" \"research\" \"completed\"\npython scripts/telnyx_api.py log-event \"$MISSION_ID\" \"$RUN_ID\" step_completed \"Completed: Research\" \"research\"\n\n# When a step FAILS:\npython scripts/telnyx_api.py update-step \"$MISSION_ID\" \"$RUN_ID\" \"calls\" \"failed\"\npython scripts/telnyx_api.py log-event \"$MISSION_ID\" \"$RUN_ID\" error \"Failed: Could not reach contractors\" \"calls\""
      },
      {
        "title": "Quick Reference: All Python Commands",
        "body": "# Check setup\npython scripts/telnyx_api.py check-key\n\n# Missions\npython scripts/telnyx_api.py create-mission <name> <instructions>\npython scripts/telnyx_api.py get-mission <mission_id>\npython scripts/telnyx_api.py list-missions\n\n# Runs\npython scripts/telnyx_api.py create-run <mission_id> <input_json>\npython scripts/telnyx_api.py get-run <mission_id> <run_id>\npython scripts/telnyx_api.py update-run <mission_id> <run_id> <status>\npython scripts/telnyx_api.py list-runs <mission_id>\n\n# Plan\npython scripts/telnyx_api.py create-plan <mission_id> <run_id> <steps_json>\npython scripts/telnyx_api.py get-plan <mission_id> <run_id>\npython scripts/telnyx_api.py update-step <mission_id> <run_id> <step_id> <status>\n\n# Events\npython scripts/telnyx_api.py log-event <mission_id> <run_id> <type> <summary> <step_id> [payload_json]\npython scripts/telnyx_api.py list-events <mission_id> <run_id>\n\n# Assistants\npython scripts/telnyx_api.py list-assistants [--name=<filter>] [--page=<n>] [--size=<n>]\npython scripts/telnyx_api.py create-assistant <name> <instructions> <greeting> [options_json]\npython scripts/telnyx_api.py get-assistant <assistant_id>\npython scripts/telnyx_api.py update-assistant <assistant_id> <updates_json>\npython scripts/telnyx_api.py get-connection-id <assistant_id> [telephony|messaging]\n\n# Phone Numbers\npython scripts/telnyx_api.py list-phones [--available]\npython scripts/telnyx_api.py get-available-phone\npython scripts/telnyx_api.py assign-phone <phone_id> <connection_id> [voice|sms]\n\n# Scheduled Events\npython scripts/telnyx_api.py schedule-call <assistant_id> <to> <from> <datetime> <mission_id> <run_id>\npython scripts/telnyx_api.py schedule-sms <assistant_id> <to> <from> <datetime> <text>\npython scripts/telnyx_api.py get-event <assistant_id> <event_id>\npython scripts/telnyx_api.py cancel-scheduled-event <assistant_id> <event_id>\npython scripts/telnyx_api.py list-events-assistant <assistant_id>\n\n# Insights\npython scripts/telnyx_api.py get-insights <conversation_id>\n\n# Mission Run Agents\npython scripts/telnyx_api.py link-agent <mission_id> <run_id> <telnyx_agent_id>\npython scripts/telnyx_api.py list-linked-agents <mission_id> <run_id>\npython scripts/telnyx_api.py unlink-agent <mission_id> <run_id> <telnyx_agent_id>\n\n# State Management\npython scripts/telnyx_api.py list-state\npython scripts/telnyx_api.py get-state <slug>\npython scripts/telnyx_api.py remove-state <slug>\n\n# Memory\npython scripts/telnyx_api.py save-memory <slug> <key> <value_json>\npython scripts/telnyx_api.py get-memory <slug> [key]\npython scripts/telnyx_api.py append-memory <slug> <key> <item_json>\n\n# High-Level Workflows\npython scripts/telnyx_api.py init <name> <instructions> <request> [steps_json]\npython scripts/telnyx_api.py setup-agent <slug> <name> <instructions> <greeting>\npython scripts/telnyx_api.py complete <slug> <mission_id> <run_id> <summary> [payload_json]"
      },
      {
        "title": "Complete Example: SMS Mission with Cron Polling",
        "body": "Here's the full flow for an SMS mission with proper lifecycle tracking and cron-based polling:\n\n# 1. Init mission\npython scripts/telnyx_api.py init \"SMS Test 003\" \\\n  \"Send a test SMS to +13322200013\" \\\n  \"SMS test with full tracking\" \\\n  '[{\"step_id\": \"setup\", \"description\": \"Create SMS agent\", \"sequence\": 1},\n    {\"step_id\": \"sms\", \"description\": \"Schedule SMS\", \"sequence\": 2},\n    {\"step_id\": \"verify\", \"description\": \"Verify delivery\", \"sequence\": 3}]'\n# Save: mission_id, run_id\n\n# 2. Step 1: Setup agent\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID setup in_progress\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_started \"Starting: Create SMS agent\" setup\n\npython scripts/telnyx_api.py setup-agent \"sms-test-003\" \"SMS Agent\" \"Send test messages\" \"Test from bot\"\n# Save: assistant_id, phone_number\n\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID setup completed\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_completed \"Completed: Created assistant $ASSISTANT_ID\" setup\n\n# 3. Step 2: Schedule SMS\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID sms in_progress\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_started \"Starting: Schedule SMS\" sms\n\npython scripts/telnyx_api.py schedule-sms $ASSISTANT_ID \"+13322200013\" \"$PHONE\" \"2026-02-19T18:43:00Z\" \\\n  \"What do you call a bear with no teeth? A gummy bear!\" \\\n  $MISSION_ID $RUN_ID sms\n# Save: event_id\n\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID sms completed\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_completed \"Completed: SMS scheduled\" sms\n\n# 4. Step 3: Verify delivery — CREATE A CRON JOB TO POLL\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID verify in_progress\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_started \"Starting: Poll for delivery\" verify\n\n# >>> Create a cron job that fires AFTER the scheduled time <<<\n# >>> Cron runs: get-event $ASSISTANT_ID $EVENT_ID <<<\n# >>> On completed: update-step verify completed, log-event, update-run succeeded, DELETE CRON <<<\n# >>> On failed: update-step verify failed, log-event, update-run failed, DELETE CRON <<<\n# >>> On pending/in_progress: do nothing, cron fires again next interval <<<\n\n# 5. (Cron fires, detects completion)\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID verify completed\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_completed \"Completed: SMS delivered\" verify\npython scripts/telnyx_api.py update-run $MISSION_ID $RUN_ID succeeded\n# DELETE the polling cron job!"
      },
      {
        "title": "Mission Classes",
        "body": "Not all missions are the same. Identify which class before planning.\n\nDoes call N depend on results of call N-1?\n  YES -> Is it negotiation (leveraging previous results)?\n    YES -> Class 3: Sequential Negotiation\n    NO  -> Does it have distinct rounds with human approval?\n      YES -> Class 4: Multi-Round / Follow-up\n      NO  -> Class 5: Information Gathering -> Action\n  NO  -> Do you need structured scoring/ranking?\n    YES -> Class 2: Parallel Screening with Rubric\n    NO  -> Class 1: Parallel Sweep"
      },
      {
        "title": "Class 1: Parallel Sweep",
        "body": "Fan out calls in parallel batches. Same question to many targets. Schedule all calls in one batch (stagger by 1-2 min). Analysis happens after ALL calls complete."
      },
      {
        "title": "Class 2: Parallel Screening with Rubric",
        "body": "Fan out calls in parallel with structured scoring criteria. Results are ranked post-hoc via insights."
      },
      {
        "title": "Class 3: Sequential Negotiation",
        "body": "Calls MUST run serially. Each call's strategy depends on previous results. Use update-assistant between calls to inject context. Never parallelize these."
      },
      {
        "title": "Class 4: Multi-Round / Follow-up",
        "body": "Two or more distinct phases. Round 1 is broad outreach, human approval gate, then Round 2 targets a subset."
      },
      {
        "title": "Class 5: Information Gathering -> Action",
        "body": "Call to find something, then act on it. Early termination when goal is met — cancel remaining calls."
      },
      {
        "title": "Default Tools",
        "body": "The send_dtmf tool is included by default. Most outbound calls hit an IVR first."
      },
      {
        "title": "IVR Navigation",
        "body": "Expect IVRs even when calling businesses. Instruct the assistant to press 0 or say 'representative'."
      },
      {
        "title": "Call Limits and Throttling",
        "body": "Stagger calls in batches of 5-10, space scheduled times 1-2 minutes apart, monitor for 429 errors."
      },
      {
        "title": "Answering Machine Detection (AMD)",
        "body": "Enable for human contacts (leave voicemail or skip machines)\nDisable for IVR systems, businesses with phone trees — set action to continue_assistant"
      },
      {
        "title": "Polling for Results: Use Cron Jobs",
        "body": "After scheduling calls, set up a cron job to poll periodically. Don't block the main session."
      },
      {
        "title": "Retry Strategy",
        "body": "Track every number's status in mission memory. Retry based on recipient type:\n\nAutomated systems: retry in 5-15 min, up to 3 times\nService industry: retry in 30 min - 2 hours, avoid peak hours\nProfessionals: retry next business day, leave one voicemail max"
      },
      {
        "title": "Approval Requests (Sensitive Actions)",
        "body": "For destructive or sensitive actions during voice calls, request user approval first:\n\n./scripts/approval.sh request \"Delete GitHub repo myproject\"\n./scripts/approval.sh request \"Send $500 to John\" --biometric\n./scripts/approval.sh request \"Post tweet about X\" --details \"Full text: ...\"\n\nWhen to request approval:\n\nDeleting repos, files, or data\nSending money or making purchases\nPosting to social media\nSending emails/messages to others\nAny irreversible action\n\nResponse values:\n\napproved → Execute the action, confirm completion\ndenied → Tell user \"Okay, I won't do that\"\ntimeout → \"I didn't get a response, should I try again?\"\nno_devices → Skip approval, action not executed (no mobile app)\n\nExample flow in voice call:\n\nUser: \"Delete my test-repo on GitHub\"\nYou: \"I'll need your approval for that. Check your phone.\"\nRun: approval.sh request \"Delete GitHub repo test-repo\"\nIf approved: Delete the repo, then say \"Done, test-repo has been deleted\"\nIf denied: \"Got it, I won't delete it\""
      },
      {
        "title": "Gateway Requirements",
        "body": "Voice calls route requests to the main agent via sessions_send. This tool is blocked by default on the Gateway HTTP tools API. You must explicitly allow it:\n\n// In openclaw.json → gateway.tools\n{\n  \"gateway\": {\n    \"tools\": {\n      \"allow\": [\"sessions_send\"]\n    }\n  }\n}\n\nOr via CLI: openclaw config patch '{\"gateway\":{\"tools\":{\"allow\":[\"sessions_send\"]}}}'\n\nWithout this, voice calls will connect but the agent won't be able to process any requests (deep tool calls return 404).\n\n⚠️ WARNING: This MUST go under gateway.tools.allow, NOT top-level tools.allow. The top-level tools.allow is the agent's tool allowlist — putting sessions_send there will restrict your agent to ONLY that tool, breaking everything. If you accidentally did this, remove the top-level tools.allow entry and restart."
      },
      {
        "title": "❌ Common Pitfalls",
        "body": "MistakeSymptomFixDifferent slug for init vs setup-agentScheduled events missing from frontendlist-state after init, copy-paste slugForgetting save-memory after actionsFrontend shows nothingSave immediately after every actionNot checking mission status after step changesMission stuck \"running\" foreverRun decision tree after every stepLeaving polling crons runningWasted resources, stale pollsDelete cron on any terminal stateNot verifying list-linked-agents after setup-agentAgent not linked, events invisibleAlways verify, fix with link-agent"
      },
      {
        "title": "Configuration",
        "body": "Edit skill-config.json:\n\nOptionDescriptionapi_keyAPI key from clawdtalk.comserverServer URL (default: https://clawdtalk.com)owner_nameYour name (auto-detected from USER.md)agent_nameAgent name (auto-detected from IDENTITY.md)greetingCustom greeting for inbound calls\n\nEnvironment variables for the Python missions API:\n\nCLAWDTALK_API_KEY — your ClawdTalk API key (required for missions)\nCLAWDTALK_API_URL — override the API endpoint (default: https://clawdtalk.com/v1)"
      },
      {
        "title": "Troubleshooting",
        "body": "Auth failed: Regenerate API key at clawdtalk.com\nGateway token/port changed: Re-run ./setup.sh to update skill-config.json with the new values\nEmpty responses: Run ./setup.sh and restart gateway\nSlow responses: Try a faster model in your gateway config\nDebug mode: DEBUG=1 ./scripts/connect.sh restart\nMissions API key: Run python scripts/telnyx_api.py check-key to verify\nJSON parsing errors: Use single quotes around JSON arguments"
      }
    ],
    "body": "ClawdTalk\n\n⚠️ First time setup? Read SETUP.md in this directory before anything else. It walks you through the complete configuration flow step by step.\n\nVoice calling, SMS messaging, and AI Missions for Clawdbot. Call your bot by phone, send texts, or run autonomous multi-step outreach campaigns — powered by ClawdTalk.\n\nTrust: By using this skill, voice transcripts, SMS messages, and mission data are sent to clawdtalk.com (operated by Telnyx). Only install if you trust this service with your conversation data.\n\nExternal Endpoints\nEndpoint\tUsed by\tData sent\nhttps://clawdtalk.com (WebSocket)\tws-client.js\tVoice transcripts, tool results, conversation state\nhttps://clawdtalk.com/v1/*\ttelnyx_api.py\tMission state, events, scheduled calls/SMS, assistant configs\nhttp://127.0.0.1:<port>\tws-client.js\tTranscribed speech (local gateway only)\nhttps://raw.githubusercontent.com/team-telnyx/clawdtalk-client/...\tupdate.sh\tNone (download only)\nSecurity & Privacy\nVoice transcripts and SMS content are transmitted to clawdtalk.com.\nMission state and events are stored server-side for tracking and insights.\nsetup.sh reads gateway config to extract connection details; with confirmation it adds sessions_send to gateway.tools.allow.\nAPI key is stored in skill-config.json — use env var CLAWDTALK_API_KEY or a ${CLAWDTALK_API_KEY} reference to avoid plaintext storage.\n⚠️ CRITICAL: SLUG CONSISTENCY\n\ninit auto-generates a slug from the mission name (lowercased, spaces → hyphens). Every command that takes a slug (setup-agent, save-memory, complete) MUST use the EXACT same slug.\n\nMismatched slugs = agent not linked = scheduled events invisible on the frontend.\n\n# After init, ALWAYS confirm the slug:\npython scripts/telnyx_api.py list-state\n# Output: find-window-washing-contractors: Find window washing contractors [running]\n#         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ COPY-PASTE THIS. NEVER ABBREVIATE.\n\n⚠️ CRITICAL: YOU OWN THE MISSION LIFECYCLE\n\nThe server does NOT automatically update plan steps or mission status. That is YOUR job as the bot. If you don't update steps and complete the mission, the UI will show \"Running\" forever with all steps \"Pending\".\n\nYour Responsibilities\n\nFor every mission, YOU must:\n\nUpdate plan steps — mark each step in_progress → completed (or failed)\nLog events — after every significant action\nPoll for completion — check if scheduled calls/SMS finished\nComplete the mission — mark the run as succeeded or failed\nClean up — remove any polling cron jobs when the mission ends\n\nThe UI reflects exactly what you tell it. No updates from you = no updates on screen.\n\n🚨 MANDATORY: SAVE TO MEMORY AFTER EVERY ACTION\n\nEvery significant action MUST be persisted using save-memory or append-memory IMMEDIATELY after the action succeeds. The frontend reads from server memory. If you don't save it, it doesn't show up. log-event alone is NOT enough.\n\nRule: If you did something, save it to memory. No exceptions. No \"I'll do it later.\" Do it NOW.\n\nExample (scheduling an SMS):\n\n# 1. Schedule it\npython scripts/telnyx_api.py schedule-sms $AID \"$TO\" \"$FROM\" \"$DATETIME\" \"$MESSAGE\" $MID $RID $STEP_ID\n\n# 2. IMMEDIATELY save to memory\npython scripts/telnyx_api.py append-memory \"$SLUG\" \"scheduled_events\" \\\n  '{\"event_id\": \"<id>\", \"type\": \"sms\", \"to\": \"<to>\", \"message\": \"<msg>\", \"scheduled_at\": \"<dt>\", \"step_id\": \"<step>\"}'\n\n# 3. Then log the event\npython scripts/telnyx_api.py log-event $MID $RID custom \"Scheduled SMS event_id=<id>\" $STEP_ID\n\n\nSkipping step 2 is the #1 cause of \"nothing shows on the frontend\" bugs.\n\n🚨 MANDATORY: CHECK MISSION STATUS AFTER EVERY STEP\n\nAfter completing or failing ANY step, you MUST check whether the mission should be completed or failed. Never leave a mission in \"running\" state when it's actually done or dead.\n\nRule: After every step change, ask yourself: is this mission finished?\n\nDecision tree (run after EVERY step):\nStep finished →\n  ├── Succeeded?\n  │     ├── All steps done? → COMPLETE MISSION (update-run succeeded)\n  │     ├── More steps remain? → Continue to next step\n  │     └── Only verify left? → Set up polling cron\n  └── Failed?\n        ├── Recoverable (retry/reschedule)? → Retry\n        └── Unrecoverable? → FAIL MISSION NOW:\n              1. update-step <step_id> failed\n              2. log-event error \"Failed: <reason>\" <step_id>\n              3. save-memory \"$SLUG\" \"error_<step_id>\" '{\"error\": \"...\", \"recoverable\": false}'\n              4. update-run $MID $RID failed\n              5. save-memory \"$SLUG\" \"result\" '{\"status\": \"failed\", \"reason\": \"...\", \"failed_step\": \"...\"}'\n              6. Clean up any polling cron jobs\n\n\nA mission stuck in \"running\" when it's actually done or dead is a bug. The user sees it and thinks work is still happening.\n\nArchitecture Overview\nHow It Fits Together\n┌──────────────┐     ┌──────────────────┐     ┌──────────────┐\n│  You (Bot)   │────▶│  ClawdTalk Server │────▶│  Telnyx API  │\n│              │     │  (dev/prod)       │     │  (cloud)     │\n│ telnyx_api.py│     │  Local DB + proxy │     │  Executes    │\n│              │     │  to Telnyx        │     │  calls/SMS   │\n└──────────────┘     └──────────────────┘     └──────────────┘\n\ntelnyx_api.py — Python CLI script. Every command you run goes through this. It talks to the ClawdTalk server, never directly to Telnyx.\nClawdTalk Server — Node.js backend. Stores missions, assistants, and events in a local Postgres DB. Proxies requests to the Telnyx API.\nTelnyx API — Cloud service. Actually makes the calls and sends the SMS at the scheduled time.\nKey Files\nFile\tPurpose\nscripts/telnyx_api.py\tCLI tool for all mission/assistant/event operations\nscripts/connect.sh\tWebSocket client for inbound voice call routing\nskill-config.json\tAPI key and server URL\n.missions_state.json\tLocal state tracking for active missions\n.connect.log\tWebSocket connection logs\nTwo Sets of IDs\n\nEvery entity exists in two places with different IDs:\n\nLocal DB ID — what the ClawdTalk server returns (e.g. 3df24dde-...)\nTelnyx ID — what the Telnyx API uses internally\n\nThe script always works with local IDs. You don't need to worry about Telnyx IDs.\n\nQuick Start\nSign up at clawdtalk.com\nAdd your phone in Settings\nGet API key from Dashboard\nRun setup: ./setup.sh\n\nsetup.sh reads your gateway config to extract connection details and (with confirmation) adds sessions_send to gateway.tools.allow. Gateway config is at ~/.openclaw/openclaw.json or ~/.clawdbot/clawdbot.json.\n\nStart connection: ./scripts/connect.sh start\nVoice Calls\n\nThe WebSocket client routes calls to your gateway's main agent session, giving full access to memory, tools, and context.\n\n./scripts/connect.sh start     # Start connection\n./scripts/connect.sh stop      # Stop\n./scripts/connect.sh status    # Check status\n\nOutbound Calls\n\nHave the bot call you or others:\n\n./scripts/call.sh                              # Call your phone\n./scripts/call.sh \"Hey, what's up?\"            # Call with greeting\n./scripts/call.sh --to +15551234567            # Call external number*\n./scripts/call.sh --to +15551234567 \"Hello!\"   # External with greeting\n./scripts/call.sh status <call_id>             # Check call status\n./scripts/call.sh end <call_id>                # End call\n\n\n*External calls require a paid account with a dedicated number. The AI will operate in privacy mode when calling external numbers (won't reveal your private info).\n\nSMS\n\nSend and receive text messages:\n\n./scripts/sms.sh send +15551234567 \"Hello!\"\n./scripts/sms.sh list\n./scripts/sms.sh conversations\n\nAI Missions (Full Tracking via Python)\n\nFor complex, multi-step missions with full tracking, state persistence, retries, and conversation insights, use the Python-based missions API.\n\nRequired: Python 3.7+, CLAWDTALK_API_KEY environment variable. Optionally set CLAWDTALK_API_URL to override the default endpoint (defaults to https://clawdtalk.com/v1).\n\npython scripts/telnyx_api.py check-key    # Verify setup\n\nCRITICAL: SAVE STATE FREQUENTLY\n\nYou MUST save your progress after EVERY significant action. If the session crashes or restarts, unsaved work is LOST.\n\nTwo-Layer Persistence: Memory + Events\n\nAlways save to BOTH:\n\nLocal Memory (.missions_state.json) - Fast, survives restarts\nEvents API (cloud) - Permanent audit trail, survives local file loss\nWhen to Save (After EVERY action!)\nAction\tSave Memory\tLog Event\nWeb search returns results\tappend-memory\tlog-event (tool_call)\nFound a contractor/lead\tappend-memory\tlog-event (custom)\nCreated assistant\tsave-memory\tlog-event (custom)\nAssigned phone number\tsave-memory\tlog-event (custom)\nScheduled a call/SMS\tappend-memory\tlog-event (custom)\nCall completed\tsave-memory\tlog-event (custom)\nGot quote/insight\tsave-memory\tlog-event (custom)\nMade a decision\tsave-memory\tlog-event (message)\nStep started\tsave-memory\tupdate-step (in_progress) + log-event (step_started)\nStep completed\tsave-memory\tupdate-step (completed) + log-event (step_completed)\nStep failed\tsave-memory\tupdate-step (failed) + log-event (error)\nError occurred\tsave-memory\tlog-event (error)\nMemory Commands (Local Backup)\n# Save a single value\npython scripts/telnyx_api.py save-memory \"<slug>\" \"key\" '{\"data\": \"value\"}'\n\n# Append to a list (great for collecting multiple items)\npython scripts/telnyx_api.py append-memory \"<slug>\" \"contractors\" '{\"name\": \"ABC Co\", \"phone\": \"+1234567890\"}'\n\n# Retrieve memory\npython scripts/telnyx_api.py get-memory \"<slug>\"           # Get all memory\npython scripts/telnyx_api.py get-memory \"<slug>\" \"key\"     # Get specific key\n\nEvent Commands (Cloud Backup)\n# Log an event (step_id is REQUIRED - links event to a plan step)\npython scripts/telnyx_api.py log-event <mission_id> <run_id> <type> \"<summary>\" <step_id> '[payload_json]'\n\n# Event types: tool_call, custom, message, error, step_started, step_completed\n# step_id: Use the step_id from your plan (e.g., \"research\", \"setup\", \"calls\")\n#          Use \"-\" if event doesn't belong to a specific step\n\nWhen to Use Missions\n\nThis skill has two modes: full missions (tracked, multi-step) and simple calls (one-off, no mission overhead). Pick the right one.\n\nUse a Full Mission When:\nThe task involves multiple calls or SMS (batch outreach, surveys, sweeps)\nYou need a complete audit trail with events, plans, and state tracking\nThe task is multi-step and takes significant effort across phases\nRetries and failure tracking matter\nYou need to compare results across multiple calls\n\nExamples:\n\n\"Find me window washing contractors in Chicago, call them and negotiate rates\"\n\"Contact all leads in this list and schedule demos\"\n\"Call 10 weather stations and find the hottest one\"\nDo NOT Use a Mission When:\nThe task is a single outbound call — just create an assistant (or reuse one) and schedule the call directly\nIt's a one-off SMS — schedule it and done\nThe task doesn't need tracking, plans, or state recovery\nYou'd be creating a mission with one step and one call — that's overengineering\n\nFor simple calls, just:\n\n# Reuse or create an assistant\npython scripts/telnyx_api.py list-assistants --name=<relevant>\n# Schedule the call\npython scripts/telnyx_api.py schedule-call <assistant_id> <to> <from> <datetime> <mission_id> <run_id>\n# Poll for completion\npython scripts/telnyx_api.py get-event <assistant_id> <event_id>\n# Get insights\npython scripts/telnyx_api.py get-insights <conversation_id>\n\n\nNo mission, no run, no plan. Keep it simple.\n\nState Persistence\n\nThe script automatically manages state in .missions_state.json. This survives restarts and supports multiple concurrent missions.\n\npython scripts/telnyx_api.py list-state                              # List all active missions\npython scripts/telnyx_api.py get-state \"find-window-washing-contractors\"  # Get state for specific mission\npython scripts/telnyx_api.py remove-state \"find-window-washing-contractors\" # Remove mission from state\n\nCore Workflow\nPhase 1: Initialize Tracking\nStep 1.1: Create a Mission\npython scripts/telnyx_api.py create-mission \"Brief descriptive name\" \"Full description of the task\"\n\n\nSave the returned mission_id - you'll need it for all subsequent calls.\n\nStep 1.2: Start a Run\npython scripts/telnyx_api.py create-run <mission_id> '{\"original_request\": \"The exact user request\", \"context\": \"Any relevant context\"}'\n\n\nSave the returned run_id.\n\nStep 1.3: Create a Plan\n\nBefore executing, outline your plan:\n\npython scripts/telnyx_api.py create-plan <mission_id> <run_id> '[\n  {\"step_id\": \"step_1\", \"description\": \"Research contractors online\", \"sequence\": 1},\n  {\"step_id\": \"step_2\", \"description\": \"Create voice agent for calls\", \"sequence\": 2},\n  {\"step_id\": \"step_3\", \"description\": \"Schedule calls to each contractor\", \"sequence\": 3},\n  {\"step_id\": \"step_4\", \"description\": \"Monitor call completions\", \"sequence\": 4},\n  {\"step_id\": \"step_5\", \"description\": \"Analyze results and select best options\", \"sequence\": 5}\n]'\n\nStep 1.4: Set Run to Running\npython scripts/telnyx_api.py update-run <mission_id> <run_id> running\n\nHigh-Level Alternative: Initialize Everything at Once\n\nUse the init command to create mission, run, plan, and set status in one step:\n\npython scripts/telnyx_api.py init \"Find window washing contractors\" \"Find contractors in Chicago, call them, negotiate rates\" \"User wants window washing quotes\" '[\n  {\"step_id\": \"research\", \"description\": \"Find contractors online\", \"sequence\": 1},\n  {\"step_id\": \"setup\", \"description\": \"Create voice agent\", \"sequence\": 2},\n  {\"step_id\": \"calls\", \"description\": \"Schedule and make calls\", \"sequence\": 3},\n  {\"step_id\": \"analyze\", \"description\": \"Analyze results\", \"sequence\": 4}\n]'\n\n\nThis also automatically resumes if a mission with the same name already exists.\n\n⚠️ Immediately after init, run list-state and copy the exact slug. Use it for ALL subsequent commands.\n\nPhase 2: Voice/SMS Agent Setup\n\nWhen your task requires making calls or sending SMS, create an AI assistant first.\n\nStep 2.1: Create a Voice/SMS Assistant\n\nFor phone calls:\n\npython scripts/telnyx_api.py create-assistant \"Contractor Outreach Agent\" \"You are calling on behalf of [COMPANY]. Your goal is to [SPECIFIC GOAL]. Be professional and concise. Collect: [WHAT TO COLLECT]. If they cannot talk now, ask for a good callback time.\" \"Hi, this is an AI assistant calling on behalf of [COMPANY]. Is this [BUSINESS NAME]? I am calling to inquire about your services. Do you have a moment?\" '[\"telephony\", \"messaging\"]'\n\n\nFor SMS:\n\npython scripts/telnyx_api.py create-assistant \"SMS Outreach Agent\" \"You send SMS messages to collect information. Keep messages brief and professional.\" \"Hi! I am reaching out on behalf of [COMPANY] regarding [PURPOSE]. Could you please reply with [REQUESTED INFO]?\" '[\"telephony\", \"messaging\"]'\n\n\nSave the returned assistant_id.\n\nStep 2.2: Find and Assign a Phone Number\npython scripts/telnyx_api.py get-available-phone                          # Get first available\npython scripts/telnyx_api.py get-connection-id <assistant_id> telephony   # Get connection ID\npython scripts/telnyx_api.py assign-phone <phone_number_id> <connection_id> voice  # Assign\n\nHigh-Level Alternative: Setup Agent in One Step\npython scripts/telnyx_api.py setup-agent \"find-window-washing-contractors\" \"Contractor Caller\" \"You are calling to get quotes for commercial window washing. Ask about: rates per floor, availability, insurance. Be professional.\" \"Hi, I am calling to inquire about your commercial window washing services. Do you have a moment to discuss rates?\"\n\n\nThis automatically creates the assistant, links it to the mission run, finds an available phone number, assigns it, and saves all IDs to the state file.\n\n⚠️ The slug MUST match what init created. If it doesn't, the agent won't be linked and scheduled events won't appear on the frontend.\n\nVerify linking worked immediately after:\n\npython scripts/telnyx_api.py list-linked-agents <mission_id> <run_id>\n# Must show your assistant_id. If empty → slug was wrong. Fix with:\npython scripts/telnyx_api.py link-agent <mission_id> <run_id> <assistant_id>\n\nStep 2.3: Link Agent to Mission Run\n\nIf using setup-agent: Linking is done automatically (only if slug matches init).\n\nIf setting up manually:\n\npython scripts/telnyx_api.py link-agent <mission_id> <run_id> <assistant_id>\npython scripts/telnyx_api.py list-linked-agents <mission_id> <run_id>\npython scripts/telnyx_api.py unlink-agent <mission_id> <run_id> <assistant_id>\n\nPhase 3: Scheduling Calls/SMS\nBusiness Hours Consideration\n\nCRITICAL: Before scheduling calls, consider business hours (9 AM - 5 PM local time). scheduled_at must be in the future (at least 1 minute from now).\n\npython scripts/telnyx_api.py schedule-call <assistant_id> \"+15551234567\" \"+15559876543\" \"2024-12-01T14:30:00Z\" <mission_id> <run_id>\npython scripts/telnyx_api.py schedule-sms <assistant_id> \"+15551234567\" \"+15559876543\" \"2024-12-01T14:30:00Z\" \"Your message here\"\n\n\nSave the returned event id.\n\nPhase 4: Monitoring Call Completion\n⚠️ THIS IS THE MOST IMPORTANT PART\n\nAfter scheduling a call or SMS, Telnyx executes it autonomously at the scheduled time. You need to poll to find out when it's done, then update the mission accordingly.\n\nCheck Scheduled Event Status\npython scripts/telnyx_api.py get-event <assistant_id> <event_id>\n\nUse Cron Jobs to Poll\n\nUse your bot's cron system to schedule polling. Do NOT block the main session waiting. Match the poll interval to the expected wait time:\n\nExpected completion\tPoll interval\tExample\n< 5 minutes\tEvery 30 seconds\tSMS sent 1 min from now\n5–30 minutes\tEvery 2–5 minutes\tCall scheduled in 15 min\n1–24 hours\tEvery 15–30 minutes\tCall scheduled for tonight\nDays/weeks\tEvery 4–8 hours\tCall scheduled for next week\n\nIf you know the exact scheduled time, don't start polling until after that time. Schedule your first poll for scheduled_time + 2 minutes.\n\nCron Job Pattern\n\nWhen you schedule a call/SMS, create a cron job to poll for it:\n\nCreate cron: poll at appropriate interval\n  → Run get-event <assistant_id> <event_id>\n  → If completed: update step, log event, complete mission if last step, DELETE THIS CRON\n  → If failed: update step as failed, log error, DELETE THIS CRON\n  → If pending/in_progress: do nothing, cron runs again at next interval\n\n\n⚠️ ALWAYS clean up cron jobs when a mission reaches a terminal state (completed, failed, cancelled). Never leave polling crons running after a mission ends.\n\nAdjusting Poll Frequency\n\nYou can update the cron interval as circumstances change:\n\nScheduled for 2 weeks from now? Start with 8-hour polling.\nAs the scheduled time approaches (within 1 hour), tighten to 5-minute intervals.\nAfter the scheduled time passes, tighten to 30-second intervals.\nEvent Status Values\nStatus\tMeaning\tAction\npending\tWaiting for scheduled time\tKeep polling\nin_progress\tCall/SMS in progress\tKeep polling\ncompleted\tFinished successfully\tUpdate step, get insights if call\nfailed\tFailed after retries\tUpdate step as failed, consider retry\nCall Status Values (Phone Calls Only)\ncall_status\tMeaning\tAction\nringing\tPhone is ringing\tPoll again in 1-2 minutes\nin-progress\tCall is active\tPoll again in 2-3 minutes\ncompleted\tCall finished normally\tGet insights\nno-answer\tNobody picked up\tRetryable — reschedule\nbusy\tLine is busy\tRetryable — retry in 10-15 min\ncanceled\tCall was canceled\tCheck if intentional\nfailed\tNetwork/system error\tRetryable — retry in 5-10 min\nPhase 5: Getting Conversation Insights\n\nOnce a call completes with a conversation_id, retrieve insights. Poll until status is \"completed\" (wait 10 seconds between retries).\n\npython scripts/telnyx_api.py get-insights <conversation_id>\n\n\nTelnyx automatically creates default insight templates when an assistant is created. You don't need to manage these — just read the results.\n\nPhase 6: Complete the Mission\npython scripts/telnyx_api.py update-run <mission_id> <run_id> succeeded\n\n# Or with full results:\npython scripts/telnyx_api.py complete \"find-window-washing-contractors\" <mission_id> <run_id> \"Summary of results\" '{\"key\": \"payload\"}'\n\nEvent Logging Reference\n\nLog EVERY action as an event. Always update step status via update-step AND log corresponding events.\n\n# When STARTING a step:\npython scripts/telnyx_api.py update-step \"$MISSION_ID\" \"$RUN_ID\" \"research\" \"in_progress\"\npython scripts/telnyx_api.py log-event \"$MISSION_ID\" \"$RUN_ID\" step_started \"Starting: Research\" \"research\"\n\n# When COMPLETING a step:\npython scripts/telnyx_api.py update-step \"$MISSION_ID\" \"$RUN_ID\" \"research\" \"completed\"\npython scripts/telnyx_api.py log-event \"$MISSION_ID\" \"$RUN_ID\" step_completed \"Completed: Research\" \"research\"\n\n# When a step FAILS:\npython scripts/telnyx_api.py update-step \"$MISSION_ID\" \"$RUN_ID\" \"calls\" \"failed\"\npython scripts/telnyx_api.py log-event \"$MISSION_ID\" \"$RUN_ID\" error \"Failed: Could not reach contractors\" \"calls\"\n\nQuick Reference: All Python Commands\n# Check setup\npython scripts/telnyx_api.py check-key\n\n# Missions\npython scripts/telnyx_api.py create-mission <name> <instructions>\npython scripts/telnyx_api.py get-mission <mission_id>\npython scripts/telnyx_api.py list-missions\n\n# Runs\npython scripts/telnyx_api.py create-run <mission_id> <input_json>\npython scripts/telnyx_api.py get-run <mission_id> <run_id>\npython scripts/telnyx_api.py update-run <mission_id> <run_id> <status>\npython scripts/telnyx_api.py list-runs <mission_id>\n\n# Plan\npython scripts/telnyx_api.py create-plan <mission_id> <run_id> <steps_json>\npython scripts/telnyx_api.py get-plan <mission_id> <run_id>\npython scripts/telnyx_api.py update-step <mission_id> <run_id> <step_id> <status>\n\n# Events\npython scripts/telnyx_api.py log-event <mission_id> <run_id> <type> <summary> <step_id> [payload_json]\npython scripts/telnyx_api.py list-events <mission_id> <run_id>\n\n# Assistants\npython scripts/telnyx_api.py list-assistants [--name=<filter>] [--page=<n>] [--size=<n>]\npython scripts/telnyx_api.py create-assistant <name> <instructions> <greeting> [options_json]\npython scripts/telnyx_api.py get-assistant <assistant_id>\npython scripts/telnyx_api.py update-assistant <assistant_id> <updates_json>\npython scripts/telnyx_api.py get-connection-id <assistant_id> [telephony|messaging]\n\n# Phone Numbers\npython scripts/telnyx_api.py list-phones [--available]\npython scripts/telnyx_api.py get-available-phone\npython scripts/telnyx_api.py assign-phone <phone_id> <connection_id> [voice|sms]\n\n# Scheduled Events\npython scripts/telnyx_api.py schedule-call <assistant_id> <to> <from> <datetime> <mission_id> <run_id>\npython scripts/telnyx_api.py schedule-sms <assistant_id> <to> <from> <datetime> <text>\npython scripts/telnyx_api.py get-event <assistant_id> <event_id>\npython scripts/telnyx_api.py cancel-scheduled-event <assistant_id> <event_id>\npython scripts/telnyx_api.py list-events-assistant <assistant_id>\n\n# Insights\npython scripts/telnyx_api.py get-insights <conversation_id>\n\n# Mission Run Agents\npython scripts/telnyx_api.py link-agent <mission_id> <run_id> <telnyx_agent_id>\npython scripts/telnyx_api.py list-linked-agents <mission_id> <run_id>\npython scripts/telnyx_api.py unlink-agent <mission_id> <run_id> <telnyx_agent_id>\n\n# State Management\npython scripts/telnyx_api.py list-state\npython scripts/telnyx_api.py get-state <slug>\npython scripts/telnyx_api.py remove-state <slug>\n\n# Memory\npython scripts/telnyx_api.py save-memory <slug> <key> <value_json>\npython scripts/telnyx_api.py get-memory <slug> [key]\npython scripts/telnyx_api.py append-memory <slug> <key> <item_json>\n\n# High-Level Workflows\npython scripts/telnyx_api.py init <name> <instructions> <request> [steps_json]\npython scripts/telnyx_api.py setup-agent <slug> <name> <instructions> <greeting>\npython scripts/telnyx_api.py complete <slug> <mission_id> <run_id> <summary> [payload_json]\n\nComplete Example: SMS Mission with Cron Polling\n\nHere's the full flow for an SMS mission with proper lifecycle tracking and cron-based polling:\n\n# 1. Init mission\npython scripts/telnyx_api.py init \"SMS Test 003\" \\\n  \"Send a test SMS to +13322200013\" \\\n  \"SMS test with full tracking\" \\\n  '[{\"step_id\": \"setup\", \"description\": \"Create SMS agent\", \"sequence\": 1},\n    {\"step_id\": \"sms\", \"description\": \"Schedule SMS\", \"sequence\": 2},\n    {\"step_id\": \"verify\", \"description\": \"Verify delivery\", \"sequence\": 3}]'\n# Save: mission_id, run_id\n\n# 2. Step 1: Setup agent\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID setup in_progress\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_started \"Starting: Create SMS agent\" setup\n\npython scripts/telnyx_api.py setup-agent \"sms-test-003\" \"SMS Agent\" \"Send test messages\" \"Test from bot\"\n# Save: assistant_id, phone_number\n\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID setup completed\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_completed \"Completed: Created assistant $ASSISTANT_ID\" setup\n\n# 3. Step 2: Schedule SMS\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID sms in_progress\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_started \"Starting: Schedule SMS\" sms\n\npython scripts/telnyx_api.py schedule-sms $ASSISTANT_ID \"+13322200013\" \"$PHONE\" \"2026-02-19T18:43:00Z\" \\\n  \"What do you call a bear with no teeth? A gummy bear!\" \\\n  $MISSION_ID $RUN_ID sms\n# Save: event_id\n\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID sms completed\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_completed \"Completed: SMS scheduled\" sms\n\n# 4. Step 3: Verify delivery — CREATE A CRON JOB TO POLL\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID verify in_progress\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_started \"Starting: Poll for delivery\" verify\n\n# >>> Create a cron job that fires AFTER the scheduled time <<<\n# >>> Cron runs: get-event $ASSISTANT_ID $EVENT_ID <<<\n# >>> On completed: update-step verify completed, log-event, update-run succeeded, DELETE CRON <<<\n# >>> On failed: update-step verify failed, log-event, update-run failed, DELETE CRON <<<\n# >>> On pending/in_progress: do nothing, cron fires again next interval <<<\n\n# 5. (Cron fires, detects completion)\npython scripts/telnyx_api.py update-step $MISSION_ID $RUN_ID verify completed\npython scripts/telnyx_api.py log-event $MISSION_ID $RUN_ID step_completed \"Completed: SMS delivered\" verify\npython scripts/telnyx_api.py update-run $MISSION_ID $RUN_ID succeeded\n# DELETE the polling cron job!\n\nMission Classes\n\nNot all missions are the same. Identify which class before planning.\n\nDoes call N depend on results of call N-1?\n  YES -> Is it negotiation (leveraging previous results)?\n    YES -> Class 3: Sequential Negotiation\n    NO  -> Does it have distinct rounds with human approval?\n      YES -> Class 4: Multi-Round / Follow-up\n      NO  -> Class 5: Information Gathering -> Action\n  NO  -> Do you need structured scoring/ranking?\n    YES -> Class 2: Parallel Screening with Rubric\n    NO  -> Class 1: Parallel Sweep\n\nClass 1: Parallel Sweep\n\nFan out calls in parallel batches. Same question to many targets. Schedule all calls in one batch (stagger by 1-2 min). Analysis happens after ALL calls complete.\n\nClass 2: Parallel Screening with Rubric\n\nFan out calls in parallel with structured scoring criteria. Results are ranked post-hoc via insights.\n\nClass 3: Sequential Negotiation\n\nCalls MUST run serially. Each call's strategy depends on previous results. Use update-assistant between calls to inject context. Never parallelize these.\n\nClass 4: Multi-Round / Follow-up\n\nTwo or more distinct phases. Round 1 is broad outreach, human approval gate, then Round 2 targets a subset.\n\nClass 5: Information Gathering -> Action\n\nCall to find something, then act on it. Early termination when goal is met — cancel remaining calls.\n\nOperational Guide\nDefault Tools\n\nThe send_dtmf tool is included by default. Most outbound calls hit an IVR first.\n\nIVR Navigation\n\nExpect IVRs even when calling businesses. Instruct the assistant to press 0 or say 'representative'.\n\nCall Limits and Throttling\n\nStagger calls in batches of 5-10, space scheduled times 1-2 minutes apart, monitor for 429 errors.\n\nAnswering Machine Detection (AMD)\nEnable for human contacts (leave voicemail or skip machines)\nDisable for IVR systems, businesses with phone trees — set action to continue_assistant\nPolling for Results: Use Cron Jobs\n\nAfter scheduling calls, set up a cron job to poll periodically. Don't block the main session.\n\nRetry Strategy\n\nTrack every number's status in mission memory. Retry based on recipient type:\n\nAutomated systems: retry in 5-15 min, up to 3 times\nService industry: retry in 30 min - 2 hours, avoid peak hours\nProfessionals: retry next business day, leave one voicemail max\nApproval Requests (Sensitive Actions)\n\nFor destructive or sensitive actions during voice calls, request user approval first:\n\n./scripts/approval.sh request \"Delete GitHub repo myproject\"\n./scripts/approval.sh request \"Send $500 to John\" --biometric\n./scripts/approval.sh request \"Post tweet about X\" --details \"Full text: ...\"\n\n\nWhen to request approval:\n\nDeleting repos, files, or data\nSending money or making purchases\nPosting to social media\nSending emails/messages to others\nAny irreversible action\n\nResponse values:\n\napproved → Execute the action, confirm completion\ndenied → Tell user \"Okay, I won't do that\"\ntimeout → \"I didn't get a response, should I try again?\"\nno_devices → Skip approval, action not executed (no mobile app)\n\nExample flow in voice call:\n\nUser: \"Delete my test-repo on GitHub\"\nYou: \"I'll need your approval for that. Check your phone.\"\nRun: approval.sh request \"Delete GitHub repo test-repo\"\nIf approved: Delete the repo, then say \"Done, test-repo has been deleted\"\nIf denied: \"Got it, I won't delete it\"\nGateway Requirements\n\nVoice calls route requests to the main agent via sessions_send. This tool is blocked by default on the Gateway HTTP tools API. You must explicitly allow it:\n\n// In openclaw.json → gateway.tools\n{\n  \"gateway\": {\n    \"tools\": {\n      \"allow\": [\"sessions_send\"]\n    }\n  }\n}\n\n\nOr via CLI: openclaw config patch '{\"gateway\":{\"tools\":{\"allow\":[\"sessions_send\"]}}}'\n\nWithout this, voice calls will connect but the agent won't be able to process any requests (deep tool calls return 404).\n\n⚠️ WARNING: This MUST go under gateway.tools.allow, NOT top-level tools.allow. The top-level tools.allow is the agent's tool allowlist — putting sessions_send there will restrict your agent to ONLY that tool, breaking everything. If you accidentally did this, remove the top-level tools.allow entry and restart.\n\n❌ Common Pitfalls\nMistake\tSymptom\tFix\nDifferent slug for init vs setup-agent\tScheduled events missing from frontend\tlist-state after init, copy-paste slug\nForgetting save-memory after actions\tFrontend shows nothing\tSave immediately after every action\nNot checking mission status after step changes\tMission stuck \"running\" forever\tRun decision tree after every step\nLeaving polling crons running\tWasted resources, stale polls\tDelete cron on any terminal state\nNot verifying list-linked-agents after setup-agent\tAgent not linked, events invisible\tAlways verify, fix with link-agent\nConfiguration\n\nEdit skill-config.json:\n\nOption\tDescription\napi_key\tAPI key from clawdtalk.com\nserver\tServer URL (default: https://clawdtalk.com)\nowner_name\tYour name (auto-detected from USER.md)\nagent_name\tAgent name (auto-detected from IDENTITY.md)\ngreeting\tCustom greeting for inbound calls\n\nEnvironment variables for the Python missions API:\n\nCLAWDTALK_API_KEY — your ClawdTalk API key (required for missions)\nCLAWDTALK_API_URL — override the API endpoint (default: https://clawdtalk.com/v1)\nTroubleshooting\nAuth failed: Regenerate API key at clawdtalk.com\nGateway token/port changed: Re-run ./setup.sh to update skill-config.json with the new values\nEmpty responses: Run ./setup.sh and restart gateway\nSlow responses: Try a faster model in your gateway config\nDebug mode: DEBUG=1 ./scripts/connect.sh restart\nMissions API key: Run python scripts/telnyx_api.py check-key to verify\nJSON parsing errors: Use single quotes around JSON arguments"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/dcasem/clawdtalk-client",
    "publisherUrl": "https://clawhub.ai/dcasem/clawdtalk-client",
    "owner": "dcasem",
    "version": "2.0.5",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/clawdtalk-client",
    "downloadUrl": "https://openagent3.xyz/downloads/clawdtalk-client",
    "agentUrl": "https://openagent3.xyz/skills/clawdtalk-client/agent",
    "manifestUrl": "https://openagent3.xyz/skills/clawdtalk-client/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/clawdtalk-client/agent.md"
  }
}