| name | alibabacloud-vms-smart-call-by-tts |
| description | Alicloud VMS Smart Voice Call Skill. Use for making AI-powered voice calls with natural language intent.
The system automatically matches contacts from the address book and generates call content via LLM.
Triggers: "ๆบ่ฝ่ฏญ้ณ้็ฅ", "AI ๆ็ต่ฏ", "smart voice call", "SubmitIntent", "็ปๆไบบๆ็ต่ฏ", "่ฏญ้ณ้็ฅๆ้".
|
Alibaba Cloud VMS Smart Voice Call
Initiate AI-generated voice calls through Alibaba Cloud Voice Messaging Service (dyvmsapi) by describing the call intent in natural language. The system automatically matches the addressee from the user's address book and generates the spoken content with an LLM.
Architecture: Alibaba Cloud VMS (dyvmsapi) + SubmitIntent API + LLM Content Generation + Contact Book Matching
โ ๏ธ Path-Selection Rules (MUST be followed in this exact order):
- Always try the intranet primary path first: enter ยง1 and run the full intranet plugin install flow (
cli.aliyun-inc.com). It is not allowed to skip ยง1 just because "this looks like an external network".
- Switch to ยง1.alt only when ยง1.3 reports
lookup cli.aliyun-inc.com: no such host or connection timeout. Any other error MUST be triaged via references/plugin-troubleshooting.md and MUST NOT be treated as a network failure.
- The external fallback only replaces
SubmitIntent: it routes through the script scripts/dyvmsapi_rpc.py to call the public gateway directly (SubmitIntent visibility is still private, with no SLA). QueryCallDetailByCallId is public, and the public-release dyvmsapi CLI plugin already includes that subcommand (aliyun plugin install --names dyvmsapi, no --source-base needed). In external mode, call-detail queries still go through the public CLI plugin; the script only handles SubmitIntent.
- โ ๏ธ The public-release plugin and the intranet-online plugin share the same name (
aliyun-cli-dyvmsapi) and are mutually exclusive โ only one can be installed at a time, and the second install overwrites the first. Priority: install the intranet-online version whenever possible (it ships both SubmitIntent and QueryCallDetailByCallId); only fall back to the public-release version when the intranet install fails (which loses SubmitIntent, then the script fills the gap). Never install the public-release version while the intranet-online version is available โ doing so loses the submit-intent subcommand.
- The full external-fallback execution manual lives in
references/external-network-fallback.md.
- Switch back to the primary path as soon as intranet connectivity is restored. Do not stay on the fallback long-term. Switch back via:
aliyun plugin uninstall --name dyvmsapi (note the singular --name), then re-run aliyun plugin install ... --source-base ... from ยง1.3 to reinstall the intranet-online version.
Compared with the legacy SingleCallByTts, this capability:
- โ Does not require enterprise-real-name verification
- โ Does not require provisioning service instances or binding real outbound numbers
- โ Does not require creating or reviewing voice templates
- โ
Only requires a configured address book and a stated intent in natural language
Capability Boundary: this Skill wraps two capabilities โ initiating a smart call (SubmitIntent) and querying the call detail (QueryCallDetailByCallId). Address-book CRUD operations and phone-number ownership verification are out of scope; the user must perform those in the Alibaba Cloud Voice Service console.
Operational Constraints
- Content compliance: The spoken content is fully generated by the LLM and is double-gated by server-side sensitive-word screening + LLM safety review. The user cannot specify the literal playback text directly.
- Compliant use only: Limited to lawful and legitimate notification scenarios. Strictly prohibited: debt collection, telecom fraud, harassment, or any other illegitimate use.
- Single-callee per invocation: Each call matches exactly one contact. Group calls are not supported. Notify multiple recipients via separate invocations.
- Phone-number safety: The phone number is never passed to the LLM. The server side performs number lookup and outbound dialing.
- Per-number rate limit: Same number โ 1 call/minute, 5 calls/hour, 20 calls/24-hour-window.
- Address-book size limit: At most 200 contacts per user.
1. Installation
[MUST] Execute steps 1.1 โ 1.2 โ 1.3 โ 1.4 in strict order. Do not skip any step. On any failure, consult references/plugin-troubleshooting.md.
1.1 [MUST] Verify Aliyun CLI is installed at version โฅ 3.3.8
# Note on --user-agent scope:
# Aliyun CLI system / tooling commands (`version`, `configure`, `plugin`,
# `upgrade`, `oss`, `auto-completion`, `mcp-proxy`, `go-migrate`, `otsutil`,
# and any subcommand invoked with `--help`) DO NOT accept `--user-agent` and
# MUST NOT carry it (passing it raises `unknown flag: --user-agent`).
# The ONLY exception is `aliyun configure ai-mode set-user-agent`, which is
# the dedicated command for declaring the AI-Mode global User-Agent (see ยง1.1.1).
# Only BUSINESS calls (e.g. `aliyun dyvmsapi submit-intent ...`,
# `aliyun dyvmsapi query-call-detail-by-call-id ...`) accept and MUST carry
# --user-agent "AlibabaCloud-Agent-Skills/alibabacloud-vms-smart-call-by-tts/1.0.0"
# so the call can be attributed to this Skill.
aliyun version
-
โ
Output 3.3.15 or any version โฅ 3.3.8 โ continue to 1.1.1
-
โ Command not found / version < 3.3.8 โ run the environment-aware installer shipped with this Skill. It picks the first strategy that matches the runtime (Homebrew โ user-level signed-binary tarball under $HOME/.local/bin), is idempotent, self-verifies, and never executes a remote script via shell pipe:
bash scripts/install_aliyun_cli.sh
Notes:
- Do not run
curl -fsSL https://aliyuncli.alicdn.com/setup.sh | bash to install the CLI: piping a remote script directly to a shell bypasses integrity verification and is treated as a security violation by static scanners; that script also writes to /usr/local/bin/aliyun and silently retries with sudo, which fails in non-interactive shells (agent sandboxes, CI runners) where no tty is available to type the password. The installer above downloads only the signed binary tarball, never executes a remote script, and routes around the sudo issue.
- On Apple Silicon Macs the installer pulls
aliyun-cli-macosx-latest-arm64.tgz; never install the amd64 build on arm64 hardware โ it requires Rosetta 2 and is brittle.
- Verify before continuing: the installer exits non-zero if the resulting
aliyun version is < 3.3.8. If it fails, switch to the manual matrix in references/cli-installation-guide.md (it covers macOS amd64/arm64, Linux amd64/arm64, and Windows, each with a sudo-less variant).
Why is the floor 3.3.8? ยง1.3 uses plugin install --source-base, a flag first introduced in aliyun CLI v3.3.7 (2026-04-16) (PR #1299). The floor is set conservatively to 3.3.8. Versions < 3.3.8 will fail ยง1.3 with ERROR: invalid flag source-base โ this is a tooling-version issue, not a network issue; upgrade the CLI.
1.1.1 [MUST] Enable AI-Mode (executed immediately after CLI is verified)
Enable AI-Mode as soon as ยง1.1 confirms the CLI is available, and before any other aliyun ... invocation in this Skill.
User-Agent is declared per-command on BUSINESS calls only. Every business aliyun ... invocation (e.g. aliyun dyvmsapi submit-intent, aliyun dyvmsapi query-call-detail-by-call-id) in SKILL.md and references/*.md MUST explicitly pass the per-Skill UA "AlibabaCloud-Agent-Skills/alibabacloud-vms-smart-call-by-tts/1.0.0" so the call can be attributed to this Skill. System / tooling commands (the categories listed in the scope-comment of ยง1.1) DO NOT accept this UA flag and MUST NOT carry it โ passing it raises unknown flag: --user-agent and aborts the command. The single exception is aliyun configure ai-mode set-user-agent, used below to declare the AI-Mode default UA.
# 1) Enable AI-Mode for this Skill session.
aliyun configure ai-mode enable
# 2) Declare the AI-Mode default UA so the gateway attributes every business
# call below to this Skill. `ai-mode set-user-agent` is the ONLY
# system/tooling command that legitimately accepts the UA flag.
aliyun configure ai-mode set-user-agent \
--user-agent "AlibabaCloud-Agent-Skills/alibabacloud-vms-smart-call-by-tts"
[MUST] Disable AI-Mode at EVERY exit point of this Skill (success, failure, or early STOP) by running aliyun configure ai-mode disable โ see ยง6 step 2 / step 4 and ยง9 best-practice #5.
1.2 [MUST] Check whether the submit-intent subcommand already exists
aliyun dyvmsapi submit-intent --help 2>&1
Decide based on the output:
| Output Pattern | Verdict | Next Step |
|---|
Contains API ็ๆฌ: 2017-05-25 and contains --user-message | Plugin is ready | Skip 1.3, jump to ยง2 |
unknown command "submit-intent" / command not found | Plugin not installed | Go to 1.3 |
aliyun: command not found | CLI not installed | Back to 1.1 |
| Other | Anomaly | Consult references/plugin-troubleshooting.md |
1.3 [MUST] Install the intranet-online dyvmsapi plugin
SubmitIntent is distributed only through the Alibaba intranet-online CLI plugin. The public-release aliyun-cli-dyvmsapi does not contain this subcommand.
Run the following command verbatim (no parameter may be omitted or modified):
aliyun plugin install --names dyvmsapi \
--version 0.1.0 \
--source-base https://cli.aliyun-inc.com/registry_id/2/env/online/plugins
[MUST] Hard requirements (a single mismatch will fail the install or pull the wrong build):
| Parameter | Correct | Common Mistake |
|---|
| CLI version | โฅ 3.3.8 | < 3.3.8 โ ERROR: invalid flag source-base โ go upgrade in ยง1.1, do NOT switch to the external fallback |
--names | plural s | --name (install fails with invalid flag; the singular form is for uninstall only) |
--version | 0.1.0 (required) | Omitting it fetches the latest public build |
--source-base | the URL above (required) | Omitting it pulls from the public mirror, which lacks submit-intent |
| URL path | env/online/plugins | env/pre/plugins is deprecated |
| URL host | cli.aliyun-inc.com | Resolvable from Alibaba intranet only |
Expected output:
Downloading aliyun-cli-dyvmsapi 0.1.0...
Plugin aliyun-cli-dyvmsapi 0.1.0 installed successfully!
If the output reads plugin "aliyun-cli-dyvmsapi" is already installed (version X.Y.Z); continuing will replace it with version 0.1.0 โ expected behavior (overwrite install). Let it finish.
If the output reads ERROR: invalid flag source-base โ CLI version is < 3.3.8 and does not understand the flag. Re-run the environment-aware fallback chain in ยง1.1 (it auto-picks brew / system-wide / user-level upgrade) to upgrade, then retry ยง1.3. [FORBIDDEN] It is strictly forbidden to switch to ยง1.alt due to this error โ this is a tooling-version issue, not a network issue. The external fallback is reserved for no such host / connection timeout only.
If the output reads lookup cli.aliyun-inc.com: no such host / connection timeout โ the runtime is not on the Alibaba intranet. Switch to ยง1.alt and continue (functionally equivalent; no plugin install needed).
Other errors โ consult references/plugin-troubleshooting.md.
1.4 [MUST] Re-validate after install
# `--help` is a help-mode invocation: it MUST NOT carry `--user-agent`
# (passing it raises `unknown flag: --user-agent` and aborts the command).
# See ยง1.1.1 for the full system-vs-business UA scope rule.
aliyun dyvmsapi submit-intent --help
Validation criteria (ALL must hold before proceeding):
- Output contains
API ็ๆฌ: 2017-05-25
- Output contains the parameter
--user-message
- Output contains the description
ๆไบคๆๆฌๆๅพโฆ or equivalent
If any criterion fails โ see references/plugin-troubleshooting.md.
1.alt External Fallback Path (enter only when the primary path is unavailable)
Trigger: ยง1.3 reports lookup cli.aliyun-inc.com: no such host, or it has been confirmed that the runtime is on a public network without access to the Alibaba intranet/VPN.
Do not enter this path while the primary plugin is functional.
Prerequisites (none may be missing):
Validate the script is in place:
python3 scripts/dyvmsapi_rpc.py --help
If the output contains dyvmsapi public RPC direct-call script (zero dependencies), proceed to ยง2 credentials validation. (On the external script path, credentials are auto-injected by the helper scripts/run_with_aliyun_creds.py from the current aliyun configure profile โ see ยง2.)
Important constraints:
- After switching to the external path, the
aliyun dyvmsapi submit-intent invocation in ยง6 step 2 MUST be replaced by the script invocation; step 4 (aliyun dyvmsapi query-call-detail-by-call-id) still uses the CLI with the public-release plugin installed above. Details: ยง6.alt and references/external-network-fallback.md.
- AI-Mode: enabled once in ยง1.1.1 and MUST be disabled at every exit point of this Skill, regardless of whether step 2 runs via the script or step 4 runs the CLI. The per-command UA rule from ยง1.1.1 still applies: business
aliyun ... calls (e.g. aliyun dyvmsapi query-call-detail-by-call-id) MUST carry the per-Skill UA; system / tooling commands MUST NOT โ see ยง1.1.1.
- Do not interleave the two paths.
2. Credentials Validation
Pre-check: Alibaba Cloud Credentials Required
Security Rules:
- NEVER read, echo, or print AK/SK values (e.g.,
echo $ALIBABA_CLOUD_ACCESS_KEY_ID is FORBIDDEN)
- NEVER ask the user to input AK/SK directly in the conversation or command line
- NEVER use
aliyun configure set with literal credential values
- ONLY use
aliyun configure list to check credential status
aliyun configure list
Check the output for a valid profile (AK, STS, or OAuth identity).
Note: Valid only means the local profile fields are well-formed; it does not prove the AK is still active server-side. If a downstream call returns InvalidAccessKeyId.NotFound / SignatureDoesNotMatch, the credentials are syntactically OK but have been disabled or rotated โ cross-check status in the AK Management Console.
If no valid profile exists, STOP here.
- Obtain credentials from the Alibaba Cloud Console
- Configure credentials outside of this session by running
aliyun configure in the user's own terminal (or by exporting environment variables in the shell profile). The interactive flow asks for several values including AK ID, AK Secret, and Default Region Id. Only the Region prompt typically blocks users (the CLI does not show candidates), so the agent MUST proactively tell the user: recommend cn-hangzhou โ dyvmsapi is a centralized service that is not region-sensitive, so any valid region works; if the user's other Alibaba Cloud resources already live in another region (e.g. cn-shanghai, cn-beijing, cn-shenzhen, cn-hongkong, ap-southeast-1), they may pick that one instead. Full candidate list: references/cli-installation-guide.md.
- Return and re-run after shows a valid profile
2.1 Primary Path (CLI) โ Credentials
On the primary path, aliyun dyvmsapi submit-intent / query-call-detail-by-call-id automatically read credentials from the current profile. The agent does not need to take any extra action.
2.2 ยง1.alt External Fallback (Script) โ Default Auto-Injected Credentials
Design: The external-fallback script path no longer asks the user to manually export AK/SK. Instead, it reuses the user's already-configured aliyun configure current profile, and the helper scripts/run_with_aliyun_creds.py auto-injects credentials into the subprocess environment. Three reasons motivate this design: โ a user experience consistent with the primary path; โก cross-process shell export cannot pass credentials into the agent's subprocess (technically infeasible); โข since the user has already provided credentials for this profile, asking again would constitute redundant input.
[MUST] Standard invocation pattern: agents always go through the helper. Do not extract credentials from ~/.aliyun/config.json by hand.
# 1) Pre-check: confirm the current profile meets auto-injection requirements
python3 scripts/run_with_aliyun_creds.py --check
# Expected: `OK profile=default mode=AK ready for auto-injection` โ ready
# 2) Tell the user which profile will be used (transparency; no credential values)
python3 scripts/run_with_aliyun_creds.py --print-profile
# Output e.g.: `profile=default mode=AK region=cn-hangzhou`
# The agent MUST tell the user explicitly: "I will call SubmitIntent with profile=<name> mode=<mode>" โ give the user a chance to refuse.
# 3) Make the actual call (helper injects env; the script reads from env; no values are persisted)
python3 scripts/run_with_aliyun_creds.py -- \
python3 scripts/dyvmsapi_rpc.py SubmitIntent -P UserMessage="<the user's intent>"
Supported modes: AK / StsToken. StsToken additionally injects ALIBABA_CLOUD_SECURITY_TOKEN, which the script then includes as a public parameter in the signature.
Unsupported modes (RamRoleArn / EcsRamRole / OAuth / External / CredentialsURI โฆ): the helper exits 3 and prompts the user to manually obtain temporary AK/SK/STS. In that case, fall back to the primary path (the CLI natively supports all modes) or have the user create a new AK profile.
[FORBIDDEN] Prohibited behaviors:
- Bypassing the helper and reading
~/.aliyun/config.json / json.load(...) directly inside agent code is strictly prohibited โ three common failure modes follow: hardcoding profiles[0] instead of (wrong profile), missing 's , and accidentally leaking credentials through debug output or script logs.
3. RAM Permissions
RAM sub-accounts must be granted dyvms:SubmitIntent and dyvms:QueryCallDetailByCallId. Root accounts need no extra setup. See references/ram-policies.md for the full policy.
[MUST] Permission Failure Handling: When any command or API call fails due to permission errors at any point during execution, follow this process:
- Read
references/ram-policies.md to get the full list of permissions required by this SKILL
- Use the
ram-permission-diagnose skill to guide the user through requesting the necessary permissions
- Pause and wait until the user confirms that the required permissions have been granted
4. Prerequisite: Configure the Address Book
Address-book management is OUT OF SCOPE for this Skill. Before initiating a smart call, the user must complete the following in the Alibaba Cloud Voice Service console:
- Verify phone-number ownership: complete ownership verification for every phone number to be added (verification is valid for ~6 months by default)
- Add contacts: assign each verified number a recognizable Tag, e.g. "Mom", "Manager Zhang", "Lao Wu"
- (Optional) Update or remove existing contacts
Address-book constraints:
Tag and PhoneNumber are strictly one-to-one
- Tag is the only signal the LLM uses for contact matching โ use clear, distinctive names
5. Parameter Confirmation
IMPORTANT: Parameter Confirmation โ Before executing the API call,
confirm the user's intent (who to call + what to convey). If the user's message already makes both clear, no confirmation is needed โ proceed directly.
Do NOT iterate on wording or draft the spoken text โ UserMessage is an intent description,
not the final playback script; the server-side LLM generates the actual spoken content (Model.CallContent).
| Parameter | Required | Description | Default |
|---|
UserMessage | Yes | Natural-language description of the call intent (NOT the literal spoken text) | None (user must provide) |
UserMessage examples:
- "Remind Mom I won't be home for dinner tonight"
- "Call Manager Zhang and let him know the meeting is at 10 AM tomorrow"
- "Tell Lao Wu to bring the contract this afternoon"
These are intent descriptions. If who + what are already clear from the user's original message, proceed directly โ do not echo back or ask for approval. Do not ask "shall I phrase it as X?" or iterate on wording โ the server generates the spoken content.
6. Core Workflow
AI-Mode and User-Agent: AI-Mode was enabled in ยง1.1.1 (executed immediately after the CLI was verified). Do not re-enable here unless it was previously disabled (see note below Step 3). Every business aliyun ... invocation below (e.g. aliyun dyvmsapi submit-intent, aliyun dyvmsapi query-call-detail-by-call-id) MUST explicitly pass the per-Skill UA "AlibabaCloud-Agent-Skills/alibabacloud-vms-smart-call-by-tts/1.0.0". System / tooling commands DO NOT accept this flag and MUST NOT carry it โ see ยง1.1.1.
[MUST] Disable AI-Mode at EVERY exit point of this Skill โ success, failure, early STOP, all exits. The disable command is:
aliyun configure ai-mode disable
Step 1: Extract User Intent
Extract who to call and what to convey from the user's message. A natural-language reference is sufficient (e.g. "ๆ็ธ", "Mom", "ๅผ ็ป็") โ it does not need to be the exact Tag literal stored in the address book; the server-side LLM performs semantic matching against the user's contact list.
- Intent already clear (who + what both unambiguous) โ skip confirmation, proceed to Step 2 immediately. Example: "Call my dad and tell him to go grocery shopping" โ who=dad, what=go grocery shopping, fire directly.
- Intent partially unclear (missing who, or what is too vague to act on) โ ask once to clarify the missing part, then fire. Example: "Make a call" โ who=? what=? ask once.
[MUST] Zero or one round, then fire โ UserMessage is NOT the verbatim script that will be spoken; it is an intent description fed to the server-side LLM, which generates the actual spoken content. Once who + what are clear (whether from the original message or a single clarification), proceed to Step 2 immediately. Prohibited behaviors:
- Drafting a "notification script" and asking the user to review wording
- Asking "shall I say it like this?" or offering multiple phrasings
- Asking the user for the exact Tag literal in the address book (e.g. "ไฝ ็ธๅจ้่ฎฏๅฝ้็ Tag ๅซไปไน?") โ the server does semantic matching; a natural-language reference is enough
- Confirming the contact's identity when it is already obvious ("็ธ"/"่็ธ"/"็ธ็ธ" are all the same role โ do not ask "which one?")
- Looping back for a second confirmation unless the user actively says the intent is wrong
[MUST] Never abort on unverifiable Tag โ The Agent has no local API to list or verify address-book entries (see ยง4: CRUD is out of scope). If the Agent cannot confirm whether the user-provided Tag exists, it MUST still proceed to Step 2 and let the server validate. Halting the flow, asking the user to "go check the console first", or refusing to call because the Tag "might not exist" is strictly prohibited โ the correct behavior is to fire the API and faithfully relay whatever the server returns (success or error).
Step 2: Initiate the Smart Call
aliyun dyvmsapi submit-intent \
--user-message "<user-confirmed natural-language intent>" \
--user-agent "AlibabaCloud-Agent-Skills/alibabacloud-vms-smart-call-by-tts/1.0.0"
ยง6.alt External Fallback โ If the runtime entered ยง1.alt (script path), replace this step with the helper-driven invocation (credentials MUST be auto-injected via the helper, see ยง2.2):
python3 scripts/run_with_aliyun_creds.py -- \
python3 scripts/dyvmsapi_rpc.py SubmitIntent \
-P UserMessage="<user-confirmed natural-language intent>"
- The Key MUST be PascalCase (
UserMessage, not user-message). Response shape is identical to the CLI; step 3's parsing logic is shared.
- Direct invocation of
python3 scripts/dyvmsapi_rpc.py ... without going through the helper is strictly prohibited โ the script does not read ~/.aliyun/config.json itself; missing env will produce [ERROR] AK/SK not provided.
- Before the call, run the ยง2.2 [MUST] 3-step routine (
--check โ --print-profile to inform the user โ actual call).
- Details in
references/external-network-fallback.md.
Step 3: Parse the Response
Code == "OK" and Success == true: the call has been initiated
- Show
Model.Tag (matched contact), Model.CallContent (spoken text), Model.CallId to the user
- For phone-number safety, the response does not contain the dialed number
- For error handling, see the error-code table in
references/related-commands.md
Code != "OK" is a valid execution result โ e.g. contact-not-found, quota exceeded, parameter invalid. Parse the error, report it to the user faithfully, and treat the Skill run as complete (with an error outcome). Do not retry automatically or loop back to Step 1 unless the user explicitly asks.
AI-Mode lifecycle after Step 3:
- If
Code != "OK" or the user does not need Step 4 โ this is the exit point โ disable AI-Mode now.
- If
Code == "OK" and Step 4 may follow (user wants to check call result) โ do NOT disable yet. Keep AI-Mode enabled until Step 4 completes.
- If the Skill session was interrupted (e.g. Agent already disabled AI-Mode after Step 3, then the user later requests Step 4) โ re-enable AI-Mode before Step 4, then disable again at the end. This is the only legitimate re-enable scenario.
[FORBIDDEN] Strictly forbidden to fabricate responses or stage Mock deliveries โ When step 2 encounters an infrastructure failure (credential missing / expired, network unreachable, non-zero script exit code with no JSON body, InvalidAccessKeyId, SignatureDoesNotMatch):
- Before STOP, ALWAYS run
aliyun configure ai-mode disable first (AI-Mode was enabled in ยง1.1.1; disable is mandatory at every exit point including failure paths).
- STOP IMMEDIATELY, report the error to the user faithfully and verbatim, and ask them to fix the issue and retry.
- Fabricating a
Code: OK / fake CallId / fake Model.Tag / fake Model.CallContent is strictly prohibited.
- Writing falsified
call_result.json / task_summary.md / executed_actions.sh to mimic a successful delivery is strictly prohibited.
- Wording such as "simulated" / "mock" / "assume the user has" / "since this is a simulated environment" used to bypass real invocation is strictly prohibited.
- Any of the above is treated as a fraudulent delivery.
Step 4 (Optional): Query the Call Result
The Model.CallId returned by SubmitIntent only signifies that the call has been accepted, not that the callee has answered. If the user wants to confirm whether the call connected, invoke query-call-detail-by-call-id.
# Take the CallId returned by SubmitIntent (format: <ms-timestamp>^<call-sequence>, e.g. "1779785134472^9876543210").
CALL_ID="<Model.CallId from step 2 response>"
# The first segment of CallId is already a Unix-millisecond timestamp; reuse it as query-date.
# `--query-date` is an int (Unix-millisecond timestamp), NOT a yyyyMMdd string โ do NOT call any datetime conversion.
QUERY_DATE="${CALL_ID%%^*}"
aliyun dyvmsapi query-call-detail-by-call-id \
--call-id "$CALL_ID" \
--prod-id 11000000300006 \
--query-date "$QUERY_DATE" \
--user-agent "AlibabaCloud-Agent-Skills/alibabacloud-vms-smart-call-by-tts/1.0.0"
Hard requirements:
--prod-id MUST be 11000000300006 (the Voice Notification product ID). SubmitIntent is dispatched under this product; any other prod-id will return Code: OK with no Data.
--query-date MUST be on the same day as the CallId (millisecond timestamp).
- CDR write delay: For notification-style calls (typical duration 10โ30 seconds), the CDR is generally available about 40 seconds after the call ends. If
Code: OK returns with no Data, retry once after another 30โ60 seconds. Do not hard-wait 1โ2 minutes blindly.
ยง6.alt External โ step 4 still uses the CLI. QueryCallDetailByCallId visibility is public; the public-release aliyun-cli-dyvmsapi plugin already includes it:
aliyun plugin update
aliyun plugin install --names dyvmsapi # public-release; no --source-base
The public-release plugin should already be installed from ยง1.alt. If for any reason it is not yet present, run the two commands above first. After install, the aliyun dyvmsapi query-call-detail-by-call-id ... command above works as-is. On the external path, the script only replaces SubmitIntent; CDR queries still go through the CLI. Details in references/external-network-fallback.md.
Response parsing:
Data is a JSON string (requires a second parse) and contains:
| Field | Meaning |
|---|
stateDesc | Localized state description, e.g. ็จๆทๆฅๅฌ (user answered) / ๆชๆฅๅฌ (no answer) / ๅผๅซไธญ (in progress) |
state | State code (200000 = answered) |
duration | Call duration in seconds |
bRingTime / bStartTime / bEndTime | Ring / answer / hangup timestamps |
callee | Dialed number (this CDR API returns the full number โ only the account owner can view their own CDR; this does not contradict the SubmitIntent rule that phone numbers are not passed to the LLM) |
gmtCreate | Time the call request was accepted by the platform |
calleeShowNumber | Caller-display number |
[MUST] Readable Presentation โ Strictly forbidden to dump the raw Data JSON string to the user. After parsing, render the result as three real Markdown tables (NOT a fenced code block, NOT ASCII separator lines like โโโโโ โ those get absorbed as <hr> by Markdown renderers and reflow the rest into a single line):
Call Result
| |
|---|
| โ
Status | <stateDesc> (state=<state>) |
| ๐ค Callee | <callee_masked> |
| ๐ฒ Display No. | <calleeShowNumber> |
| โฐ Duration | <duration> seconds |
Timeline
| |
|---|
| ๐ Accepted | <gmtCreate> |
| ๐ Ringing | <bRingTime> (+<offset_after_accepted>s) |
| ๐ Answered | <bStartTime> (+<offset_after_ringing>s after ring) |
| ๐ Hung up | <bEndTime> (talk <duration>s) |
| ๐ Hangup by | <callee-initiated|caller-initiated> (hangupDirection=<0|1>) |
Reference
Rules:
- Render real Markdown tables. Do NOT wrap the layout in a fenced code block, and do NOT use ASCII separators (
โโโโโ, ===, --- inside cells, etc.) โ they get absorbed as <hr> by Markdown renderers and reflow the rest of the text into a single line.
- Show the localized
stateDesc next to the numeric state. Don't show the raw number alone.
For the full parameter reference and response examples, see references/related-commands.md.
[MUST] Disable AI-Mode at EVERY exit point โ before delivering the final response for ANY reason, run aliyun configure ai-mode disable first.
7. Success Validation
See references/verification-method.md.
Quick check: Code == "OK" and a non-empty Model.CallId in the response = the call has been initiated successfully.
8. Command Reference
See references/related-commands.md.
9. Best Practices
UserMessage must reference a contact explicitly: use a recognizable tag the user believes is in their address book (e.g. "Mom", "Manager Zhang"); avoid pronouns ("him", "that person").
- Respect the rate limits: per-number 1/min, 5/hour, 20/24h; for batch notifications, space invocations at least 60 seconds apart.
- Configure the address book before invocation: ensure the contact is added in the console with valid phone-ownership verification.
- Compliant use only: for lawful notification scenarios; debt collection, fraud, harassment, and the like are forbidden.
- AI-Mode MUST be disabled at the end of every Skill execution (success or failure): run
aliyun configure ai-mode disable.
10. Reference Links
| File | Content |
|---|
references/cli-installation-guide.md | Aliyun CLI installation guide |
references/plugin-troubleshooting.md | dyvmsapi plugin install troubleshooting (MUST consult on any ยง1 failure) |
references/ram-policies.md | RAM policy (minimum-Action) |
references/related-commands.md | CLI command reference, parameters, error codes |
references/verification-method.md | Verification methods |
references/acceptance-criteria.md | Acceptance criteria |
references/external-network-fallback.md | External fallback execution manual (enter only when the primary path is unavailable) |
scripts/dyvmsapi_rpc.py | Zero-dependency Python script that calls the public dyvmsapi gateway directly |
scripts/run_with_aliyun_creds.py | Credential-injection helper: auto-injects env from the aliyun configure current profile, then exec's the subcommand (mandatory entrypoint for the external fallback path) |
scripts/install_aliyun_cli.sh | Environment-aware installer / upgrader for the Aliyun CLI (Homebrew โ user-level signed-binary tarball; idempotent and self-verifying). Invoked from ยง1.1 when the CLI is missing or below 3.3.8. |
related_apis.yaml | Dependent API inventory |