Critical CLI Compliance (Must Read First)
The following declarations apply to every aliyun CLI invocation in this Skill —
they must be honored before any send / query operation, workflow step, or functional
scenario described later in this document.
Pre-check: Aliyun CLI >= 3.3.3 required
Run
aliyun versionto verify the version is >= 3.3.3. If not installed or the version is too low, runcurl -fsSL https://aliyuncli.alicdn.com/setup.sh | bashto install or update.
Pre-check: Aliyun CLI plugin update required
[MUST] run
aliyun configure set --auto-plugin-install trueto enable automatic plugin installation. [MUST] runaliyun plugin updateto ensure that any existing plugins on your local machine are always up-to-date.
[MUST] Enable AI-Mode — AI-mode is required for Agent Skill execution. Run the following commands before any CLI invocation:
aliyun configure ai-mode enable
aliyun configure ai-mode set-user-agent --user-agent "AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message"
[MUST] Disable AI-Mode at EVERY exit point — Before delivering the final response for ANY reason, always disable AI-mode first. This applies to ALL exit paths: workflow success, workflow failure, error/exception, user cancellation, session end, or any other scenario where no further CLI commands will be executed. AI-mode is only used for Agent Skill invocation scenarios and MUST NOT remain enabled after the skill stops running.
aliyun configure ai-mode disable
[MUST] CLI User-Agent — Every aliyun CLI command invocation in this Skill must
include the flag:
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message
Overview
This Skill wraps the Alibaba Cloud Short Message Service (SMS) end-to-end on top of the aliyun CLI, exposing the following capabilities:
- Send SMS: verification codes, notifications, or marketing messages (SendSms).
- Batch send: different signatures / template params per phone number (SendBatchSms).
- Signature management: query approval status and signature lists.
- Template management: query approval status and template lists.
- Send status query: query SMS send details and delivery receipts.
- Send statistics query: aggregated send / success / fail counts in a date range (QuerySendStatistics).
- SMS qualification query: list records (QuerySmsQualificationRecord) and
single-record detail (QuerySingleSmsQualification) — see
references/sms-qualification.md.
Interactive Parameter Confirmation (Must Read)
Before executing any send-class operation (send-sms / send-batch-sms), this Skill
must collect these critical parameters first:
--sign-name(signature name)--template-code(template code)--template-param(template variables, when the template contains placeholders)--phone-numbers/--phone-number-json(phone numbers)
Handling Rules
When the user does not explicitly provide the signature or template, the AI agent must not guess or fabricate them. Instead it should:
- Ask the user proactively: "Which signature/template should I use? If unsure, I can list approved ones from your account for you to pick from."
- After the user agrees, call list APIs:
aliyun dysmsapi query-sms-sign-list ...thenaliyun dysmsapi get-sms-sign --sign-name <name>per candidate.aliyun dysmsapi query-sms-template-list ...- Hard filter: keep only signs with
SignStatus = 1(approved) and templates withTemplateStatus = 1. Do NOT drop signs based on carrier registration alone — unregistered carriers may still deliver. Instead, surfaceSignIspRegisterDetailList[*].RegisterResult(per-carrier registration status) as an extra column in the candidate table and let the user decide. Columns: index / code / name / content /SignStatus/ per-carrier registration.
- Resolve template variables: If the picked template contains
${xxx}placeholders, ask for each variable's value one by one and assemble them into--template-paramJSON. - Phone numbers: Always require explicit phone numbers from the user; never reuse
placeholder numbers like
13800138000from this document as the actual recipient. - Final confirmation: Once all critical parameters are collected, restate the
complete send plan and only call
send-sms/send-batch-smsafter the user gives an explicit confirmation (e.g. "confirm" / "send").
Quick Recovery When Signature / Template Is Invalid
If send-sms returns isv.SMS_SIGN_NAME_ILLEGAL / isv.SMS_TEMPLATE_ILLEGAL, the agent
should proactively offer to "list existing signatures and templates" and, after the user
agrees, call the list APIs instead of retrying blindly.
Prerequisites
1. Install aliyun CLI (>= 3.3.3)
# macOS
brew install aliyun-cli
# Linux
wget https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz
tar -xzf aliyun-cli-linux-latest-amd64.tgz && sudo mv aliyun /usr/local/bin/
aliyun version # must be >= 3.3.3
2. Install the dysmsapi plugin
aliyun plugin install --names dysmsapi
3. Configure Credentials
The aliyun CLI default credential chain is recommended; it picks credentials in this
priority order: env vars → ~/.aliyun/config.json → ECS RAM role → OIDC Token.
# Recommended for CI/CD: env vars
export ALIBABA_CLOUD_ACCESS_KEY_ID=<your-access-key-id>
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<your-access-key-secret>
export ALIBABA_CLOUD_REGION_ID=cn-hangzhou
# Verify
aliyun configure get
Important: Never hard-code AK/SK in code or commands. Always rely on the default credential chain. On ECS use a RAM role; in K8s use OIDC.
4. Activate the SMS Service
In the Alibaba Cloud SMS Console: activate the service, create an approved signature, and create an approved template.
Usage
Calling aliyun CLI directly
Send SMS:
aliyun dysmsapi send-sms \
--api-version 2017-05-25 \
--phone-numbers "13800138000" \
--sign-name "AliyunDemo" \
--template-code "SMS_123456" \
--template-param '{"code":"123456"}' \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message \
--read-timeout 3
Batch send (different signatures / template params):
aliyun dysmsapi send-batch-sms \
--api-version 2017-05-25 \
--phone-number-json '["13800138000","13900139000"]' \
--sign-name-json '["SignA","SignB"]' \
--template-code "SMS_123456" \
--template-param-json '[{"code":"111111"},{"code":"222222"}]' \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message \
--read-timeout 3
Query lists / status / details:
# Approved signatures / templates (use to populate user choices)
aliyun dysmsapi query-sms-sign-list --api-version 2017-05-25 --page-index 1 --page-size 50 --user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
aliyun dysmsapi query-sms-template-list --api-version 2017-05-25 --page-index 1 --page-size 50 --user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
# Single signature / template lookup
aliyun dysmsapi get-sms-sign --api-version 2017-05-25 --sign-name "AliyunDemo" --user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
aliyun dysmsapi get-sms-template --api-version 2017-05-25 --template-code "SMS_123456" --user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
# Per-message delivery details (use BizId for precise lookup)
aliyun dysmsapi query-send-details \
--api-version 2017-05-25 \
--phone-number "13800138000" --send-date "20260326" \
--page-size 10 --current-page 1 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
# Aggregated statistics (--is-globe: 1=domestic, 2=intl/HK-Macao-Taiwan)
aliyun dysmsapi query-send-statistics \
--api-version 2017-05-25 --is-globe 1 \
--start-date "20260301" --end-date "20260326" \
--page-index 1 --page-size 10 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
# Filter by signature name + template type (optional)
aliyun dysmsapi query-send-statistics \
--api-version 2017-05-25 --is-globe 1 \
--start-date "20260301" --end-date "20260326" \
--page-index 1 --page-size 10 \
--sign-name "AliyunDemo" --template-type 0 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
# SMS qualification — list records (full detail in references/sms-qualification.md)
aliyun dysmsapi query-sms-qualification-record \
--api-version 2017-05-25 --page-no 1 --page-size 20 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
# SMS qualification — single detail by GroupId
aliyun dysmsapi query-single-sms-qualification \
--api-version 2017-05-25 --qualification-group-id 10000123 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
Full filter parameters, response schemas, and state enum mapping for the qualification APIs are documented in
references/sms-qualification.md.
Using the wrapper script
scripts/send_sms.sh automatically applies --api-version, the compliant --user-agent,
and --read-timeout:
# Send (single or comma-separated phones)
./scripts/send_sms.sh send -p "13800138000" -s "AliyunDemo" -t "SMS_123456" -tp '{"code":"123456"}'
# Send with signature/template pre-verification (recommended)
./scripts/send_sms.sh send -p "13800138000" -s "AliyunDemo" -t "SMS_123456" -tp '{"code":"123456"}' --verify
# List & inspect
./scripts/send_sms.sh list-signs
./scripts/send_sms.sh list-templates
./scripts/send_sms.sh query-sign --sign-name "AliyunDemo"
./scripts/send_sms.sh query-template --template-code "SMS_123456"
# Status & statistics
./scripts/send_sms.sh query-status -p "13800138000" --send-date "20260326" --biz-id "xxx^0"
./scripts/send_sms.sh query-statistics --start-date "20260301" --end-date "20260326"
./scripts/send_sms.sh query-statistics --start-date "20260301" --end-date "20260326" --is-globe 2
# Filter by signature name and/or template type
./scripts/send_sms.sh query-statistics --start-date "20260301" --end-date "20260326" --sign-name "AliyunDemo" --template-type 0
Parameters
aliyun dysmsapi send-sms
| Parameter | Required | Description |
| ----------------- | -------- | -------------------------------------------------------- |
| --api-version | Yes | API version, fixed to 2017-05-25 |
| --phone-numbers | Yes | Phone numbers, comma-separated, up to 1000 |
| --sign-name | Yes | SMS signature name |
| --template-code | Yes | SMS template code |
| --template-param | No | Template variables JSON, e.g. '{"code":"123456"}' |
| --out-id | No | External tracking ID |
| --user-agent | Yes | Fixed to AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message |
| --read-timeout | Yes | Read timeout in seconds, recommended value 3 |
aliyun dysmsapi send-batch-sms (batch send)
| Parameter | Required | Description |
| -------------------------- | -------- | ---------------------------------------------------------------------------- |
| --api-version | Yes | API version, fixed to 2017-05-25 |
| --phone-number-json | Yes | Phone numbers JSON array, up to 100, e.g. '["138xxx","139xxx"]' |
| --sign-name-json | Yes | Signature names JSON array, must match the phone count |
| --template-code | Yes | Template code (all phones share the same template) |
| --template-param-json | No | Template variables JSON array, must match the phone count |
| --sms-up-extend-code-json | No | Upstream SMS extension codes JSON array |
| --out-id | No | External tracking ID, less than 256 characters |
| --user-agent | Yes | Fixed to AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message |
| --read-timeout | Yes | Read timeout in seconds, recommended value 3 |
SendSms vs SendBatchSms:
send-smsshares one signature/template across up to 1000 numbers;send-batch-smslets each phone use a different signature/template params (up to 100 numbers).
aliyun dysmsapi query-send-statistics
| Parameter | Required | Description |
| ----------------- | -------- | ------------------------------------------------------------------------------------ |
| --api-version | Yes | API version, fixed to 2017-05-25 |
| --is-globe | Yes | Scope: 1 = domestic; 2 = international / HK-Macao-Taiwan |
| --start-date | Yes | Start date in yyyyMMdd |
| --end-date | Yes | End date in yyyyMMdd |
| --page-index | Yes | Current page, starts from 1 |
| --page-size | Yes | Page size, 1~50 |
| --template-type | No | 0=verify code, 1=notification, 2=marketing(corp), 3=intl/HK-Macao-Taiwan(corp), 7=digital |
| --sign-name | No | Filter by signature name |
| --user-agent | Yes | Fixed to AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message |
| --read-timeout | Yes | Read timeout in seconds, recommended value 3 |
Response: returns
Data.TargetList[](each entry hasSendDate,TotalCount,RespondedSuccessCount,RespondedFailCount,NoRespondedCount) andData.TotalSize.
Wrapper script options
| Option | Short | Description |
| ----------------- | ----- | ------------------------------------------ |
| --phone-numbers | -p | Phone numbers |
| --sign-name | -s | Signature name |
| --template-code | -t | Template code |
| --template-param | -tp | Template variables (JSON) |
| --out-id | -o | External tracking ID |
| --verify | — | Verify signature/template before sending |
| --region | -r | Region ID, defaults to cn-hangzhou |
| --profile | — | Use the given aliyun CLI profile |
Output
Successful send response
{
"BizId": "114814474505895421^0",
"Code": "OK",
"Message": "OK",
"RequestId": "4C3D8B1B-B3D8-5673-B724-1F251799CE9A"
}
Approval status reference
| Value | SignStatus / TemplateStatus | Description | | ----- | --------------------------- | ------------------------------------ | | 0 | Reviewing | SMS cannot be sent for now | | 1 | Approved | Available for sending | | 2 | Rejected | Needs revision and resubmission | | 10 | Cancelled | Sign/template has been cancelled |
Error Handling
Common business error codes
| Error code | Description | Suggested action | | -------------------------------- | ------------------------------------ | --------------------------------------------- | | isv.SMS_SIGNATURE_SCENE_ILLEGAL | Signature/template scene mismatch | Make sure signature and template scenes align | | isv.SMS_TEMPLATE_ILLEGAL | Template missing or unapproved | Verify the template has been approved | | isv.SMS_SIGN_NAME_ILLEGAL | Signature missing or unapproved | Verify the signature has been approved | | isv.MOBILE_NUMBER_ILLEGAL | Bad phone number format | Check the number format | | isv.AMOUNT_NOT_ENOUGH | Insufficient account balance | Top up the SMS quota | | isv.BUSINESS_LIMIT_CONTROL | Throttling triggered | Reduce the send rate | | SignatureNotFound | Signature not found | Create the signature in the console | | TemplateNotFound | Template not found | Create the template in the console |
query-send-detailsErrCode= Alibabaisv.*/isp.*(above) + carrier receipts (DELIVERED,MOBILE_NOT_ON_SERVICE,MOBILE_SEND_LIMIT, …). Full table + triage:references/sms-error-codes.md.
CLI configuration errors
| Error message | Cause | Resolution | | ---------------------------- | -------------------- | ---------------------------------------------- | | InvalidAccessKeyId.NotFound | Wrong AccessKey ID | Check the AccessKey ID | | SignatureDoesNotMatch | Wrong Secret | Check the AccessKey Secret | | Forbidden.RAM | Insufficient permission | Verify the RAM user has SMS permissions |
Execution Flow
- Pre-check: aliyun CLI installed (>= 3.3.3) and dysmsapi plugin available; AI-Mode enabled; credentials configured.
- Validate required parameters (
phone-numbers,sign-name,template-code). If signature or template is missing, ask the user; after consent callquery-sms-sign-list/query-sms-template-listand present approved candidates. - [Optional, --verify] Verify sign via
get-sms-sign: requireSignStatus=1; also surfaceSignIspRegisterDetailList[*].RegisterResultto the user as info (unregistered carriers may still deliver — do not block). - [Optional, --verify] Verify template status via
get-sms-template(TemplateStatus=1). - Send via
aliyun dysmsapi send-sms(orsend-batch-smsfor per-recipient personalization). - Return result:
Code=OKonly confirms gateway acceptance — returnBizId. To report final delivery to the user, always callquery-send-details(Scenario 4); never use the send response as proof of delivery. - [MUST] Disable AI-Mode at every exit (success / failure / cancellation).
Examples
Scenario 1: Send a verification code
# 1) Pull approved signatures & templates first (so the user can pick)
aliyun dysmsapi query-sms-sign-list --api-version 2017-05-25 --page-index 1 --page-size 50 --user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
aliyun dysmsapi query-sms-template-list --api-version 2017-05-25 --page-index 1 --page-size 50 --user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
# 2) Send (after user confirmation)
aliyun dysmsapi send-sms \
--api-version 2017-05-25 \
--phone-numbers "13800138000" \
--sign-name "YourSign" --template-code "SMS_xxx" \
--template-param '{"code":"123456"}' \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
Scenario 2: Bulk-send with same signature & params
aliyun dysmsapi send-sms \
--api-version 2017-05-25 \
--phone-numbers "13800138000,13900139000,13700137000" \
--sign-name "YourSign" --template-code "SMS_xxx" \
--template-param '{"activity":"Double 11 Sale","discount":"50% OFF"}' \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
Scenario 3: Batch send with per-recipient personalization
aliyun dysmsapi send-batch-sms \
--api-version 2017-05-25 \
--phone-number-json '["13800138000","13900139000","13700137000"]' \
--sign-name-json '["BrandA","BrandB","BrandC"]' \
--template-code "SMS_xxx" \
--template-param-json '[{"name":"Alice","code":"111111"},{"name":"Bob","code":"222222"},{"name":"Charlie","code":"333333"}]' \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
Lengths of
--phone-number-json,--sign-name-json, and--template-param-jsonmust match and correspond one-to-one.
Scenario 4: Verify delivery & aggregate statistics
# Per-message delivery (uses BizId returned by send-sms)
aliyun dysmsapi query-send-details \
--api-version 2017-05-25 \
--phone-number "13800138000" --send-date "20260326" --biz-id "xxx^0" \
--page-size 10 --current-page 1 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
# Range-based aggregated statistics (1 row per send-day)
aliyun dysmsapi query-send-statistics \
--api-version 2017-05-25 --is-globe 1 \
--start-date "20260301" --end-date "20260326" \
--page-index 1 --page-size 10 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
QuerySendDetails vs QuerySendStatistics:
query-send-detailsreturns per-message records (delivery time, error code) — useful for troubleshooting.query-send-statisticsreturns aggregated daily counts — useful for trend reporting.
Multi-Environment / Multi-Account
aliyun CLI supports multiple profiles. Prefer env vars or RAM roles:
# Option 1: env vars (recommended)
export ALIBABA_CLOUD_ACCESS_KEY_ID=<your-access-key-id>
export ALIBABA_CLOUD_ACCESS_KEY_SECRET=<your-access-key-secret>
# Option 2: profiles (region only; credentials still come from env vars or RAM role)
aliyun configure set --profile prod --region cn-hangzhou
aliyun configure set --profile test --region cn-shanghai
aliyun dysmsapi send-sms --profile prod \
--api-version 2017-05-25 \
--phone-numbers "13800138000" --sign-name "Sign" --template-code "SMS_xxx" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-message --read-timeout 3
Notes
- Plugin install: First-time use requires
aliyun plugin install --names dysmsapi. - API version: When calling the CLI directly,
--api-version 2017-05-25is mandatory. - Parameter format: kebab-case (e.g.
--phone-numbers, not--PhoneNumbers). - Timeout:
--read-timeout 3is required. After a timeout, query the delivery receipt before deciding whether to retry. - User-Agent:
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-sms-send-short-messageis required so the server can identify the caller. - Idempotency: SendSms/SendBatchSms are NOT idempotent — prevent duplicate sends at the business layer.
- Single vs batch: Prefer
send-smsfor verification codes;send-batch-smsis only needed when each recipient requires different signature or template params (≤ 100). - Billing: Billing depends on carrier delivery; API success but carrier failure is not billed. QPS limit is 5000/s per user.
- Credential safety: Never hard-code AK/SK; always rely on the default credential
chain (env vars /
~/.aliyun/config.json/ ECS RAM role / OIDC). - Parameter confirmation: Never guess signature/template — always ask the user, and
after consent fetch
query-sms-sign-list/query-sms-template-list(see "Interactive Parameter Confirmation"). - Send-result reporting:
send-sms/send-batch-smsresponses only confirm gateway acceptance (Code=OK+BizId); they are NOT proof of delivery. Whenever the user asks "did it arrive?" / "was it delivered?", always callquery-send-details(useBizIdfor precise lookup) and surfaceSendStatus(1=in-flight, 2=failed, 3=delivered) andErrCode— never reply based on the send-API response alone.
References
- Alibaba Cloud CLI documentation
- SMS Service console
- SendSms API documentation
- Send-status error codes (local) —
query-send-detailsErrCode(Alibabaisv.*/isp.*+ carrier receipts); upstream: 101347 / 101346 - SMS qualification query (local) —
QuerySmsQualificationRecord/QuerySingleSmsQualification
Scan to join WeChat group