{
  "schemaVersion": "1.0",
  "item": {
    "slug": "openclaw-phone",
    "name": "Openclaw phone",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/BenjaminWaye/openclaw-phone",
    "canonicalUrl": "https://clawhub.ai/BenjaminWaye/openclaw-phone",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/openclaw-phone",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=openclaw-phone",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SKILL.md",
      "examples/prompts.md",
      "docs/auth-config.md",
      "docs/event-updates.md",
      "agents/openai.yaml"
    ],
    "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. Then review README.md for any prerequisites, environment setup, or post-install checks. 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. Then review README.md for any prerequisites, environment setup, or post-install checks. 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/openclaw-phone"
    },
    "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/openclaw-phone",
    "agentPageUrl": "https://openagent3.xyz/skills/openclaw-phone/agent",
    "manifestUrl": "https://openagent3.xyz/skills/openclaw-phone/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/openclaw-phone/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. Then review README.md for any prerequisites, environment setup, or post-install checks. 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. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "CallMyCall (OpenClaw Skill)",
        "body": "This skill helps you operate CallMyCall from chat. It is pull based (no webhook callbacks): you start a call, store the returned call ID in state, and later fetch status and results on demand."
      },
      {
        "title": "API Key Resolution (OpenClaw best practice)",
        "body": "Resolve credentials in this order:\n\nEnvironment variable: CALLMYCALL_API_KEY (preferred)\nOpenClaw user config: ~/.openclaw/openclaw.json under skills.openclaw-phone.apiKey\nIf still missing, ask for a one-time key for the current task only.\nOnly if the user explicitly asks for persistence, provide manual instructions for saving the key to ~/.openclaw/openclaw.json.\n\nPersistence rules:\n\nNever store API keys in SKILL.md, examples, references, or memory/state files.\nDo not write API keys into recent_calls or any conversation-visible output. Do not tell the user “I won’t echo it back.”\nUse interactive keys for the current task only.\nDo not write user config files automatically from this skill."
      },
      {
        "title": "How This Skill Should Work",
        "body": "Resolve API key using the order in \"API Key Resolution (OpenClaw best practice)\".\nCollect required call info using a layered gating flow (below).\nPresent a short review summary and ask for confirmation.\nOn confirmation, call POST /v1/start-call.\nStore the returned sid in state as a recent call."
      },
      {
        "title": "Required Auth",
        "body": "Send the API key in the Authorization header:\n\nAuthorization: Bearer YOUR_API_KEY\n\nNever echo the API key back to the user or include it in logs/summaries."
      },
      {
        "title": "Stateful Calls List (required)",
        "body": "Maintain a list (last 10) of recent calls in state:\n\nrecent_calls: array of objects\n\nid (call SID)\nphone_number\ntask\nstarted_at\nstatus (optional, updated when you fetch)\n\nUse this list to let the user say \"end call 1\" or \"show results for call 2\"."
      },
      {
        "title": "Layered Gating Flow (copy from web app)",
        "body": "Do not rely on a single validation step. Use all layers below."
      },
      {
        "title": "Layer 1: Structured collection contract",
        "body": "Do not finalize a task until all required fields exist:\n\nphone_number\nlanguage\ncall_brief (background + goals)"
      },
      {
        "title": "Layer 2: Task gap analysis",
        "body": "When the user gives the initial request, analyze what is missing. Then ask only for missing info. If the user answers partially, repeat analysis and keep asking for the remaining gaps."
      },
      {
        "title": "Layer 3: Prompt level enforcement",
        "body": "While missing info exists, continue gathering required fields. Do not proceed to the call until all required fields are present."
      },
      {
        "title": "Layer 4: Runtime validation before finalizing",
        "body": "Before sending the call request:\n\nEnsure phone exists and is E.164\nBlock emergency or premium numbers\nEnsure from_number is not the same as phone_number\nIf from_number is requested, run caller-ID preflight:\n\nGET /v1/verified-caller-ids\nConfirm requested from_number exists in verified_caller_ids\nIf not verified: do not place call yet; ask user whether to continue with default caller ID or verify first\n\n\nNormalize language; normalize voice fields (genderVoice, openaiVoice) only if provided\nIf scheduling is present, parse and clamp to a valid time"
      },
      {
        "title": "Layer 5: Human review gate",
        "body": "Present a short review summary:\n\nPhone number\nCall brief (background + goals)\nLanguage (and voice if provided)\nAny schedule\n\nAsk: \"Confirm and place the call?\" Do not proceed without explicit confirmation."
      },
      {
        "title": "Start a Call",
        "body": "Collect required fields using the layered gating flow.\nIf from_number is provided, run caller-ID preflight via GET /v1/verified-caller-ids.\nIf requested from_number is not verified, ask user to choose:\n\ncontinue now with default caller ID, or\nverify number first (POST /v1/verify-caller-id, then GET /v1/verification-status/:verificationId).\n\n\nIf a schedule/time is requested, follow Scheduled Requests (No Cron) below instead of calling the API immediately.\nOtherwise call POST /v1/start-call.\nStore the returned sid in recent_calls.\nReply with confirmation and the call ID."
      },
      {
        "title": "Scheduled Requests (No Cron)",
        "body": "Because the API has no scheduling field:\n\nCollect all required fields now.\nSave a compact call plan in skill state only for in-session follow-up.\nDo not create or modify OS schedulers (cron, launchd, task scheduler) and do not run autonomous background turns.\nOffer one of these safe options:\n\nplace the call now, or\nprovide a reminder summary and ask the user to return at the target time to run start-call.\n\nIf the user asks to schedule for later, explain that this skill does not create background jobs; it can prepare the call plan and execute when the user confirms in-session."
      },
      {
        "title": "List Recent Calls",
        "body": "Read recent_calls from state.\nFor each call, fetch status via GET /v1/calls/:callId if needed.\nDisplay a numbered list."
      },
      {
        "title": "Retry Until Answered (important)",
        "body": "When the user asks to call repeatedly until answered:\n\nPlace one call with POST /v1/start-call.\nPoll GET /v1/calls/:callId until terminal status.\nTreat response as either flat (status, duration) or nested (call.status, call.duration).\nIf status is busy, no-answer, failed, or canceled, wait requested interval and place next call.\nStop retry loop when:\n\nstatus is in-progress, or\nstatus is completed with duration > 0.\n\n\nReport each attempt (call ID + status) back to user.\n\nImplementation note: keep one base URL per run (https://call-my-call-backend.fly.dev preferred) and use it consistently for both start + status endpoints."
      },
      {
        "title": "End a Call",
        "body": "If the user says \"end the call\" without specifying which, list recent calls and ask which one.\n\nIf there is only one active call, confirm and end it.\n\nCall:\n\nPOST /v1/end-call with { callSid }."
      },
      {
        "title": "Get Results",
        "body": "When the user asks for call results:\n\nFetch status via GET /v1/calls/:callId.\nIf available, fetch transcript via GET /v1/calls/:callId/transcripts/stream.\nIf the call was recorded, fetch recording URL via GET /v1/calls/:callSid/recording.\n\nReturn:\n\nStatus (completed, failed, canceled)\nShort summary (1 to 3 bullets)\nTranscript excerpt (first few lines, only after user asks to view transcript content)\nRecording URL (if present, warn that URL access may expose sensitive audio)"
      },
      {
        "title": "Safety and UX",
        "body": "If user input is ambiguous, ask a clarification question.\nNever expose secrets or store API keys in transcript.\nTreat transcripts and recordings as sensitive; share only minimal excerpts requested by the user.\nNever create persistent scheduler entries or autonomous background execution from this skill.\nIf a request fails, show the HTTP error and suggest next steps."
      },
      {
        "title": "References",
        "body": "Full API reference: references/api.md\nExamples: examples/prompts.md"
      }
    ],
    "body": "CallMyCall (OpenClaw Skill)\n\nThis skill helps you operate CallMyCall from chat. It is pull based (no webhook callbacks): you start a call, store the returned call ID in state, and later fetch status and results on demand.\n\nAPI Key Resolution (OpenClaw best practice)\n\nResolve credentials in this order:\n\nEnvironment variable: CALLMYCALL_API_KEY (preferred)\nOpenClaw user config: ~/.openclaw/openclaw.json under skills.openclaw-phone.apiKey\nIf still missing, ask for a one-time key for the current task only.\nOnly if the user explicitly asks for persistence, provide manual instructions for saving the key to ~/.openclaw/openclaw.json.\n\nPersistence rules:\n\nNever store API keys in SKILL.md, examples, references, or memory/state files.\nDo not write API keys into recent_calls or any conversation-visible output. Do not tell the user “I won’t echo it back.”\nUse interactive keys for the current task only.\nDo not write user config files automatically from this skill.\nHow This Skill Should Work\nResolve API key using the order in \"API Key Resolution (OpenClaw best practice)\".\nCollect required call info using a layered gating flow (below).\nPresent a short review summary and ask for confirmation.\nOn confirmation, call POST /v1/start-call.\nStore the returned sid in state as a recent call.\nRequired Auth\n\nSend the API key in the Authorization header:\n\nAuthorization: Bearer YOUR_API_KEY\n\n\nNever echo the API key back to the user or include it in logs/summaries.\n\nStateful Calls List (required)\n\nMaintain a list (last 10) of recent calls in state:\n\nrecent_calls: array of objects\nid (call SID)\nphone_number\ntask\nstarted_at\nstatus (optional, updated when you fetch)\n\nUse this list to let the user say \"end call 1\" or \"show results for call 2\".\n\nLayered Gating Flow (copy from web app)\n\nDo not rely on a single validation step. Use all layers below.\n\nLayer 1: Structured collection contract\n\nDo not finalize a task until all required fields exist:\n\nphone_number\nlanguage\ncall_brief (background + goals)\nLayer 2: Task gap analysis\n\nWhen the user gives the initial request, analyze what is missing. Then ask only for missing info. If the user answers partially, repeat analysis and keep asking for the remaining gaps.\n\nLayer 3: Prompt level enforcement\n\nWhile missing info exists, continue gathering required fields. Do not proceed to the call until all required fields are present.\n\nLayer 4: Runtime validation before finalizing\n\nBefore sending the call request:\n\nEnsure phone exists and is E.164\nBlock emergency or premium numbers\nEnsure from_number is not the same as phone_number\nIf from_number is requested, run caller-ID preflight:\nGET /v1/verified-caller-ids\nConfirm requested from_number exists in verified_caller_ids\nIf not verified: do not place call yet; ask user whether to continue with default caller ID or verify first\nNormalize language; normalize voice fields (genderVoice, openaiVoice) only if provided\nIf scheduling is present, parse and clamp to a valid time\nLayer 5: Human review gate\n\nPresent a short review summary:\n\nPhone number\nCall brief (background + goals)\nLanguage (and voice if provided)\nAny schedule\n\nAsk: \"Confirm and place the call?\" Do not proceed without explicit confirmation.\n\nWorkflows\nStart a Call\nCollect required fields using the layered gating flow.\nIf from_number is provided, run caller-ID preflight via GET /v1/verified-caller-ids.\nIf requested from_number is not verified, ask user to choose:\ncontinue now with default caller ID, or\nverify number first (POST /v1/verify-caller-id, then GET /v1/verification-status/:verificationId).\nIf a schedule/time is requested, follow Scheduled Requests (No Cron) below instead of calling the API immediately.\nOtherwise call POST /v1/start-call.\nStore the returned sid in recent_calls.\nReply with confirmation and the call ID.\nScheduled Requests (No Cron)\n\nBecause the API has no scheduling field:\n\nCollect all required fields now.\nSave a compact call plan in skill state only for in-session follow-up.\nDo not create or modify OS schedulers (cron, launchd, task scheduler) and do not run autonomous background turns.\nOffer one of these safe options:\nplace the call now, or\nprovide a reminder summary and ask the user to return at the target time to run start-call.\n\nIf the user asks to schedule for later, explain that this skill does not create background jobs; it can prepare the call plan and execute when the user confirms in-session.\n\nList Recent Calls\nRead recent_calls from state.\nFor each call, fetch status via GET /v1/calls/:callId if needed.\nDisplay a numbered list.\nRetry Until Answered (important)\n\nWhen the user asks to call repeatedly until answered:\n\nPlace one call with POST /v1/start-call.\nPoll GET /v1/calls/:callId until terminal status.\nTreat response as either flat (status, duration) or nested (call.status, call.duration).\nIf status is busy, no-answer, failed, or canceled, wait requested interval and place next call.\nStop retry loop when:\nstatus is in-progress, or\nstatus is completed with duration > 0.\nReport each attempt (call ID + status) back to user.\n\nImplementation note: keep one base URL per run (https://call-my-call-backend.fly.dev preferred) and use it consistently for both start + status endpoints.\n\nEnd a Call\n\nIf the user says \"end the call\" without specifying which, list recent calls and ask which one.\n\nIf there is only one active call, confirm and end it.\n\nCall:\n\nPOST /v1/end-call with { callSid }.\nGet Results\n\nWhen the user asks for call results:\n\nFetch status via GET /v1/calls/:callId.\nIf available, fetch transcript via GET /v1/calls/:callId/transcripts/stream.\nIf the call was recorded, fetch recording URL via GET /v1/calls/:callSid/recording.\n\nReturn:\n\nStatus (completed, failed, canceled)\nShort summary (1 to 3 bullets)\nTranscript excerpt (first few lines, only after user asks to view transcript content)\nRecording URL (if present, warn that URL access may expose sensitive audio)\nSafety and UX\nIf user input is ambiguous, ask a clarification question.\nNever expose secrets or store API keys in transcript.\nTreat transcripts and recordings as sensitive; share only minimal excerpts requested by the user.\nNever create persistent scheduler entries or autonomous background execution from this skill.\nIf a request fails, show the HTTP error and suggest next steps.\nReferences\nFull API reference: references/api.md\nExamples: examples/prompts.md"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/BenjaminWaye/openclaw-phone",
    "publisherUrl": "https://clawhub.ai/BenjaminWaye/openclaw-phone",
    "owner": "BenjaminWaye",
    "version": "1.0.1",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/openclaw-phone",
    "downloadUrl": "https://openagent3.xyz/downloads/openclaw-phone",
    "agentUrl": "https://openagent3.xyz/skills/openclaw-phone/agent",
    "manifestUrl": "https://openagent3.xyz/skills/openclaw-phone/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/openclaw-phone/agent.md"
  }
}