
Volcengine Sdk Generator
- 31 installs
- 16 repo stars
- Updated August 3, 2026
- volcengine/volcengine-skills
Helps with ai & agent building tasks.
About
volcengine-sdk-generator is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- volcengine-sdk-generator
- AI & Agent Building
- AI-coding skill
Volcengine Sdk Generator by the numbers
- 31 all-time installs (skills.sh)
- +2 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #9,100 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/volcengine/volcengine-skills --skill volcengine-sdk-generatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 31 |
|---|---|
| repo stars | ★ 16 |
| Last updated | August 3, 2026 |
| Repository | volcengine/volcengine-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Volcengine SDK Generator
Generate ordinary Volcengine API call examples by default. Keep the default output focused on the API call itself: authentication setup, request object/params, invocation, and printing the response. Do not add retry, proxy, connection pool, debug logging, or other advanced SDK configuration unless the user explicitly asks for those topics.
For advanced SDK configuration questions, use the language-specific files under references/. These reference files are self-contained; answer from them directly.
| Topic | Reference |
|---|---|
| Go SDK configuration | references/sdk-integration-go.md |
| Python SDK configuration | references/sdk-integration-python.md |
| Java SDK configuration | references/sdk-integration-java.md |
| Node.js SDK configuration | references/sdk-integration-nodejs.md |
| PHP SDK configuration | references/sdk-integration-php.md |
Core Rules
- API discovery uses
scripts/rg_rank.py. After a concrete API is selected, callscripts/make_code.pyin direct mode with--service-code,--api-version, and--action. rg_rank.pysearches the bundled local ranker by default. It uses onergrecall pass whenrgis installed and automatically falls back to pure Python scanning whenrgis unavailable.- If local ranking has zero results,
rg_rank.pyautomatically falls back to the API Explorer search endpoint and marks those results asremote_search. Use--remote-searchsparingly only when local results are clearly wrong or incomplete. - Use the user's original request as the default
--query; do not rewrite it into a guessed API name or SDK method. The ranker tolerates surrounding noise through keyword inference, alias matching, OR recall, and field-weighted scoring. - Extract a shorter
--queryonly when the user clearly self-corrects with words such as等等,不对,重新来,我改主意,其实想要,其实是想要,应该是, or改成; the extracted query must be a continuous substring from the user request, not a guessed API name. - When multiple resources or services appear without a clear self-correction, run
rg_rank.pyonce with the original request. If top candidates are across different services and top1 does not lead top2 by at least 30%, list concise candidates and ask the user to choose. - Use
--resource,--intent,--service,--action, and--extraonly as high-confidence overrides or supplements when local ranking is noisy, the product alias is rare, or the user provides an explicit machine term. Values must come from the user wording or a trusted alias; do not invent terms. Manually provided--resource,--intent, and--servicereplace built-in inference for that group, so partial values can reduce recall. Include all known Chinese, English, and camelCase variants together when using them. - Pure-generic queries such as
api,sdk, ordemoskip local matching by themselves and either trigger remote search or returnempty_querywhen remote fallback is disabled. Refine the query with a concrete resource or action word. - ServiceCode is case-sensitive. Preserve the exact
service_codevalue from the selected API record when callingmake_code.py; for example,Kafkais notkafka. - When local ranking returns the same
service_code + actionacross multiple API versions and the user did not specify a version, prefer the packaged API Explorer default version. - Fetch
api-swaggeronly after a concrete API is selected. - The
api-swaggerfetch may include bothVersionandAPIVersionbecause that endpoint expects them; themake-codepayload must not includeVersion. - Call
make-codewithApiAction,ServiceCode,APIVersion,Region, andParams. - Do not send
Versiontomake-code. Paramsmust come from the user. Do not auto-fill from swagger demos.- Swagger is used for API metadata, required parameter hints, and lightweight validation. Do not serialize query arrays, form arrays, or
.Nparameters formake-code; pass the user’s JSON object asParams. - If the user omits required top-level parameters, mock only those top-level required parameters and clearly mark them as mock values. Do not mock optional parameters. If a required top-level parameter is an object or array, recursively fill only required child fields/items.
- Mock values must be derived from the fetched swagger first: prefer
example, thenexamples, thendefault, thenenum, then type/constraint-aware fallback. If a swagger example is masked, such as****orXX, skip it and use a valid fallback value. - Mock comments must be in Chinese by default and placed near the mocked assignment line when the target language supports line comments; do not add a duplicate mock banner at the top of the returned code.
- Returned SDK code must print the API response value. The script post-processes fixed
make-codetemplates for Python, Go, Java, and PHP to assign the response and print it. - Return the code generated by
scripts/make_code.pyas the primary SDK example. Do not rewrite SDK request construction, authentication setup, or response handling into a custom application unless the user explicitly asks for that. If optional formatting or convenience logic is added, keep the generated active response print, such asprint(resp),fmt.Println(resp),System.out.println(resp),print_r($response), orconsole.log(response). - If language is not specified, return all languages from
DemoSdk. - SDK install/dependency info is a separate, on-demand capability. Only when the user explicitly asks how to install the SDK or which package/version to use (keywords such as 依赖, 安装, install, 版本, 包, maven,
go get, pip, composer, npm), runscripts/sdk_info.pywith--service-codeand--api-version(reuse the selected API's values; add--languageto filter to one of go/python/java/php/nodejs). It returns the live install command (RunCommand) plus package and version per language. Do NOT run it during normal code generation. - If the API match is ambiguous, show concise candidates and ask the user to choose one. Do not add follow-up execution boilerplate such as saying that you will fetch swagger, mock required params, and call
make-codeafter the user chooses.
Workflow
1. Parse the user request:
- API hint: action, Chinese name, service code, or natural-language description.
- Language: Python, Go, Java, PHP, cURL, Node.js, or unspecified.
- Params: JSON object supplied by the user.
- Region: user value or default
cn-beijing.
2. Locate or validate the API once for every request. If the user already provides service_code, api_version, and action, use those values as strict filters and verify they exist locally before direct mode. For natural-language requests, call scripts/rg_rank.py with --query first. Use the full original request unless a clear self-correction keyword points to a later target; in that case use the final target substring. Avoid optional term flags on the first pass. Manually provided --resource, --intent, and --service replace built-in inference for that group rather than merging with it, so a partial flag value can reduce recall. If you must use them, include all known variants together. If rg_rank.py returns remote_search results because the local ranker had zero hits, treat them as candidates and still verify the selected service_code, api_version, and action before calling direct mode. Avoid --remote-search unless the local candidates are obviously wrong or incomplete.
3. After selecting service_code, api_version, and action, call scripts/make_code.py in direct API mode with --service-code, --api-version, and --action. If top-level required params are missing, the script fills only those required top-level params with swagger-derived mock values and annotates the returned code in Chinese. Ask for clarification only when API selection is genuinely ambiguous after local ranking; in that clarification, only list candidates and ask the user to choose.
4. Once params are available, call make-code through the script and return the official code. Do not transform the generated sample into a hand-written utility; any custom formatting must be secondary and must preserve the active response print.
Commands
Rank local candidates:
python3 scripts/rg_rank.py \
--query '角色扮演' \
--limit 10 \
--format textUse optional term flags only for high-confidence overrides or supplements, and keep --query as the user's wording:
python3 scripts/rg_rank.py \
--query '标准型加速器替换公网带宽包' \
--service 'ga' \
--resource '公网带宽包|PublicBandwidthPackage' \
--intent '替换|Replace' \
--limit 10 \
--format textDirect API mode:
In TRN examples, <account-id> is the Volcengine account ID segment, such as a masked 2134xxxyyy.
python3 scripts/make_code.py \
--service-code sts \
--api-version 2018-01-01 \
--action AssumeRole \
--language python \
--params-json '{"DurationSeconds":3600,"RoleSessionName":"demo","RoleTrn":"trn:iam::<account-id>:role/demo"}'Use --refresh-swagger when API Explorer metadata has just changed or generated code looks stale:
python3 scripts/make_code.py \
--service-code sts \
--api-version 2018-01-01 \
--action AssumeRole \
--refresh-swagger \
--params-json '{}'Fetch SDK install/dependency info on demand (only when the user asks about install, package, or version):
python3 scripts/sdk_info.py \
--service-code sts \
--api-version 2018-01-01 \
--language go[
{
"id": "sts_assume_role",
"patterns": [
"扮演角色"
],
"resource": [
"角色扮演",
"扮演角色",
"AssumeRole"
],
"intent": [
"获取",
"调用",
"Assume"
],
"service": [
"sts"
],
"action": [
"AssumeRole"
],
"target": {
"service_code": "sts",
"api_version": "2018-01-01",
"action": "AssumeRole"
}
},
{
"id": "ecs_run_instances",
"patterns": [
"创建ecs",
"创建一个ecs",
"创建ecs实例",
"购买云服务器",
"购买ecs",
"新建云服务器",
"新建ecs实例"
],
"resource": [
"ecs",
"云服务器",
"ECS",
"实例",
"Instance",
"RunInstances"
],
"intent": [
"创建",
"购买",
"新建",
"Run"
],
"service": [
"ecs"
],
"action": [
"RunInstances"
],
"target": {
"service_code": "ecs",
"api_version": "2020-04-01",
"action": "RunInstances"
}
},
{
"id": "ecs_describe_instances",
"patterns": [
"列出ecs",
"查询ecs",
"查看ecs",
"列出云服务器",
"查询云服务器",
"查看云服务器",
"ecs实例列表",
"云服务器列表",
"查询ecs详情",
"查看ecs详情",
"查询云服务器详情",
"查看云服务器详情",
"ecs实例详情",
"云服务器详情",
"describe ecs instances"
],
"resource": [
"ecs",
"云服务器",
"ECS",
"实例",
"Instance"
],
"intent": [
"列出",
"查询",
"查看",
"Describe"
],
"service": [
"ecs"
],
"action": [
"DescribeInstances"
],
"target": {
"service_code": "ecs",
"api_version": "2020-04-01",
"action": "DescribeInstances"
}
},
{
"id": "ecs_delete_instance",
"patterns": [
"删除ecs",
"释放ecs",
"销毁ecs",
"释放云服务器",
"退订云服务器",
"删除ecs实例"
],
"resource": [
"ecs",
"云服务器",
"ECS",
"实例",
"Instance"
],
"intent": [
"删除",
"释放",
"销毁",
"退订",
"Delete"
],
"service": [
"ecs"
],
"action": [
"DeleteInstance",
"DeleteInstances"
],
"target": {
"service_code": "ecs",
"api_version": "2020-04-01",
"action": "DeleteInstance"
}
},
{
"id": "ecs_start_instance",
"patterns": [
"启动ecs",
"启动ecs实例",
"开机ecs",
"开机云服务器"
],
"resource": [
"ecs",
"云服务器",
"ECS",
"实例",
"Instance"
],
"intent": [
"启动",
"开机",
"Start"
],
"service": [
"ecs"
],
"action": [
"StartInstance",
"StartInstances"
],
"target": {
"service_code": "ecs",
"api_version": "2020-04-01",
"action": "StartInstance"
}
},
{
"id": "ecs_stop_instance",
"patterns": [
"停止ecs",
"关闭ecs",
"关闭云服务器",
"关机ecs",
"关机云服务器"
],
"resource": [
"ecs",
"云服务器",
"ECS",
"实例",
"Instance"
],
"intent": [
"停止",
"关闭",
"关机",
"Stop"
],
"service": [
"ecs"
],
"action": [
"StopInstance",
"StopInstances"
],
"target": {
"service_code": "ecs",
"api_version": "2020-04-01",
"action": "StopInstance"
}
},
{
"id": "ecs_images",
"patterns": [
"查询ecs镜像",
"列出ecs镜像",
"查询云服务器镜像",
"镜像列表"
],
"resource": [
"ecs",
"云服务器",
"镜像",
"Image"
],
"intent": [
"查询",
"列出",
"查看",
"Describe"
],
"service": [
"ecs"
],
"action": [
"DescribeImages"
],
"target": {
"service_code": "ecs",
"api_version": "2020-04-01",
"action": "DescribeImages"
}
},
{
"id": "ecs_create_image",
"patterns": [
"创建ecs镜像",
"创建云服务器镜像",
"制作镜像"
],
"resource": [
"ecs",
"云服务器",
"镜像",
"Image"
],
"intent": [
"创建",
"制作",
"Create"
],
"service": [
"ecs"
],
"action": [
"CreateImage"
],
"target": {
"service_code": "ecs",
"api_version": "2020-04-01",
"action": "CreateImage"
}
},
{
"id": "ecs_key_pair",
"patterns": [
"创建ecs密钥对",
"查询ecs密钥对",
"云服务器密钥对"
],
"resource": [
"ecs",
"云服务器",
"密钥对",
"KeyPair"
],
"intent": [
"创建",
"查询",
"列出",
"Create",
"Describe"
],
"service": [
"ecs"
],
"action": [
"CreateKeyPair",
"DescribeKeyPairs"
]
},
{
"id": "vpc_create_vpc",
"patterns": [
"创建vpc",
"创建私有网络",
"新建vpc",
"新建私有网络"
],
"resource": [
"vpc",
"VPC",
"私有网络"
],
"intent": [
"创建",
"新建",
"Create"
],
"service": [
"vpc"
],
"action": [
"CreateVpc"
],
"target": {
"service_code": "vpc",
"api_version": "2020-04-01",
"action": "CreateVpc"
}
},
{
"id": "vpc_describe_vpcs",
"patterns": [
"列出vpc",
"查询vpc",
"查看vpc",
"vpc列表",
"私有网络列表",
"列出私有网络",
"查询私有网络"
],
"resource": [
"vpc",
"VPC",
"私有网络"
],
"intent": [
"列出",
"查询",
"查看",
"Describe"
],
"service": [
"vpc"
],
"action": [
"DescribeVpcs"
],
"target": {
"service_code": "vpc",
"api_version": "2020-04-01",
"action": "DescribeVpcs"
}
},
{
"id": "vpc_describe_vpc_detail",
"patterns": [
"查询vpc详情",
"查看vpc详情",
"查询私有网络详情",
"查看私有网络详情"
],
"resource": [
"vpc",
"VPC",
"私有网络",
"详情"
],
"intent": [
"查询",
"查看",
"Describe"
],
"service": [
"vpc"
],
"action": [
"DescribeVpcAttributes"
],
"target": {
"service_code": "vpc",
"api_version": "2020-04-01",
"action": "DescribeVpcAttributes"
}
},
{
"id": "vpc_associate_cidr",
"patterns": [
"增加辅助网段",
"添加辅助网段",
"绑定辅助cidr",
"vpc增加辅助网段"
],
"resource": [
"私有网络",
"VPC",
"辅助网",
"辅助网段",
"辅助CIDR",
"VpcCidrBlock",
"CidrBlock"
],
"intent": [
"添加",
"增加",
"Associate"
],
"service": [
"vpc"
],
"action": [
"AssociateVpcCidrBlock"
],
"target": {
"service_code": "vpc",
"api_version": "2020-04-01",
"action": "AssociateVpcCidrBlock"
}
},
{
"id": "vpc_disassociate_cidr",
"patterns": [
"删除辅助网段",
"解绑辅助cidr",
"删除私有网络的辅助网",
"删除私有网络辅助网",
"移除辅助网段"
],
"resource": [
"私有网络",
"VPC",
"辅助网",
"辅助网段",
"辅助CIDR",
"VpcCidrBlock",
"CidrBlock"
],
"intent": [
"删除",
"移除",
"解绑",
"Disassociate"
],
"service": [
"vpc"
],
"action": [
"DisassociateVpcCidrBlock"
],
"target": {
"service_code": "vpc",
"api_version": "2020-04-01",
"action": "DisassociateVpcCidrBlock"
}
},
{
"id": "vpc_subnet",
"patterns": [
"列出子网",
"vpc子网",
"私有网络子网"
],
"resource": [
"vpc",
"VPC",
"子网",
"Subnet"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"Create",
"Describe",
"Delete"
],
"service": [
"vpc"
],
"action": [
"CreateSubnet",
"DescribeSubnets",
"DeleteSubnet"
]
},
{
"id": "vpc_security_group",
"patterns": [
"列出安全组",
"安全组规则",
"添加安全组规则"
],
"resource": [
"vpc",
"安全组",
"SecurityGroup"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"添加",
"Create",
"Describe",
"Delete",
"Authorize"
],
"service": [
"vpc"
],
"action": [
"CreateSecurityGroup",
"DescribeSecurityGroups",
"DeleteSecurityGroup",
"AuthorizeSecurityGroupIngress",
"AuthorizeSecurityGroupEgress"
]
},
{
"id": "vpc_eip",
"patterns": [
"创建公网ip",
"弹性公网ip"
],
"resource": [
"公网IP",
"弹性公网IP",
"EIP",
"EipAddress"
],
"intent": [
"申请",
"创建",
"查询",
"释放",
"绑定",
"解绑",
"Allocate",
"Describe",
"Release",
"Associate",
"Disassociate"
],
"service": [
"vpc"
],
"action": [
"AllocateEipAddress",
"DescribeEipAddresses",
"ReleaseEipAddress",
"AssociateEipAddress",
"DisassociateEipAddress"
]
},
{
"id": "vpc_bandwidth_package",
"patterns": [
"修改共享带宽包"
],
"resource": [
"共享带宽包",
"带宽包",
"宽带包",
"BandwidthPackage"
],
"intent": [
"创建",
"查询",
"删除",
"修改",
"Create",
"Describe",
"Delete",
"Modify"
],
"service": [
"vpc"
],
"action": [
"CreateBandwidthPackage",
"DescribeBandwidthPackages",
"DeleteBandwidthPackage",
"ModifyBandwidthPackageAttributes"
]
},
{
"id": "redis_create_instance",
"patterns": [
"新建redis",
"购买redis",
"创建redis",
"创建redis实例",
"创建缓存数据库"
],
"resource": [
"Redis",
"redis",
"缓存数据库",
"实例",
"DBInstance"
],
"intent": [
"创建",
"新建",
"购买",
"Create"
],
"service": [
"Redis"
],
"action": [
"CreateDBInstance"
],
"target": {
"service_code": "Redis",
"api_version": "2020-12-07",
"action": "CreateDBInstance"
}
},
{
"id": "redis_describe_instances",
"patterns": [
"列出redis",
"查询redis",
"redis实例列表",
"查看redis实例",
"查询缓存数据库实例"
],
"resource": [
"Redis",
"redis",
"缓存数据库",
"实例",
"DBInstance"
],
"intent": [
"列出",
"查询",
"查看",
"Describe"
],
"service": [
"Redis"
],
"action": [
"DescribeDBInstances"
],
"target": {
"service_code": "Redis",
"api_version": "2020-12-07",
"action": "DescribeDBInstances"
}
},
{
"id": "redis_describe_instance_detail",
"patterns": [
"查询redis详情",
"查看redis详情",
"redis实例详情",
"缓存数据库详情"
],
"resource": [
"Redis",
"redis",
"缓存数据库",
"实例详情",
"DBInstance"
],
"intent": [
"查询",
"查看",
"Describe"
],
"service": [
"Redis"
],
"action": [
"DescribeDBInstanceDetail"
],
"target": {
"service_code": "Redis",
"api_version": "2020-12-07",
"action": "DescribeDBInstanceDetail"
}
},
{
"id": "redis_delete_instance",
"patterns": [
"退订redis",
"删除redis",
"释放redis",
"删除redis实例"
],
"resource": [
"Redis",
"redis",
"缓存数据库",
"实例",
"DBInstance"
],
"intent": [
"删除",
"释放",
"销毁",
"退订",
"Delete"
],
"service": [
"Redis"
],
"action": [
"DeleteDBInstance"
],
"target": {
"service_code": "Redis",
"api_version": "2020-12-07",
"action": "DeleteDBInstance"
}
},
{
"id": "redis_backup",
"patterns": [
"redis创建备份",
"redis备份列表",
"查询redis备份",
"redis手动备份"
],
"resource": [
"Redis",
"redis",
"备份",
"Backup"
],
"intent": [
"创建",
"查询",
"列出",
"Create",
"Describe"
],
"service": [
"Redis"
],
"action": [
"CreateBackup",
"DescribeBackups"
]
},
{
"id": "mysql_create_instance",
"patterns": [
"购买mysql",
"创建mysql",
"创建mysql实例",
"新建mysql"
],
"resource": [
"MySQL",
"mysql",
"RDS",
"云数据库",
"实例",
"DBInstance"
],
"intent": [
"创建",
"购买",
"Create"
],
"service": [
"rds_mysql"
],
"action": [
"CreateDBInstance"
],
"target": {
"service_code": "rds_mysql",
"api_version": "2022-01-01",
"action": "CreateDBInstance"
}
},
{
"id": "mysql_describe_instances",
"patterns": [
"列出mysql",
"查询mysql",
"mysql实例列表",
"查询rds mysql",
"云数据库mysql列表"
],
"resource": [
"MySQL",
"mysql",
"RDS",
"云数据库",
"实例",
"DBInstance"
],
"intent": [
"列出",
"查询",
"查看",
"Describe"
],
"service": [
"rds_mysql"
],
"action": [
"DescribeDBInstances"
],
"target": {
"service_code": "rds_mysql",
"api_version": "2022-01-01",
"action": "DescribeDBInstances"
}
},
{
"id": "mysql_describe_instance_detail",
"patterns": [
"查询mysql详情",
"查看mysql详情",
"mysql实例详情",
"rds mysql详情"
],
"resource": [
"MySQL",
"mysql",
"RDS",
"云数据库",
"实例详情",
"DBInstance"
],
"intent": [
"查询",
"查看",
"Describe"
],
"service": [
"rds_mysql"
],
"action": [
"DescribeDBInstanceDetail"
],
"target": {
"service_code": "rds_mysql",
"api_version": "2022-01-01",
"action": "DescribeDBInstanceDetail"
}
},
{
"id": "mysql_delete_instance",
"patterns": [
"退订mysql",
"删除mysql",
"释放mysql",
"删除mysql实例"
],
"resource": [
"MySQL",
"mysql",
"RDS",
"云数据库",
"实例",
"DBInstance"
],
"intent": [
"删除",
"释放",
"销毁",
"退订",
"Delete"
],
"service": [
"rds_mysql"
],
"action": [
"DeleteDBInstance"
],
"target": {
"service_code": "rds_mysql",
"api_version": "2022-01-01",
"action": "DeleteDBInstance"
}
},
{
"id": "mysql_describe_databases",
"patterns": [
"mysql查询数据库",
"查询mysql数据库",
"mysql数据库列表",
"列出mysql数据库",
"查看mysql数据库"
],
"resource": [
"MySQL",
"mysql",
"数据库",
"Database"
],
"intent": [
"查询",
"列出",
"查看",
"Describe"
],
"service": [
"rds_mysql"
],
"action": [
"DescribeDatabases"
],
"target": {
"service_code": "rds_mysql",
"api_version": "2022-01-01",
"action": "DescribeDatabases"
}
},
{
"id": "mysql_create_database",
"patterns": [
"mysql创建数据库",
"创建mysql数据库",
"新建mysql数据库"
],
"resource": [
"MySQL",
"mysql",
"数据库",
"Database"
],
"intent": [
"创建",
"新建",
"Create"
],
"service": [
"rds_mysql"
],
"action": [
"CreateDatabase"
],
"target": {
"service_code": "rds_mysql",
"api_version": "2022-01-01",
"action": "CreateDatabase"
}
},
{
"id": "mysql_delete_database",
"patterns": [
"mysql删除数据库",
"删除mysql数据库"
],
"resource": [
"MySQL",
"mysql",
"数据库",
"Database"
],
"intent": [
"删除",
"Delete"
],
"service": [
"rds_mysql"
],
"action": [
"DeleteDatabase"
],
"target": {
"service_code": "rds_mysql",
"api_version": "2022-01-01",
"action": "DeleteDatabase"
}
},
{
"id": "mysql_account",
"patterns": [
"mysql创建账号",
"mysql查询账号",
"mysql账号列表",
"mysql删除账号"
],
"resource": [
"MySQL",
"mysql",
"账号",
"账户",
"Account"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"Create",
"Describe",
"Delete"
],
"service": [
"rds_mysql"
],
"action": [
"CreateDBAccount",
"DescribeDBAccounts",
"DeleteDBAccount"
]
},
{
"id": "kafka_describe_instances",
"patterns": [
"列出kafka",
"查询kafka",
"查看kafka实例",
"kafka实例列表",
"消息队列kafka列表"
],
"resource": [
"Kafka",
"kafka",
"消息队列",
"实例"
],
"intent": [
"列出",
"查询",
"查看",
"Describe"
],
"service": [
"Kafka"
],
"action": [
"DescribeInstances"
],
"target": {
"service_code": "Kafka",
"api_version": "2022-05-01",
"action": "DescribeInstances"
}
},
{
"id": "kafka_describe_instance_detail",
"patterns": [
"查询kafka详情",
"查看kafka详情",
"kafka实例详情",
"消息队列kafka详情"
],
"resource": [
"Kafka",
"kafka",
"消息队列",
"实例详情"
],
"intent": [
"查询",
"查看",
"Describe"
],
"service": [
"Kafka"
],
"action": [
"DescribeInstanceDetail"
],
"target": {
"service_code": "Kafka",
"api_version": "2022-05-01",
"action": "DescribeInstanceDetail"
}
},
{
"id": "kafka_delete_instance",
"patterns": [
"退订kafka",
"删除kafka",
"删除kafka实例"
],
"resource": [
"Kafka",
"kafka",
"消息队列",
"实例"
],
"intent": [
"删除",
"释放",
"销毁",
"退订",
"Delete"
],
"service": [
"Kafka"
],
"action": [
"DeleteInstance"
],
"target": {
"service_code": "Kafka",
"api_version": "2022-05-01",
"action": "DeleteInstance"
}
},
{
"id": "kafka_topic",
"patterns": [
"创建kafka topic",
"查询kafka topic",
"列出kafka topic",
"kafka主题"
],
"resource": [
"Kafka",
"kafka",
"Topic",
"主题"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"Create",
"Describe",
"Delete"
],
"service": [
"Kafka"
],
"action": [
"CreateTopic",
"DescribeTopics",
"DeleteTopic"
]
},
{
"id": "kafka_group",
"patterns": [
"创建kafka group",
"查询kafka group",
"列出kafka group",
"kafka消费组",
"kafka group列表"
],
"resource": [
"Kafka",
"kafka",
"Group",
"消费组"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"Create",
"Describe",
"Delete"
],
"service": [
"Kafka"
],
"action": [
"CreateGroup",
"DescribeGroups",
"DeleteGroup"
]
},
{
"id": "kafka_user",
"patterns": [
"创建kafka用户",
"查询kafka用户",
"列出kafka用户",
"删除kafka用户",
"kafka sasl用户"
],
"resource": [
"Kafka",
"kafka",
"SASL",
"用户",
"User"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"Create",
"Describe",
"Delete"
],
"service": [
"Kafka"
],
"action": [
"CreateUser",
"DescribeUsers",
"DeleteUser"
]
},
{
"id": "postgresql_create_instance",
"patterns": [
"创建pg实例",
"创建postgresql",
"创建pgsql",
"购买pg",
"新建pg"
],
"resource": [
"PostgreSQL",
"postgresql",
"postgres",
"pgsql",
"pssql",
"PG",
"云数据库",
"实例",
"DBInstance"
],
"intent": [
"创建",
"购买",
"Create"
],
"service": [
"rds_postgresql"
],
"action": [
"CreateDBInstance"
],
"target": {
"service_code": "rds_postgresql",
"api_version": "2022-01-01",
"action": "CreateDBInstance"
}
},
{
"id": "postgresql_describe_instances",
"patterns": [
"列出postgresql",
"查询postgresql",
"查询pg实例"
],
"resource": [
"PostgreSQL",
"postgresql",
"postgres",
"pgsql",
"pssql",
"PG",
"云数据库",
"实例",
"DBInstance"
],
"intent": [
"列出",
"查询",
"查看",
"Describe"
],
"service": [
"rds_postgresql"
],
"action": [
"DescribeDBInstances"
],
"target": {
"service_code": "rds_postgresql",
"api_version": "2022-01-01",
"action": "DescribeDBInstances"
}
},
{
"id": "postgresql_describe_instance_detail",
"patterns": [
"查看postgresql详情",
"pgsql实例详情",
"pssql实例详情",
"pg实例详情"
],
"resource": [
"PostgreSQL",
"postgresql",
"postgres",
"pgsql",
"pssql",
"PG",
"实例详情",
"DBInstance"
],
"intent": [
"查询",
"查看",
"Describe"
],
"service": [
"rds_postgresql"
],
"action": [
"DescribeDBInstanceDetail"
],
"target": {
"service_code": "rds_postgresql",
"api_version": "2022-01-01",
"action": "DescribeDBInstanceDetail"
}
},
{
"id": "postgresql_delete_instance",
"patterns": [
"删除pg实例",
"删除postgresql",
"退订pg",
"删除pgsql实例"
],
"resource": [
"PostgreSQL",
"postgresql",
"postgres",
"pgsql",
"pssql",
"PG",
"实例",
"DBInstance"
],
"intent": [
"删除",
"释放",
"销毁",
"退订",
"Delete"
],
"service": [
"rds_postgresql"
],
"action": [
"DeleteDBInstance"
],
"target": {
"service_code": "rds_postgresql",
"api_version": "2022-01-01",
"action": "DeleteDBInstance"
}
},
{
"id": "postgresql_database",
"patterns": [
"postgresql创建数据库",
"postgresql查询数据库",
"pgsql数据库列表",
"pssql数据库列表",
"pg创建数据库"
],
"resource": [
"PostgreSQL",
"postgresql",
"pgsql",
"pssql",
"PG",
"数据库",
"Database"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"Create",
"Describe",
"Delete"
],
"service": [
"rds_postgresql"
],
"action": [
"CreateDatabase",
"DescribeDatabases",
"DeleteDatabase"
]
},
{
"id": "postgresql_describe_schemas",
"patterns": [
"pgsql schema列表",
"pssql schema列表",
"pg schema列表"
],
"resource": [
"PostgreSQL",
"postgresql",
"pgsql",
"pssql",
"PG",
"Schema"
],
"intent": [
"查询",
"列出",
"查看",
"Describe"
],
"service": [
"rds_postgresql"
],
"action": [
"DescribeSchemas"
],
"target": {
"service_code": "rds_postgresql",
"api_version": "2022-01-01",
"action": "DescribeSchemas"
}
},
{
"id": "cdn_add_domain",
"patterns": [
"cdn添加域名",
"cdn接入域名",
"创建cdn域名",
"添加加速域名",
"接入加速域名",
"创建加速域名"
],
"resource": [
"CDN",
"cdn",
"内容分发",
"域名",
"加速域名",
"CdnDomain"
],
"intent": [
"添加",
"接入",
"创建",
"Add",
"Create"
],
"service": [
"CDN"
],
"action": [
"AddCdnDomain"
],
"target": {
"service_code": "CDN",
"api_version": "2021-03-01",
"action": "AddCdnDomain"
}
},
{
"id": "cdn_list_domains",
"patterns": [
"查询cdn域名",
"列出cdn域名",
"cdn域名列表",
"查询加速域名",
"列出加速域名",
"cdn加速域名列表"
],
"resource": [
"CDN",
"cdn",
"内容分发",
"域名",
"加速域名",
"CdnDomain"
],
"intent": [
"列出",
"查询",
"查看",
"List"
],
"service": [
"CDN"
],
"action": [
"ListCdnDomains"
],
"target": {
"service_code": "CDN",
"api_version": "2021-03-01",
"action": "ListCdnDomains"
}
},
{
"id": "cdn_describe_config",
"patterns": [
"查询cdn配置",
"获取cdn配置",
"查询加速域名配置",
"cdn域名配置"
],
"resource": [
"CDN",
"cdn",
"内容分发",
"配置",
"加速域名",
"CdnConfig"
],
"intent": [
"查询",
"获取",
"Describe"
],
"service": [
"CDN"
],
"action": [
"DescribeCdnConfig"
],
"target": {
"service_code": "CDN",
"api_version": "2021-03-01",
"action": "DescribeCdnConfig"
}
},
{
"id": "cdn_update_config",
"patterns": [
"更新cdn配置",
"更新加速域名配置"
],
"resource": [
"CDN",
"cdn",
"内容分发",
"配置",
"加速域名",
"CdnConfig"
],
"intent": [
"修改",
"更新",
"Update"
],
"service": [
"CDN"
],
"action": [
"UpdateCdnConfig"
],
"target": {
"service_code": "CDN",
"api_version": "2021-03-01",
"action": "UpdateCdnConfig"
}
},
{
"id": "cdn_start_stop_domain",
"patterns": [
"启用cdn域名",
"停用cdn域名",
"启动加速域名",
"关闭加速域名"
],
"resource": [
"CDN",
"cdn",
"内容分发",
"域名",
"加速域名",
"CdnDomain"
],
"intent": [
"启用",
"停用",
"启动",
"关闭",
"Start",
"Stop"
],
"service": [
"CDN"
],
"action": [
"StartCdnDomain",
"StopCdnDomain"
]
},
{
"id": "cdn_refresh_preload",
"patterns": [
"cdn刷新",
"cdn预热",
"刷新cdn缓存",
"预热cdn缓存",
"刷新预热任务"
],
"resource": [
"CDN",
"cdn",
"内容分发",
"刷新",
"预热",
"Refresh",
"Preload"
],
"intent": [
"提交",
"创建",
"查询",
"Submit",
"Describe"
],
"service": [
"CDN"
],
"action": [
"SubmitRefreshTask",
"SubmitPreloadTask",
"DescribeContentTasks"
]
},
{
"id": "ark_chat_completions",
"patterns": [
"文本对话"
],
"resource": [
"ark",
"方舟",
"大模型",
"ChatCompletions",
"对话"
],
"intent": [
"对话",
"调用",
"Chat"
],
"service": [
"ark"
],
"action": [
"ChatCompletions"
],
"target": {
"service_code": "ark",
"api_version": "2024-01-01",
"action": "ChatCompletions"
}
},
{
"id": "ark_embeddings",
"patterns": [
"ark向量化",
"方舟向量化",
"embedding",
"embeddings",
"生成向量"
],
"resource": [
"ark",
"方舟",
"大模型",
"Embeddings",
"向量化",
"向量"
],
"intent": [
"向量化",
"生成",
"Embedding"
],
"service": [
"ark"
],
"action": [
"Embeddings"
],
"target": {
"service_code": "ark",
"api_version": "2024-01-01",
"action": "Embeddings"
}
},
{
"id": "ark_models",
"patterns": [
"查询方舟模型",
"列出方舟模型",
"方舟模型列表",
"查询基础模型"
],
"resource": [
"ark",
"方舟",
"大模型",
"基础模型",
"FoundationModel",
"Model"
],
"intent": [
"查询",
"列出",
"获取",
"List",
"Get"
],
"service": [
"ark"
],
"action": [
"ListFoundationModels",
"GetFoundationModel"
]
},
{
"id": "ark_endpoint",
"patterns": [
"查询推理接入点"
],
"resource": [
"ark",
"方舟",
"Endpoint",
"推理接入点"
],
"intent": [
"创建",
"查询",
"列出",
"获取",
"Create",
"List",
"Get"
],
"service": [
"ark"
],
"action": [
"CreateEndpoint",
"ListEndpoints",
"GetEndpoint"
]
},
{
"id": "alb_create_load_balancer",
"patterns": [
"创建应用型负载均衡",
"创建alb",
"创建alb实例"
],
"resource": [
"ALB",
"alb",
"应用负载均衡",
"应用型负载均衡",
"负载均衡",
"LoadBalancer"
],
"intent": [
"创建",
"Create"
],
"service": [
"alb"
],
"action": [
"CreateLoadBalancer"
],
"target": {
"service_code": "alb",
"api_version": "2020-04-01",
"action": "CreateLoadBalancer"
}
},
{
"id": "alb_listener",
"patterns": [
"创建alb监听器",
"查询alb监听器",
"alb监听器列表",
"删除alb监听器",
"应用负载均衡监听器"
],
"resource": [
"ALB",
"alb",
"监听器",
"Listener"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"Create",
"Describe",
"Delete"
],
"service": [
"alb"
],
"action": [
"CreateListener",
"DescribeListeners",
"DeleteListener"
]
},
{
"id": "alb_server_group",
"patterns": [
"创建alb服务器组",
"查询alb服务器组",
"alb服务器组列表",
"应用负载均衡服务器组",
"alb后端服务器组"
],
"resource": [
"ALB",
"alb",
"服务器组",
"后端服务器组",
"ServerGroup"
],
"intent": [
"创建",
"查询",
"列出",
"Create",
"Describe"
],
"service": [
"alb"
],
"action": [
"CreateServerGroup",
"DescribeServerGroups"
]
},
{
"id": "alb_rules",
"patterns": [
"创建alb转发规则",
"查询alb转发规则",
"alb转发规则列表",
"应用负载均衡转发规则"
],
"resource": [
"ALB",
"alb",
"转发规则",
"Rule"
],
"intent": [
"创建",
"查询",
"列出",
"Create",
"Describe"
],
"service": [
"alb"
],
"action": [
"CreateRules",
"DescribeRules"
]
},
{
"id": "slb_listener",
"patterns": [
"创建slb监听器",
"查询slb监听器",
"slb监听器列表",
"删除slb监听器",
"clb监听器",
"负载均衡监听器"
],
"resource": [
"SLB",
"slb",
"CLB",
"clb",
"监听器",
"Listener"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"Create",
"Describe",
"Delete"
],
"service": [
"clb"
],
"action": [
"CreateListener",
"DescribeListeners",
"DeleteListener"
]
},
{
"id": "slb_server_group",
"patterns": [
"创建slb服务器组",
"查询slb服务器组",
"slb服务器组列表",
"clb服务器组",
"负载均衡服务器组"
],
"resource": [
"SLB",
"slb",
"CLB",
"clb",
"服务器组",
"后端服务器组",
"ServerGroup"
],
"intent": [
"创建",
"查询",
"列出",
"Create",
"Describe"
],
"service": [
"clb"
],
"action": [
"CreateServerGroup",
"DescribeServerGroups"
]
},
{
"id": "nlb_load_balancer",
"patterns": [
"查询nlb",
"nlb实例列表",
"网络型负载均衡",
"创建网络负载均衡"
],
"resource": [
"NLB",
"nlb",
"网络型负载均衡",
"网络负载均衡",
"LoadBalancer"
],
"intent": [
"创建",
"查询",
"列出",
"Create",
"Describe"
],
"service": [
"clb"
],
"action": [
"CreateNetworkLoadBalancer",
"DescribeNetworkLoadBalancers"
]
},
{
"id": "waf_create_domain",
"patterns": [
"waf接入域名",
"waf添加域名",
"waf接入网站"
],
"resource": [
"WAF",
"waf",
"域名",
"网站",
"Domain"
],
"intent": [
"创建",
"添加",
"接入",
"Create"
],
"service": [
"waf"
],
"action": [
"CreateDomain"
],
"target": {
"service_code": "waf",
"api_version": "2023-12-25",
"action": "CreateDomain"
}
},
{
"id": "waf_describe_domains",
"patterns": [
"查询waf域名",
"列出waf域名",
"waf域名列表",
"查询waf站点",
"waf网站列表",
"查询waf网站"
],
"resource": [
"WAF",
"waf",
"域名",
"网站",
"Domain"
],
"intent": [
"列出",
"查询",
"查看",
"List",
"Get"
],
"service": [
"waf"
],
"action": [
"ListDomain",
"GetDomainInfo"
],
"target": {
"service_code": "waf",
"api_version": "2023-12-25",
"action": "ListDomain"
}
},
{
"id": "waf_update_domain",
"patterns": [
"修改waf域名",
"更新waf域名",
"修改waf网站",
"更新waf网站",
"waf修改域名配置"
],
"resource": [
"WAF",
"waf",
"域名",
"网站",
"Domain"
],
"intent": [
"修改",
"更新",
"Update"
],
"service": [
"waf"
],
"action": [
"UpdateDomain"
],
"target": {
"service_code": "waf",
"api_version": "2023-12-25",
"action": "UpdateDomain"
}
},
{
"id": "waf_acl_rule",
"patterns": [
"waf创建访问管控",
"waf查询访问管控",
"waf访问管控规则",
"waf创建acl规则",
"waf查询acl规则"
],
"resource": [
"WAF",
"waf",
"访问管控",
"ACL",
"AclRule"
],
"intent": [
"创建",
"查询",
"列出",
"Create",
"List"
],
"service": [
"waf"
],
"action": [
"CreateAclRule",
"ListAclRule"
]
},
{
"id": "waf_cc_rule",
"patterns": [
"waf创建cc规则",
"waf cc防护",
"waf频率限制",
"waf防刷规则"
],
"resource": [
"WAF",
"waf",
"CC",
"频率限制",
"防刷",
"CCRule"
],
"intent": [
"创建",
"查询",
"列出",
"Create",
"List"
],
"service": [
"waf"
],
"action": [
"CreateCCRule",
"ListCCRule"
]
},
{
"id": "cr_get_authorization_token",
"patterns": [
"获取镜像仓库临时密码",
"镜像仓库临时密码",
"获取镜像仓库密码",
"镜像仓库登录密码"
],
"resource": [
"镜像仓库",
"Registry",
"AuthorizationToken",
"临时密码",
"登录密码"
],
"intent": [
"获取",
"Get"
],
"service": [
"cr"
],
"action": [
"GetAuthorizationToken"
],
"target": {
"service_code": "cr",
"api_version": "2022-05-12",
"action": "GetAuthorizationToken"
}
},
{
"id": "cr_repository",
"patterns": [
"创建镜像仓库",
"查询镜像仓库",
"镜像仓库列表",
"删除镜像仓库"
],
"resource": [
"镜像仓库",
"OCI",
"制品仓库",
"Repository"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"Create",
"List",
"Delete"
],
"service": [
"cr"
],
"action": [
"CreateRepository",
"ListRepositories",
"DeleteRepository"
]
},
{
"id": "ga_public_bandwidth_package",
"patterns": [
"公网带宽包",
"公网宽带包",
"ga公网带宽包",
"共享公网带宽包"
],
"resource": [
"公网带宽包",
"公网宽带包",
"带宽包",
"宽带包",
"PublicBandwidthPackage"
],
"intent": [
"创建",
"查询",
"列出",
"删除",
"更新",
"Create",
"Describe",
"List",
"Delete",
"Update"
],
"service": [
"ga"
],
"action": [
"CreatePublicBandwidthPackage",
"DescribePublicBandwidthPackage",
"ListPublicBandwidthPackages",
"TerminatePublicBandwidthPackage",
"UpdatePublicBandwidthPackage"
]
},
{
"id": "ga_terminate_public_bandwidth_package",
"patterns": [
"删除公网带宽包"
],
"resource": [
"公网带宽包",
"公网宽带包",
"带宽包",
"宽带包",
"PublicBandwidthPackage"
],
"intent": [
"删除",
"退订",
"Terminate"
],
"service": [
"ga"
],
"action": [
"TerminatePublicBandwidthPackage"
],
"target": {
"service_code": "ga",
"api_version": "2022-03-01",
"action": "TerminatePublicBandwidthPackage"
}
},
{
"id": "apig_create_gateway_service",
"patterns": [
"api网关创建服务",
"apig创建服务",
"创建api网关服务",
"创建apig服务"
],
"resource": [
"API网关",
"api网关",
"网关服务",
"GatewayService"
],
"intent": [
"创建",
"Create"
],
"service": [
"apig"
],
"action": [
"CreateGatewayService"
],
"target": {
"service_code": "apig",
"api_version": "2021-03-03",
"action": "CreateGatewayService"
}
}
]
Go SDK Integration Reference
Requirements
Go 1.14+ (1.18+ for Ark service) for the common SDK. Some service packages may require newer Go versions. Use Go modules.
Credential Resolution
Prefer the default credential chain or explicit provider objects. Do not hardcode AK/SK in production examples.
Default chain order when a session is created without explicit credentials:
1. EnvProvider 2. OIDCCredentialsProvider from VOLCENGINE_OIDC_* 3. CLI profile provider from ~/.volcengine/config.json 4. EcsRoleProvider from ECS IMDSv2
The chain reuses the last successful provider by default and falls back to the full chain if that provider later fails.
Environment Variables
EnvProvider reads these variables in order:
- AK:
VOLCENGINE_ACCESS_KEY>VOLCSTACK_ACCESS_KEY_ID>VOLCSTACK_ACCESS_KEY - SK:
VOLCENGINE_SECRET_KEY>VOLCSTACK_SECRET_ACCESS_KEY>VOLCSTACK_SECRET_KEY - Token:
VOLCENGINE_SESSION_TOKEN>VOLCSTACK_SESSION_TOKEN
Use VOLCENGINE_* for new code.
AK/SK and STS Token
package main
import (
"os"
"github.com/volcengine/volcengine-go-sdk/volcengine"
"github.com/volcengine/volcengine-go-sdk/volcengine/credentials"
"github.com/volcengine/volcengine-go-sdk/volcengine/session"
)
func main() {
config := volcengine.NewConfig().
WithRegion("cn-beijing").
WithCredentials(credentials.NewStaticCredentials(
os.Getenv("VOLCENGINE_ACCESS_KEY"),
os.Getenv("VOLCENGINE_SECRET_KEY"),
os.Getenv("VOLCENGINE_SESSION_TOKEN"),
))
_, err := session.NewSession(config)
if err != nil {
panic(err)
}
}For environment-only resolution:
config := volcengine.NewConfig().
WithRegion("cn-beijing").
WithCredentials(credentials.NewEnvCredentials())Default Credential Chain
package main
import (
"github.com/volcengine/volcengine-go-sdk/service/ecs"
"github.com/volcengine/volcengine-go-sdk/volcengine/session"
)
func main() {
sess, err := session.NewSession()
if err != nil {
panic(err)
}
_ = ecs.New(sess)
}To customize the ECS role name used by the default chain:
package main
import (
"github.com/volcengine/volcengine-go-sdk/volcengine"
"github.com/volcengine/volcengine-go-sdk/volcengine/credentials"
"github.com/volcengine/volcengine-go-sdk/volcengine/defaults"
"github.com/volcengine/volcengine-go-sdk/volcengine/session"
)
func main() {
creds := defaults.NewDefaultCredentialProvider(func(o *credentials.DefaultCredentialProviderOptions) {
o.RoleName = "your-ecs-role-name"
})
_, err := session.NewSession(volcengine.NewConfig().
WithRegion("cn-beijing").
WithCredentials(creds))
if err != nil {
panic(err)
}
}STS AssumeRole
Current Go SDK uses credentials.NewStsCredentialsWithOptions or credentials.NewStsCredentials. The older NewAssumeRoleCredentials helper is not present in this SDK.
package main
import (
"os"
"time"
"github.com/volcengine/volcengine-go-sdk/volcengine"
"github.com/volcengine/volcengine-go-sdk/volcengine/credentials"
"github.com/volcengine/volcengine-go-sdk/volcengine/session"
)
func main() {
config := volcengine.NewConfig().
WithRegion("cn-beijing").
WithCredentials(credentials.NewStsCredentialsWithOptions(
os.Getenv("VOLCENGINE_ACCESS_KEY"),
os.Getenv("VOLCENGINE_SECRET_KEY"),
"RoleName",
"AccountId",
func(o *credentials.StsAssumeRoleOptions) {
o.Host = "sts.volcengineapi.com"
o.Region = "cn-beijing"
o.Schema = "https"
o.DurationSeconds = 3600
o.Timeout = 30 * time.Second
o.MaxRetries = 3
o.RetryInterval = time.Second
},
))
_, err := session.NewSession(config)
if err != nil {
panic(err)
}
}DurationSeconds must be at least 900. The provider refreshes before expiry. If the source credentials are temporary, set o.SessionToken.
OIDC
The default chain can read OIDC settings from environment variables:
VOLCENGINE_OIDC_ROLE_TRNVOLCENGINE_OIDC_TOKEN_FILEVOLCENGINE_OIDC_ROLE_SESSION_NAMEVOLCENGINE_OIDC_ROLE_POLICYVOLCENGINE_OIDC_STS_ENDPOINT
provider := credentials.NewOIDCCredentialsProviderWithOptions(
"/path/to/oidc-token",
"trn:iam::<account-id>:role/oidc-role",
func(o *credentials.OIDCProviderOptions) {
o.DurationSeconds = 3600
o.Endpoint = "sts.volcengineapi.com"
o.MaxRetries = volcengine.Int(3)
o.RetryInterval = time.Second
},
)
config := volcengine.NewConfig().
WithRegion("cn-beijing").
WithCredentials(credentials.NewCredentials(provider))SAML
provider := credentials.NewSAMLCredentialsProviderWithOptions(
"trn:iam::<account-id>:role/saml-role",
"trn:iam::<account-id>:saml-provider/MyIdp",
"BASE64_ENCODED_SAML_RESPONSE",
func(o *credentials.SAMLProviderOptions) {
o.DurationSeconds = 3600
o.MaxRetries = volcengine.Int(3)
o.RetryInterval = time.Second
},
)
config := volcengine.NewConfig().
WithRegion("cn-beijing").
WithCredentials(credentials.NewCredentials(provider))CLI Profile Provider
The CLI provider reads ~/.volcengine/config.json unless overridden.
- Config path priority: constructor argument >
VOLCENGINE_CLI_CONFIG_FILE> default path - Profile priority: constructor argument >
VOLCENGINE_PROFILE>VOLCSTACK_PROFILE> configcurrent>default
Supported modes include AK, StsToken, RamRoleArn, OIDC, EcsRole, SSO, and console-login.
ECS Role Provider
EcsRoleProvider uses ECS IMDSv2:
1. PUT /latest/api/token 2. Resolve role name: constructor argument > VOLCENGINE_ECS_METADATA > IMDS auto-detect 3. GET /volcstack/latest/iam/security_credentials/{roleName}
Set VOLCENGINE_ECS_METADATA_DISABLED=true to disable IMDS credentials.
config := volcengine.NewConfig().
WithRegion("cn-beijing").
WithCredentials(credentials.NewEcsRoleCredentials("your-ecs-role-name"))Endpoint Configuration
config := volcengine.NewConfig().
WithRegion("cn-shanghai").
WithEndpoint("custom-endpoint.volcengineapi.com").
WithUseDualStack(true)HTTP Transport, Proxy, SSL
httpClient := &http.Client{
Timeout: 60 * time.Second,
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
MaxIdleConns: 200,
IdleConnTimeout: 120 * time.Second,
TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS12},
},
}
config := volcengine.NewConfig().
WithHTTPClient(httpClient).
WithHTTPProxy("http://proxy:8080").
WithHTTPSProxy("https://proxy:8080")WithDisableSSL(true) switches to HTTP. Do not disable TLS unless the target endpoint requires it.
Timeouts
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
resp, err := svc.DescribeInstancesWithContext(ctx, input)Retry
config := volcengine.NewConfig().WithMaxRetries(5)
input.SetRetryableErrorCodes([]string{"Throttling", "ResourceIsBusy"})Debugging
config := volcengine.NewConfig().
WithDebug(true).
WithLogWriter(os.Stderr)Java SDK Integration Reference
Requirements
Java 1.8.0_131+. For Java 9+, add javax.annotation-api if your build complains about missing annotation classes.
Credential Resolution
Use either explicit Credentials, a CredentialProvider, or the automatic default chain. When neither ApiClient.setCredentials(...) nor ApiClient.setCredentialProvider(...) is configured, the signing interceptor creates a default chain automatically.
Default chain order:
1. EnvironmentVariableCredentialProvider 2. OidcCredentialProvider.fromEnvironment() 3. CLIConfigCredentialProvider 4. EcsRoleCredentialProvider unless VOLCENGINE_ECS_METADATA_DISABLED=true
The default chain reuses the last successful provider by default.
Environment Variables
Java reads only VOLCENGINE_* credential variables:
VOLCENGINE_ACCESS_KEYVOLCENGINE_SECRET_KEYVOLCENGINE_SESSION_TOKEN
It does not use the legacy VOLCSTACK_* fallbacks for basic credentials.
AK/SK and STS Token
import com.volcengine.ApiClient;
import com.volcengine.sign.Credentials;
public class SampleCode {
public static void main(String[] args) {
ApiClient apiClient = new ApiClient()
.setCredentials(Credentials.getCredentials(
System.getenv("VOLCENGINE_ACCESS_KEY"),
System.getenv("VOLCENGINE_SECRET_KEY"),
System.getenv("VOLCENGINE_SESSION_TOKEN")))
.setRegion("cn-beijing");
}
}Environment Provider
import com.volcengine.ApiClient;
import com.volcengine.auth.CredentialProvider;
import com.volcengine.auth.EnvironmentVariableCredentialProvider;
public class SampleCode {
public static void main(String[] args) {
ApiClient apiClient = new ApiClient()
.setCredentialProvider(new CredentialProvider(
new EnvironmentVariableCredentialProvider()))
.setRegion("cn-beijing");
}
}Default Credential Chain
import com.volcengine.ApiClient;
public class SampleCode {
public static void main(String[] args) {
ApiClient apiClient = new ApiClient().setRegion("cn-beijing");
}
}To customize the ECS role name used by the default chain:
import com.volcengine.ApiClient;
import com.volcengine.auth.CredentialProvider;
import com.volcengine.auth.DefaultCredentialProvider;
public class SampleCode {
public static void main(String[] args) {
DefaultCredentialProvider provider = DefaultCredentialProvider.builder()
.roleName("your-ecs-role-name")
.reuseLastProviderEnabled(true)
.build();
ApiClient apiClient = new ApiClient()
.setCredentialProvider(new CredentialProvider(provider))
.setRegion("cn-beijing");
}
}STS AssumeRole
Current Java SDK uses StsAssumeRoleProvider. The older Credentials.getAssumeRoleCredentials(...) helper is not present in this SDK.
import com.volcengine.ApiClient;
import com.volcengine.auth.CredentialProvider;
import com.volcengine.auth.StsAssumeRoleProvider;
public class SampleCode {
public static void main(String[] args) {
StsAssumeRoleProvider provider = new StsAssumeRoleProvider(
System.getenv("VOLCENGINE_ACCESS_KEY"),
System.getenv("VOLCENGINE_SECRET_KEY"),
"RoleName",
"AccountId");
provider.setHost("sts.volcengineapi.com");
provider.setRegion("cn-beijing");
provider.setSchema("https");
provider.setDurationSeconds(3600);
provider.setTimeout(30);
provider.setExpireBufferSeconds(60);
ApiClient apiClient = new ApiClient()
.setCredentialProvider(new CredentialProvider(provider))
.setRegion("cn-beijing");
}
}If the source AK/SK are temporary, use the constructor that also accepts sessionToken.
OIDC
Required environment variables for env mode:
VOLCENGINE_OIDC_ROLE_TRNVOLCENGINE_OIDC_TOKEN_FILE
Optional:
VOLCENGINE_OIDC_ROLE_SESSION_NAMEVOLCENGINE_OIDC_ROLE_POLICYVOLCENGINE_OIDC_STS_ENDPOINT
import com.volcengine.ApiClient;
import com.volcengine.auth.CredentialProvider;
import com.volcengine.auth.OidcCredentialProvider;
public class SampleCode {
public static void main(String[] args) {
OidcCredentialProvider provider = new OidcCredentialProvider(
"trn:iam::<account-id>:role/oidc-role",
null,
"/var/run/secrets/oidc/token",
null,
"sts.volcengineapi.com");
provider.setDurationSeconds(3600);
provider.setExpireBufferSeconds(300);
provider.setSchema("https");
provider.setMaxRetries(3);
provider.setRetryIntervalMs(1000);
ApiClient apiClient = new ApiClient()
.setCredentialProvider(new CredentialProvider(provider))
.setRegion("cn-beijing");
}
}SAML
import com.volcengine.ApiClient;
import com.volcengine.auth.CredentialProvider;
import com.volcengine.auth.SamlCredentialProvider;
public class SampleCode {
public static void main(String[] args) {
SamlCredentialProvider provider = new SamlCredentialProvider(
"trn:iam::<account-id>:role/saml-role",
"trn:iam::<account-id>:saml-provider/MyIdp",
"BASE64_ENCODED_SAML_RESPONSE",
null,
"sts.volcengineapi.com");
provider.setDurationSeconds(3600);
provider.setExpireBufferSeconds(300);
provider.setSchema("https");
provider.setMaxRetries(3);
provider.setRetryIntervalMs(1000);
ApiClient apiClient = new ApiClient()
.setCredentialProvider(new CredentialProvider(provider))
.setRegion("cn-beijing");
}
}CLI Profile Provider
CLIConfigCredentialProvider reads $HOME/.volcengine/config.json by default.
- Config path priority: constructor
configPath>VOLCENGINE_CLI_CONFIG_FILE> default path - Profile priority: constructor
profileName>VOLCENGINE_PROFILE> configcurrent>default
Supported modes include AK, StsToken, RamRoleArn, OIDC, EcsRole, SSO, and console-login. Mode matching is case-insensitive.
ECS Role Provider
EcsRoleCredentialProvider uses ECS IMDSv2 and supports role auto-detection:
- Role name priority: constructor argument >
VOLCENGINE_ECS_METADATA> IMDS auto-detect - Disable switch:
VOLCENGINE_ECS_METADATA_DISABLED=true - Default connect timeout: 1000 ms
- Default read timeout: 1000 ms
- Default retries: 3
- Default expiry buffer: 300 seconds
import com.volcengine.ApiClient;
import com.volcengine.auth.CredentialProvider;
import com.volcengine.auth.EcsRoleCredentialProvider;
public class SampleCode {
public static void main(String[] args) {
EcsRoleCredentialProvider provider =
EcsRoleCredentialProvider.create("your-ecs-role-name");
provider.setMaxRetries(3);
provider.setRetryIntervalMs(1000);
provider.setExpireBufferSeconds(300);
ApiClient apiClient = new ApiClient()
.setCredentialProvider(new CredentialProvider(provider))
.setRegion("cn-beijing");
}
}Endpoint Configuration
apiClient.setEndpoint("custom-endpoint.volcengineapi.com");
apiClient.setRegion("cn-shanghai");
apiClient.setUseDualStack(true);HTTP Connection Pool
apiClient.setMaxIdleConns(10);
apiClient.setKeepAliveDurationMs(300000);SSL, Proxy, Timeouts
apiClient.setVerifyingSsl(false);
apiClient.setDisableSSL(true);
apiClient.setHttpProxy("http://proxy:8080");
apiClient.setHttpsProxy("https://proxy:8080");
apiClient.setConnectionTimeout(5000);
apiClient.setReadTimeout(30000);
apiClient.setWriteTimeout(30000);Retry
apiClient.setRetrySettings(new RetrySettings()
.setMaxAttempts(5)
.setMinDelay(300)
.setMaxDelay(300000));Debugging
apiClient.setDebugging(true);Node.js SDK Integration Reference
Requirements
Node.js >= 18. Install @volcengine/sdk-core and the target service package.
pnpm add @volcengine/sdk-core
pnpm add @volcengine/ecs # service-specific packageCredential Resolution
Use explicit client credentials, credentialProvider, assumeRoleParams, or the automatic default chain. If a client has no inline AK/SK and no credentialProvider, the credentials middleware creates a DefaultCredentialProvider.
Resolution order inside the middleware:
1. Inline accessKeyId + secretAccessKey 2. Legacy assumeRoleParams, converted to StsAssumeRoleProvider 3. Explicit credentialProvider 4. DefaultCredentialProvider
Default chain order:
1. EnvironmentVariableCredentialProvider 2. OidcCredentialProvider 3. CLIConfigCredentialProvider 4. EcsRoleCredentialProvider unless VOLCENGINE_ECS_METADATA_DISABLED=true
Environment Variables
EnvironmentVariableCredentialProvider reads:
- AK:
VOLCENGINE_ACCESS_KEY>VOLCSTACK_ACCESS_KEY_ID>VOLCSTACK_ACCESS_KEY - SK:
VOLCENGINE_SECRET_KEY>VOLCSTACK_SECRET_ACCESS_KEY>VOLCSTACK_SECRET_KEY - Token:
VOLCENGINE_SESSION_TOKEN>VOLCSTACK_SESSION_TOKEN
Use VOLCENGINE_* for new code.
AK/SK and STS Token
import { EcsClient } from "@volcengine/ecs";
const client = new EcsClient({
region: "cn-beijing",
accessKeyId: process.env.VOLCENGINE_ACCESS_KEY,
secretAccessKey: process.env.VOLCENGINE_SECRET_KEY,
sessionToken: process.env.VOLCENGINE_SESSION_TOKEN,
});Environment-only usage:
import { EcsClient } from "@volcengine/ecs";
const client = new EcsClient({ region: "cn-beijing" });Default Credential Chain
import { DefaultCredentialProvider } from "@volcengine/sdk-core";
import { EcsClient } from "@volcengine/ecs";
const client = new EcsClient({
region: "cn-beijing",
credentialProvider: new DefaultCredentialProvider({
roleName: "your-ecs-role-name",
reuseLastProviderEnabled: true,
}),
});STS AssumeRole
Use StsAssumeRoleProvider. It caches credentials by source AK/SK and role TRN, merges concurrent refreshes, and refreshes before expiry.
import { StsAssumeRoleProvider } from "@volcengine/sdk-core";
import { EcsClient } from "@volcengine/ecs";
const credentialProvider = new StsAssumeRoleProvider({
accessKeyId: process.env.VOLCENGINE_ACCESS_KEY!,
secretAccessKey: process.env.VOLCENGINE_SECRET_KEY!,
roleTrn: "trn:iam::<account-id>:role/role123",
roleSessionName: "sdk-node-demo",
region: "cn-beijing",
host: "sts.volcengineapi.com",
protocol: "https",
durationSeconds: 3600,
policy: undefined,
});
const client = new EcsClient({
region: "cn-beijing",
credentialProvider,
});Legacy assumeRoleParams is still accepted by the middleware and translated to StsAssumeRoleProvider.
OIDC
Supported OIDC environment variables:
VOLCENGINE_OIDC_ROLE_TRNVOLCENGINE_OIDC_TOKEN_FILEVOLCENGINE_OIDC_ROLE_SESSION_NAMEVOLCENGINE_OIDC_ROLE_POLICYVOLCENGINE_OIDC_STS_ENDPOINT
import { OidcCredentialProvider } from "@volcengine/sdk-core";
import { EcsClient } from "@volcengine/ecs";
const credentialProvider = new OidcCredentialProvider({
roleTrn: "trn:iam::<account-id>:role/oidc-role",
oidcTokenFile: "/path/to/oidc/token",
roleSessionName: "sdk-node-oidc",
host: "sts.volcengineapi.com",
});
const client = new EcsClient({
region: "cn-beijing",
credentialProvider,
});Use new OidcCredentialProvider() to read from environment variables.
SAML
Supported SAML environment variables:
VOLCENGINE_SAML_ROLE_TRNVOLCENGINE_SAML_ACCOUNT_IDVOLCENGINE_SAML_PROVIDER_TRNVOLCENGINE_SAML_ASSERTIONVOLCENGINE_SAML_ENDPOINTVOLCENGINE_SAML_POLICY
import { SamlCredentialProvider } from "@volcengine/sdk-core";
import { EcsClient } from "@volcengine/ecs";
const credentialProvider = new SamlCredentialProvider({
roleTrn: "trn:iam::<account-id>:role/saml-role",
accountId: "<account-id>",
samlProviderTrn: "trn:iam::<account-id>:saml-provider/my-provider",
samlAssertion: "BASE64_ENCODED_SAML_ASSERTION",
host: "sts.volcengineapi.com",
});
const client = new EcsClient({
region: "cn-beijing",
credentialProvider,
});Use new SamlCredentialProvider() to read from environment variables.
CLI Profile Provider
CLIConfigCredentialProvider reads ~/.volcengine/config.json by default.
- Config path priority:
VOLCENGINE_CLI_CONFIG_FILE> default path - Supported modes include AK/static credentials, STS token, role, OIDC, ECS role, SSO, and console-login according to the current CLI provider implementation.
ECS Role Provider
EcsRoleCredentialProvider uses ECS IMDSv2:
- Role name priority: constructor argument >
VOLCENGINE_ECS_METADATA - Disable switch:
VOLCENGINE_ECS_METADATA_DISABLED=true - Default connect timeout: 1 second
- Default read timeout: 1 second
- Default retries: 3
- Default expiry buffer: 300 seconds
The current source contains an autoDetectRoleName helper, but resolveRoleName still throws when neither constructor roleName nor VOLCENGINE_ECS_METADATA is set. Pass the role name explicitly for now.
import { EcsRoleCredentialProvider } from "@volcengine/sdk-core";
import { EcsClient } from "@volcengine/ecs";
const credentialProvider = new EcsRoleCredentialProvider({
roleName: "your-ecs-role-name",
connectTimeout: 1,
readTimeout: 1,
maxRetries: 3,
retryInterval: 1,
expiredBufferSeconds: 300,
});
const client = new EcsClient({
region: "cn-beijing",
credentialProvider,
});Endpoint Configuration
const client = new EcsClient({
region: "cn-shanghai",
host: "custom-endpoint.volcengineapi.com",
useDualStack: true,
});Network Configuration
const client = new EcsClient({
region: "cn-beijing",
protocol: "https",
httpOptions: {
timeout: 5000,
ignoreSSL: false,
proxy: { protocol: "http", host: "127.0.0.1", port: 8888 },
pool: {
keepAlive: true,
keepAliveMsecs: 1000,
maxSockets: 50,
maxFreeSockets: 10,
},
},
});Proxy can also be configured with VOLC_PROXY_PROTOCOL, VOLC_PROXY_HOST, and VOLC_PROXY_PORT. Constructor options take priority.
Timeouts
const client = new EcsClient({
region: "cn-beijing",
httpOptions: { timeout: 5000 },
});
await client.send(command, { timeout: 30000 });Retry
import { StrategyName } from "@volcengine/sdk-core";
const client = new EcsClient({
region: "cn-beijing",
maxRetries: 5,
strategyName: StrategyName.ExponentialWithRandomJitterBackoffStrategy,
});Set autoRetry: false to disable retry.
Error Handling
import { HttpRequestError } from "@volcengine/sdk-core";
try {
await client.send(command);
} catch (error) {
if (error instanceof HttpRequestError) {
const requestId = error.data?.ResponseMetadata?.RequestId;
const apiError = error.data?.ResponseMetadata?.Error;
console.error(error.status, requestId, apiError?.Code, apiError?.Message);
}
}Resource Cleanup
client.destroy();Debugging
client.middlewareStack.add(
(next) => async (args) => {
console.log("Request:", args.request.method, args.request.host);
const result = await next(args);
console.log("Response:", result.response?.status);
return result;
},
{ step: "finalizeRequest", name: "LogMiddleware", priority: 10 },
);PHP SDK Integration Reference
Requirements
PHP >= 5.5. Install dependencies with Composer.
Credential Resolution
Use explicit Configuration AK/SK, setCredentialProvider(...), or the automatic default chain. When AK and SK are both empty, ApiClient creates and caches a DefaultCredentialProvider on the configuration.
Default chain order:
1. EnvironmentVariableCredentialProvider 2. OidcCredentialProvider::fromEnvironment() 3. CLIConfigCredentialProvider 4. EcsRoleCredentialProvider
The default chain reuses the last successful provider by default.
Environment Variables
EnvironmentVariableCredentialProvider reads:
- AK:
VOLCENGINE_ACCESS_KEY>VOLCSTACK_ACCESS_KEY_ID>VOLCSTACK_ACCESS_KEY - SK:
VOLCENGINE_SECRET_KEY>VOLCSTACK_SECRET_ACCESS_KEY>VOLCSTACK_SECRET_KEY - Token:
VOLCENGINE_SESSION_TOKEN>VOLCSTACK_SESSION_TOKEN
Use VOLCENGINE_* for new code.
AK/SK and STS Token
<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = \Volcengine\Common\Configuration::getDefaultConfiguration()
->setAk(getenv('VOLCENGINE_ACCESS_KEY'))
->setSk(getenv('VOLCENGINE_SECRET_KEY'))
->setSessionToken(getenv('VOLCENGINE_SESSION_TOKEN') ?: '')
->setRegion('cn-beijing');Environment Provider
<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = \Volcengine\Common\Configuration::getDefaultConfiguration()
->setRegion('cn-beijing')
->setCredentialProvider(
new \Volcengine\Common\Auth\Providers\EnvironmentVariableCredentialProvider()
);Default Credential Chain
<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = \Volcengine\Common\Configuration::getDefaultConfiguration()
->setRegion('cn-beijing');With empty AK/SK, the next generated service API call uses DefaultCredentialProvider automatically.
STS AssumeRole
Current PHP SDK uses StsProvider. The old setAssumeRoleTrn, setAssumeRoleSessionName, and setAssumeRoleDurationSeconds configuration methods are not present in the current common Configuration.
<?php
require_once __DIR__ . '/vendor/autoload.php';
$provider = new \Volcengine\Common\Auth\Providers\StsProvider(
getenv('VOLCENGINE_ACCESS_KEY'),
getenv('VOLCENGINE_SECRET_KEY'),
'RoleName',
'AccountId',
'cn-beijing',
3600,
'https',
'sts.volcengineapi.com',
null
);
$config = \Volcengine\Common\Configuration::getDefaultConfiguration()
->setRegion('cn-beijing')
->setCredentialProvider($provider);When Configuration has no explicit AK/SK, ApiClient calls the provider's getCredentials() and reads AccessKeyId, SecretAccessKey, and SessionToken. StsProvider::getCredentials() calls STS AssumeRole on each invocation and does not maintain a local credential cache, unlike the OIDC and SAML providers.
OIDC
Supported OIDC environment variables:
VOLCENGINE_OIDC_ROLE_TRNVOLCENGINE_OIDC_TOKEN_FILEVOLCENGINE_OIDC_ROLE_SESSION_NAMEVOLCENGINE_OIDC_ROLE_POLICYVOLCENGINE_OIDC_STS_ENDPOINT
<?php
require_once __DIR__ . '/vendor/autoload.php';
$provider = new \Volcengine\Common\Auth\Providers\OidcCredentialProvider(
'trn:iam::<account-id>:role/oidc-role',
'/var/run/secrets/oidc/token',
'credentials-php-demo',
null,
'sts.volcengineapi.com'
);
$provider->setSchema('https')
->setMaxRetries(3)
->setRetryInterval(1);
$config = \Volcengine\Common\Configuration::getDefaultConfiguration()
->setRegion('cn-beijing')
->setCredentialProvider($provider);Use OidcCredentialProvider::fromEnvironment() to read from environment variables.
SAML
<?php
require_once __DIR__ . '/vendor/autoload.php';
$provider = new \Volcengine\Common\Auth\Providers\SamlCredentialProvider(
'RoleName',
'<account-id>',
'MyIdp',
'BASE64_ENCODED_SAML_RESPONSE',
null,
'sts.volcengineapi.com'
);
$provider->setSchema('https')
->setMaxRetries(3)
->setRetryInterval(1);
$config = \Volcengine\Common\Configuration::getDefaultConfiguration()
->setRegion('cn-beijing')
->setCredentialProvider($provider);OIDC and SAML providers cache credentials and refresh before expiry. Their expiry is estimated from local durationSeconds.
CLI Profile Provider
CLIConfigCredentialProvider reads ~/.volcengine/config.json by default.
- Config path priority: constructor
configPath>VOLCENGINE_CLI_CONFIG_FILE> default path - Profile priority: constructor
profileName>VOLCENGINE_PROFILE/VOLCSTACK_PROFILE> configcurrent>default
Supported modes include ak, StsToken, ramrolearn, oidc, ecsrole, sso, and console-login.
For sso and console-login, PHP refreshes token cache files with an atomic rename so short-lived PHP processes can share refreshed tokens.
ECS Role Provider
EcsRoleCredentialProvider uses ECS IMDSv2 and supports role auto-detection:
- Role name priority: constructor argument >
VOLCENGINE_ECS_METADATA> IMDS auto-detect - Disable switch:
VOLCENGINE_ECS_METADATA_DISABLED=true - Default connect timeout: 1 second
- Default read timeout: 1 second
- Default retries: 3
- Default expiry buffer: 300 seconds
<?php
require_once __DIR__ . '/vendor/autoload.php';
$provider = \Volcengine\Common\Auth\Providers\EcsRoleCredentialProvider::create(
'your-ecs-role-name'
);
$provider->setMaxRetries(3)
->setRetryInterval(1)
->setConnectTimeout(1)
->setReadTimeout(1)
->setExpireBufferSeconds(300);
$config = \Volcengine\Common\Configuration::getDefaultConfiguration()
->setRegion('cn-beijing')
->setCredentialProvider($provider);The previous documentation note claiming ECS role auto-detection is unsupported is outdated for this source tree.
Endpoint Configuration
$config->setHost('custom-endpoint.volcengineapi.com');
$config->setRegion('cn-shanghai');
$config->setUseDualStack(true);SSL, Proxy, and HTTP Client
$config->setSchema('http');
$config->setVerifySsl(false);
$apiInstance = new \Volcengine\Ecs\Api\ECSApi(
new \GuzzleHttp\Client([
'proxy' => 'http://proxy:8080',
'timeout' => 30,
'connect_timeout' => 5,
'curl' => [CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2],
]),
$config
);Debugging
$config->setDebug(true);
$config->setDebugFile('/path/to/sdk.log');Python SDK Integration Reference
Requirements
Python >= 2.7 for the common SDK. Some runtimes, such as Ark, require Python 3.6+.
Credential Resolution
Use explicit configuration.ak/sk, configuration.credential_provider, or the automatic default chain. When ak, sk, and credential_provider are all unset, SignRequestInterceptor creates a shared DefaultCredentialProvider.
Default chain order:
1. EnvironmentVariableCredentialProvider 2. StsOidcCredentialProvider 3. CLIConfigCredentialProvider 4. EcsRoleCredentialProvider unless VOLCENGINE_ECS_METADATA_DISABLED=true
The chain reuses the last successful provider by default.
Environment Variables
Python reads these basic credential variables:
VOLCENGINE_ACCESS_KEYVOLCENGINE_SECRET_KEYVOLCENGINE_SESSION_TOKEN
It does not use legacy VOLCSTACK_* fallbacks for basic credentials.
AK/SK and STS Token
import os
import volcenginesdkcore
configuration = volcenginesdkcore.Configuration()
configuration.ak = os.environ.get("VOLCENGINE_ACCESS_KEY")
configuration.sk = os.environ.get("VOLCENGINE_SECRET_KEY")
configuration.session_token = os.environ.get("VOLCENGINE_SESSION_TOKEN")
configuration.region = "cn-beijing"
volcenginesdkcore.Configuration.set_default(configuration)Environment Provider
import volcenginesdkcore
from volcenginesdkcore.auth.providers.env_provider import EnvironmentVariableCredentialProvider
configuration = volcenginesdkcore.Configuration()
configuration.region = "cn-beijing"
configuration.credential_provider = EnvironmentVariableCredentialProvider()
volcenginesdkcore.Configuration.set_default(configuration)Default Credential Chain
import volcenginesdkcore
from volcenginesdkcore.auth.providers.default_provider import DefaultCredentialProvider
configuration = volcenginesdkcore.Configuration()
configuration.region = "cn-beijing"
configuration.credential_provider = DefaultCredentialProvider()
volcenginesdkcore.Configuration.set_default(configuration)You can omit credential_provider; the SDK creates the default chain automatically when no explicit AK/SK are configured.
STS AssumeRole
Current Python SDK uses StsCredentialProvider. The old configuration.assume_role_* fields are not implemented in Configuration.
import os
import volcenginesdkcore
from volcenginesdkcore.auth.providers.sts_provider import StsCredentialProvider
configuration = volcenginesdkcore.Configuration()
configuration.region = "cn-beijing"
configuration.credential_provider = StsCredentialProvider(
ak=os.environ.get("VOLCENGINE_ACCESS_KEY"),
sk=os.environ.get("VOLCENGINE_SECRET_KEY"),
role_name="RoleName",
account_id="AccountId",
duration_seconds=3600,
scheme="https",
host="sts.volcengineapi.com",
region="cn-beijing",
timeout=30,
expired_buffer_seconds=60,
max_retries=3,
retry_interval=1,
)
volcenginesdkcore.Configuration.set_default(configuration)max_retries is total attempts and is coerced to at least 1. expired_buffer_seconds must be <= 600.
OIDC
StsOidcCredentialProvider supports two modes:
- Backward-compatible explicit mode with
role_name + account_id + oidc_token - Env-aware mode with
role_trn + oidc_token_file
Supported OIDC environment variables:
VOLCENGINE_OIDC_ROLE_TRNVOLCENGINE_OIDC_TOKEN_FILEVOLCENGINE_OIDC_ROLE_SESSION_NAMEVOLCENGINE_OIDC_ROLE_POLICYVOLCENGINE_OIDC_STS_ENDPOINT
import volcenginesdkcore
from volcenginesdkcore.auth.providers.sts_oidc_provider import StsOidcCredentialProvider
configuration = volcenginesdkcore.Configuration()
configuration.region = "cn-beijing"
configuration.credential_provider = StsOidcCredentialProvider(
role_trn="trn:iam::<account-id>:role/oidc-role",
oidc_token_file="/var/run/secrets/oidc/token",
duration_seconds=3600,
host="sts.volcengineapi.com",
region="cn-beijing",
max_retries=3,
retry_interval=1,
)
volcenginesdkcore.Configuration.set_default(configuration)Use StsOidcCredentialProvider() with no arguments to read from environment variables.
SAML
import volcenginesdkcore
from volcenginesdkcore.auth.providers.sts_saml_provider import StsSamlCredentialProvider
configuration = volcenginesdkcore.Configuration()
configuration.region = "cn-beijing"
configuration.credential_provider = StsSamlCredentialProvider(
role_trn="trn:iam::<account-id>:role/saml-role",
saml_provider_trn="trn:iam::<account-id>:saml-provider/MyIdp",
saml_resp="BASE64_ENCODED_SAML_RESPONSE",
duration_seconds=3600,
host="sts.volcengineapi.com",
region="cn-beijing",
max_retries=3,
retry_interval=1,
)
volcenginesdkcore.Configuration.set_default(configuration)role_trn has priority over role_name + account_id. saml_provider_trn has priority over account_id + provider_name.
CLI Profile Provider
CLIConfigCredentialProvider reads ~/.volcengine/config.json by default.
- Config path priority: constructor
config_path>VOLCENGINE_CLI_CONFIG_FILE> default path - Profile priority: constructor
profile_name>VOLCENGINE_PROFILE> configcurrent>default
Supported modes include AK, StsToken, RamRoleArn, OIDC, EcsRole, SSO, and console-login.
For SSO and console-login, the SDK refreshes tokens in memory and does not write cache files.
ECS Role Provider
EcsRoleCredentialProvider uses ECS IMDSv2:
- Role name priority: constructor argument >
VOLCENGINE_ECS_METADATA> IMDS auto-detect - Disable switch:
VOLCENGINE_ECS_METADATA_DISABLED=true - Default connect timeout: 1 second
- Default read timeout: 1 second
- Default retries: 3
- Default expiry buffer: 300 seconds
import volcenginesdkcore
from volcenginesdkcore.auth.providers.ecs_role_provider import EcsRoleCredentialProvider
configuration = volcenginesdkcore.Configuration()
configuration.region = "cn-beijing"
configuration.credential_provider = EcsRoleCredentialProvider(
role_name="your-ecs-role-name",
connect_timeout=1,
read_timeout=1,
max_retries=3,
retry_interval=1,
expired_buffer_seconds=300,
)
volcenginesdkcore.Configuration.set_default(configuration)Endpoint Configuration
configuration.host = "custom-endpoint.volcengineapi.com"
configuration.region = "cn-shanghai"
configuration.use_dual_stack = TrueConnection Pool
configuration.num_pools = 8
configuration.connection_pool_maxsize = 20Use num_pools; connection_pools_count is not a field on the current Configuration.
SSL and Proxy
configuration.scheme = "http"
configuration.verify_ssl = False
configuration.ssl_ca_cert = "/path/to/ca-bundle.crt"
configuration.proxy = "http://proxy:8080"
configuration.http_proxy = "http://proxy:8080"
configuration.https_proxy = "https://proxy:8080"Timeouts
configuration.connect_timeout = 10.0
configuration.read_timeout = 60.0Per-request timeout may be supplied through generated SDK runtime options when the target service method supports _runtime_option.
Retry
configuration.auto_retry = True
configuration.num_max_retries = 5
configuration.min_retry_delay_ms = 300
configuration.max_retry_delay_ms = 300000
configuration.retry_error_codes = ["Throttling", "ResourceIsBusy"]The retryer uses retries-after-initial-attempt semantics. Provider-level STS helpers may use total-attempt semantics and adapt internally.
Debugging
configuration.debug = True
configuration.logger_file = "/path/to/sdk.log"#!/usr/bin/env python3
# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd.
# SPDX-License-Identifier: MIT
"""Find a Volcengine API locally, fetch swagger, and call explorer make-code."""
from __future__ import annotations
import argparse
import json
import os
import platform
import re
import sys
import time
import urllib.parse
import urllib.request
from pathlib import Path
from typing import Any
API_BASE = "https://api.volcengine.com/api/common"
METHODS = ("get", "post", "put", "delete", "patch", "head", "trace")
LANG_ALIASES = {
"python": "PYTHON",
"py": "PYTHON",
"go": "GO",
"golang": "GO",
"java": "JAVA",
"php": "PHP",
"curl": "CURL",
"shell": "CURL",
"node": "NODEJS",
"nodejs": "NODEJS",
"node.js": "NODEJS",
}
def skill_root() -> Path:
return Path(__file__).resolve().parents[1]
def references_dir() -> Path:
return skill_root() / "references"
def cache_dir() -> Path:
custom = os.environ.get("VOLCENGINE_MAKE_CODE_CACHE_DIR")
if custom:
return Path(custom).expanduser()
if platform.system() == "Windows":
base = os.environ.get("LOCALAPPDATA") or os.environ.get("APPDATA")
if base:
return Path(base) / "volcengine-make-code"
xdg = os.environ.get("XDG_CACHE_HOME")
if xdg:
return Path(xdg) / "volcengine-make-code"
return Path.home() / ".cache" / "volcengine-make-code"
def normalize(value: str | None) -> str:
return re.sub(r"\s+", " ", value or "").strip()
def norm_key(value: str | None) -> str:
return normalize(value).lower()
def split_words(value: str) -> list[str]:
value = re.sub(r"([a-z0-9])([A-Z])", r"\1 \2", value or "")
return [p.lower() for p in re.split(r"[^A-Za-z0-9_]+", value) if p]
def chinese_intents(value: str) -> list[str]:
intents = []
for intent in ("创建", "查询", "删除", "更新", "修改", "绑定", "解绑", "列表", "获取"):
if intent in (value or ""):
intents.append(intent)
return intents
def load_records() -> list[dict[str, Any]]:
wiki_path = references_dir() / "api_wiki.jsonl"
return [
json.loads(line)
for line in wiki_path.read_text(encoding="utf-8").splitlines()
if line.strip()
]
def service_codes(records: list[dict[str, Any]]) -> set[str]:
return {str(record.get("service_code", "")).lower() for record in records if record.get("service_code")}
def infer_service_code_from_query(query: str | None, records: list[dict[str, Any]]) -> str | None:
if not query:
return None
codes = service_codes(records)
for token in re.findall(r"[A-Za-z][A-Za-z0-9_]*", query):
value = token.lower()
if value in codes:
return next(
str(record["service_code"])
for record in records
if str(record.get("service_code", "")).lower() == value
)
return None
def default_version_for_service(service_code: str, *, x_language: str = "zh") -> str | None:
path = cache_dir() / "versions" / f"{service_code.lower()}.json"
data = None
if path.exists() and time.time() - path.stat().st_mtime < 7 * 86400:
try:
data = json.loads(path.read_text(encoding="utf-8"))
except json.JSONDecodeError:
data = None
if data is None:
params = urllib.parse.urlencode({"ServiceCode": service_code})
try:
data = http_json(f"{API_BASE}/explorer/versions?{params}", x_language=x_language)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
except Exception:
return None
versions = data.get("Result", {}).get("Versions", [])
for item in versions:
if item.get("IsDefault") == 1:
return item.get("Version")
if versions:
return versions[0].get("Version")
return None
def rank_candidates(
matches: list[dict[str, Any]],
*,
query: str | None,
default_version: str | None = None,
) -> list[dict[str, Any]]:
return sorted(
matches,
key=lambda r: (
default_version is not None and r.get("api_version") == default_version,
record_score(r, query or r.get("action", "")),
r.get("online_status") == 0,
r.get("api_version", ""),
),
reverse=True,
)
def record_score(record: dict[str, Any], query: str) -> int:
q_raw = query or ""
q = norm_key(query)
compact_q = re.sub(r"\s+", "", q)
score = 0
action = norm_key(record.get("action"))
service = norm_key(record.get("service_code"))
name_cn = norm_key(record.get("name_cn"))
group = norm_key(record.get("api_group"))
description = norm_key(record.get("description"))
usage = norm_key(record.get("usage_scenario"))
haystack = " ".join([action, service, name_cn, group, description, usage])
compact_name = re.sub(r"\s+", "", name_cn)
if action and action == q:
score += 160
if action and action in q:
score += 130
if name_cn and name_cn == q:
score += 160
if compact_name and compact_name in compact_q:
score += 135
if service and "创建" in q_raw and compact_name == f"创建{service}":
score += 160
if q and q in haystack:
score += 60
if service and re.search(rf"\b{re.escape(service)}\b", q):
score += 35
for intent in chinese_intents(q_raw):
if name_cn == f"{intent}实例":
score += 120
elif name_cn.startswith(intent):
score += 75
elif intent in name_cn:
score += 35
if intent in description:
score += 20
for word in split_words(q_raw):
if len(word) <= 1:
continue
if word == action:
score += 40
elif word in action:
score += 20
elif word in haystack:
score += 8
for keyword in record.get("keywords", []):
k = norm_key(keyword)
if k and k in q:
score += 15
return score
def find_local_candidates(
records: list[dict[str, Any]],
*,
query: str | None,
service_code: str | None,
action: str | None,
api_version: str | None,
limit: int = 8,
) -> list[dict[str, Any]]:
inferred_service_code = service_code or infer_service_code_from_query(query, records)
default_version = (
default_version_for_service(inferred_service_code)
if inferred_service_code and not api_version
else None
)
if inferred_service_code and action:
matches = [
r
for r in records
if r.get("service_code", "").lower() == inferred_service_code.lower()
and r.get("action", "").lower() == action.lower()
and (not api_version or r.get("api_version") == api_version)
]
return rank_candidates(matches, query=query, default_version=default_version)[:limit]
if action:
matches = [
r
for r in records
if r.get("action", "").lower() == action.lower()
]
if inferred_service_code:
matches = [
r
for r in matches
if r.get("service_code", "").lower() == inferred_service_code.lower()
]
if api_version:
matches = [r for r in matches if r.get("api_version") == api_version]
if matches:
return rank_candidates(matches, query=query or action, default_version=default_version)[:limit]
if not query:
return []
candidate_records = records
if inferred_service_code:
candidate_records = [
record
for record in records
if str(record.get("service_code", "")).lower() == inferred_service_code.lower()
]
scored = [(record_score(record, query), record) for record in candidate_records]
scored = [(score, record) for score, record in scored if score > 0]
scored.sort(
key=lambda item: (
default_version is not None and item[1].get("api_version") == default_version,
item[0],
item[1].get("online_status") == 0,
item[1].get("api_version", ""),
),
reverse=True,
)
return [record for _, record in scored[:limit]]
def http_json(
url: str,
*,
method: str = "GET",
payload: dict[str, Any] | None = None,
x_language: str = "zh",
timeout: int = 20,
) -> dict[str, Any]:
data = None
headers = {
"Accept": "application/json, text/plain, */*",
"x-language": x_language,
"User-Agent": "volcengine-make-code-skill/1.0",
}
if payload is not None:
data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
try:
with urllib.request.urlopen(req, timeout=timeout) as resp:
body = resp.read().decode("utf-8")
return json.loads(body)
except urllib.error.HTTPError as exc:
body = exc.read().decode("utf-8", errors="replace")
raise RuntimeError(f"HTTP {exc.code} {url}: {body}") from exc
def choose_operation(swagger: dict[str, Any]) -> tuple[str, str, dict[str, Any]]:
paths = swagger.get("paths") or {}
for path, path_item in paths.items():
if not isinstance(path_item, dict):
continue
for method in METHODS:
operation = path_item.get(method)
if isinstance(operation, dict):
return path, method, operation
raise ValueError("swagger has no supported operation")
def resolve_ref(swagger: dict[str, Any], value: dict[str, Any] | None) -> dict[str, Any]:
if not isinstance(value, dict):
return {}
ref = value.get("$ref")
if not ref or not isinstance(ref, str) or not ref.startswith("#/"):
return value
current: Any = swagger
for part in ref[2:].split("/"):
part = part.replace("~1", "/").replace("~0", "~")
if not isinstance(current, dict):
return value
current = current.get(part)
return current if isinstance(current, dict) else value
def first_request_body_schema(swagger: dict[str, Any], operation: dict[str, Any]) -> dict[str, Any]:
request_body = resolve_ref(swagger, operation.get("requestBody"))
content = request_body.get("content") or {}
if not isinstance(content, dict) or not content:
return {}
preferred = ["application/json", "application/x-www-form-urlencoded", "multipart/form-data"]
for content_type in [*preferred, *content.keys()]:
media = content.get(content_type)
if isinstance(media, dict):
return resolve_ref(swagger, media.get("schema"))
return {}
def schema_properties(swagger: dict[str, Any], schema: dict[str, Any]) -> dict[str, Any]:
schema = resolve_ref(swagger, schema)
props = schema.get("properties")
if isinstance(props, dict):
return props
return {}
def extract_swagger_param_info(swagger: dict[str, Any]) -> dict[str, Any]:
path, _method, operation = choose_operation(swagger)
path_item = swagger.get("paths", {}).get(path, {})
known: set[str] = set()
required: set[str] = set()
schemas: dict[str, dict[str, Any]] = {}
parameters = []
if isinstance(path_item.get("parameters"), list):
parameters.extend(path_item["parameters"])
if isinstance(operation.get("parameters"), list):
parameters.extend(operation["parameters"])
for param_ref in parameters:
param = resolve_ref(swagger, param_ref)
name = param.get("name")
if not name:
continue
known.add(name)
schemas[name] = resolve_ref(swagger, param.get("schema")) or {"type": "string"}
if param.get("required") is True:
required.add(name)
body_schema = first_request_body_schema(swagger, operation)
for name, prop_schema in schema_properties(swagger, body_schema).items():
known.add(name)
schemas[name] = resolve_ref(swagger, prop_schema) or {}
for name in body_schema.get("required") or []:
if isinstance(name, str):
required.add(name)
servers = swagger.get("servers") or []
region = None
if servers and isinstance(servers[0], dict):
variables = servers[0].get("variables") or {}
for name, variable in variables.items():
if not isinstance(variable, dict):
continue
if variable.get("x-service-region"):
region = variable.get("default")
return {
"known_params": sorted(known),
"required_params": sorted(required),
"param_schemas": schemas,
"default_region": region,
"_swagger": swagger,
}
def schema_type(schema: dict[str, Any]) -> str:
raw_type = schema.get("type")
if isinstance(raw_type, list):
raw_type = raw_type[0] if raw_type else ""
if isinstance(raw_type, str):
return raw_type
if isinstance(schema.get("properties"), dict):
return "object"
if isinstance(schema.get("items"), dict):
return "array"
return ""
def mock_required_object(swagger: dict[str, Any] | None, schema: dict[str, Any], depth: int) -> dict[str, Any]:
if depth >= 5:
return {}
props = schema.get("properties")
if not isinstance(props, dict):
return {}
result: dict[str, Any] = {}
for child_name in schema.get("required") or []:
if not isinstance(child_name, str):
continue
child_schema = props.get(child_name, {})
result[child_name] = mock_value_for_schema(
child_name,
child_schema if isinstance(child_schema, dict) else {},
swagger=swagger,
depth=depth + 1,
)
return result
def mock_value_for_schema(
name: str,
schema: dict[str, Any],
*,
swagger: dict[str, Any] | None = None,
depth: int = 0,
) -> Any:
if swagger:
schema = resolve_ref(swagger, schema)
lower_name = name.lower()
value = schema.get("example")
if value not in (None, "") and is_usable_example(name, value, schema):
return value
examples = schema.get("examples")
if isinstance(examples, list):
for value in examples:
if value not in (None, "") and is_usable_example(name, value, schema):
return value
elif isinstance(examples, dict):
for item in examples.values():
value = item.get("value") if isinstance(item, dict) else item
if value not in (None, "") and is_usable_example(name, value, schema):
return value
value = schema.get("default")
if value not in (None, "") and is_usable_example(name, value, schema):
return value
enum_values = schema.get("enum")
if isinstance(enum_values, list) and enum_values:
return enum_values[0]
current_type = schema_type(schema)
if current_type == "object":
return mock_required_object(swagger, schema, depth)
if current_type == "array":
item_schema = schema.get("items")
if not isinstance(item_schema, dict):
return []
return [
mock_value_for_schema(
name,
item_schema,
swagger=swagger,
depth=depth + 1,
)
]
if lower_name in {"cidrblock", "cidr", "ipcidr"} or "cidrblock" in lower_name:
return "172.16.0.0/16"
if lower_name.endswith("zoneid"):
return "cn-beijing-a"
if lower_name.endswith("imageid"):
return "image-xxxxxxxx"
if lower_name.endswith("instancetypeid"):
return "ecs.g1.large"
if lower_name.endswith("vpcid"):
return "vpc-xxxxxxxx"
if lower_name.endswith("subnetid"):
return "subnet-xxxxxxxx"
if lower_name.endswith("securitygroupid"):
return "sg-xxxxxxxx"
if lower_name.endswith("name"):
return f"demo-{re.sub(r'[^a-zA-Z0-9]+', '-', name).strip('-').lower() or 'name'}"
if current_type == "integer":
return 1
if current_type == "number":
return 1.0
if current_type == "boolean":
return True
return f"mock-{re.sub(r'[^a-zA-Z0-9]+', '-', name).strip('-').lower() or 'value'}"
def is_masked_example(value: Any) -> bool:
if isinstance(value, str):
return bool(re.search(r"(\*{2,}|X{2,}|x{2,})", value))
if isinstance(value, list):
return any(is_masked_example(item) for item in value)
if isinstance(value, dict):
return any(is_masked_example(item) for item in value.values())
return False
def is_usable_example(name: str, value: Any, schema: dict[str, Any]) -> bool:
if is_masked_example(value):
return False
if is_url_style_json_example(value):
return False
current_type = schema_type(schema)
if current_type == "integer":
if isinstance(value, bool):
return False
if isinstance(value, int):
return True
if isinstance(value, str):
try:
int(value.strip())
return True
except (TypeError, ValueError):
return False
return False
if current_type == "number":
if isinstance(value, bool):
return False
if isinstance(value, (int, float)):
return True
if isinstance(value, str):
try:
float(value.strip())
return True
except (TypeError, ValueError):
return False
return False
if current_type == "boolean":
if isinstance(value, bool):
return True
if isinstance(value, str):
return value.strip().lower() in {"true", "false", "1", "0"}
return False
return True
def is_url_style_json_example(value: Any) -> bool:
if not isinstance(value, str):
return False
if re.search(r"\b[A-Za-z][A-Za-z0-9_]*\.\d+\.[A-Za-z0-9_]+\s*=", value):
return True
if "&" in value and re.search(r"(^|&)[^&=\s]+=[^&]*", value):
return True
return False
def apply_missing_required_mocks(
params: dict[str, Any],
param_info: dict[str, Any],
) -> tuple[dict[str, Any], dict[str, Any]]:
result = dict(params)
mocked: dict[str, Any] = {}
schemas = param_info.get("param_schemas") or {}
swagger = param_info.get("_swagger") if isinstance(param_info.get("_swagger"), dict) else None
for name in param_info["required_params"]:
if name in result:
continue
value = mock_value_for_schema(name, schemas.get(name, {}), swagger=swagger)
result[name] = value
mocked[name] = value
return result, mocked
def swagger_cache_path(record: dict[str, Any]) -> Path:
return (
cache_dir()
/ "swagger"
/ record["service_code"]
/ record["api_version"]
/ f"{record['action']}.json"
)
def fetch_swagger(
record: dict[str, Any],
*,
x_language: str,
refresh: bool = False,
ttl_seconds: int = 86400,
) -> dict[str, Any]:
path = swagger_cache_path(record)
if not refresh and path.exists():
if time.time() - path.stat().st_mtime < ttl_seconds:
return json.loads(path.read_text(encoding="utf-8"))
params = urllib.parse.urlencode(
{
"ServiceCode": record["service_code"],
"Version": record["api_version"],
"APIVersion": record["api_version"],
"ActionName": record["action"],
}
)
data = http_json(f"{API_BASE}/explorer/api-swagger?{params}", x_language=x_language)
candidates = []
result = data.get("Result")
if isinstance(result, dict):
candidates.append(result.get("Api"))
candidates.append(data.get("Api"))
swagger = next(
(
item
for item in candidates
if isinstance(item, dict) and isinstance(item.get("paths"), dict)
),
None,
)
if swagger is None:
raise RuntimeError("api-swagger response did not include swagger object")
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(swagger, ensure_ascii=False), encoding="utf-8")
return swagger
def load_params(args: argparse.Namespace) -> dict[str, Any]:
if args.params_json and args.params_file:
raise ValueError("use only one of --params-json or --params-file")
if args.params_file:
text = Path(args.params_file).read_text(encoding="utf-8")
elif args.params_json:
text = args.params_json
else:
return {}
data = json.loads(text)
if not isinstance(data, dict):
raise ValueError("params must be a JSON object")
return data
def normalize_language(language: str | None) -> str | None:
if not language:
return None
return LANG_ALIASES.get(language.lower(), language.upper())
def make_payload(
record: dict[str, Any],
swagger: dict[str, Any],
params: dict[str, Any],
region: str | None,
) -> tuple[dict[str, Any], dict[str, Any]]:
info = swagger.get("info") if isinstance(swagger.get("info"), dict) else {}
param_info = extract_swagger_param_info(swagger)
resolved_region = region or param_info.get("default_region") or "cn-beijing"
payload = {
"ApiAction": info.get("x-action") or record["action"],
"ServiceCode": info.get("x-service-code") or record["service_code"],
"APIVersion": info.get("version") or record["api_version"],
"Region": resolved_region,
"Params": params,
}
return payload, param_info
def call_make_code(payload: dict[str, Any], *, x_language: str) -> dict[str, Any]:
return http_json(
f"{API_BASE}/explorer/make-code",
method="POST",
payload=payload,
x_language=x_language,
)
def print_json(data: Any) -> None:
print(json.dumps(data, ensure_ascii=False, indent=2))
def print_text(output: dict[str, Any]) -> None:
api = output.get("api") or {}
print(
f"{api.get('service_code')} {api.get('api_version')} {api.get('action')} "
f"{api.get('name_cn', '')}".strip()
)
warnings = output.get("warnings") or {}
mock_notice_value = warnings.get("mock_notice")
if mock_notice_value:
print(mock_notice_value)
selected_code = output.get("code")
if isinstance(selected_code, str):
print(selected_code)
return
demo_sdk = output.get("raw_demo_sdk") or {}
for language, code in demo_sdk.items():
print(f"\n## {language}")
if isinstance(code, str):
print(code)
else:
print(json.dumps(code, ensure_ascii=False, indent=2))
def ensure_go_fmt_import(code: str) -> str:
if '"fmt"' in code:
return code
lines = code.splitlines(keepends=True)
for idx, line in enumerate(lines):
if line.strip() == "import (":
lines.insert(idx + 1, '\t"fmt"\n')
return "".join(lines)
for idx, line in enumerate(lines):
if line.startswith("import ") and '"fmt"' not in line:
existing = line[len("import ") :].strip()
lines[idx] = "import (\n"
lines.insert(idx + 1, f"\t{existing}\n")
lines.insert(idx + 2, '\t"fmt"\n')
lines.insert(idx + 3, ")\n")
return "".join(lines)
return code
def add_python_response_print(code: str) -> str:
if re.search(r"^\s*print\(resp\)", code, re.MULTILINE):
return code
pattern = re.compile(r"^(\s*)(api_instance\.[A-Za-z_][A-Za-z0-9_]*\([^#\n]*\))(\s*)$", re.MULTILINE)
def repl(match: re.Match[str]) -> str:
indent = match.group(1)
call = match.group(2)
suffix = match.group(3)
return f"{indent}resp = {call}{suffix}\n{indent}print(resp)"
return pattern.sub(repl, code, count=1)
def add_go_response_print(code: str) -> str:
if "fmt.Println(resp)" in code:
return code
pattern = re.compile(r"^(\s*)_, err = (svc\.[A-Za-z_][A-Za-z0-9_]*\([^#\n]*\))(\s*)$", re.MULTILINE)
call_indent = ""
def repl(match: re.Match[str]) -> str:
nonlocal call_indent
call_indent = match.group(1)
return f"{match.group(1)}resp, err := {match.group(2)}{match.group(3)}"
code, count = pattern.subn(repl, code, count=1)
if not count:
return code
code = ensure_go_fmt_import(code)
api_call = re.search(
rf"(?m)^{re.escape(call_indent)}resp, err := svc\.[A-Za-z_][A-Za-z0-9_]*\([^#\n]*\)\s*$",
code,
)
if api_call:
lines = code.splitlines(keepends=True)
char_pos = 0
api_line_idx = 0
for idx, line in enumerate(lines):
next_pos = char_pos + len(line)
if char_pos <= api_call.start() < next_pos:
api_line_idx = idx
break
char_pos = next_pos
for idx in range(api_line_idx + 1, len(lines)):
if re.match(rf"^{re.escape(call_indent)}if err != nil \{{", lines[idx]):
brace_depth = 0
for end_idx in range(idx, len(lines)):
brace_depth += lines[end_idx].count("{")
brace_depth -= lines[end_idx].count("}")
if brace_depth == 0:
lines.insert(end_idx + 1, f"{call_indent}fmt.Println(resp)\n")
return "".join(lines)
break
return code
def add_java_response_print(code: str) -> str:
if "System.out.println(resp);" in code:
return code
pattern = re.compile(r"^(\s*)(api\.[A-Za-z_][A-Za-z0-9_]*\([^;\n]*\);)(\s*)$", re.MULTILINE)
def repl(match: re.Match[str]) -> str:
indent = match.group(1)
call = match.group(2)[:-1]
return f"{indent}Object resp = {call};\n{indent}System.out.println(resp);"
return pattern.sub(repl, code, count=1)
def add_php_response_print(code: str) -> str:
if "print_r($response);" in code:
return code
pattern = re.compile(r"^(\s*)(\$apiInstance->[A-Za-z_][A-Za-z0-9_]*\([^;\n]*\);)(\s*)$", re.MULTILINE)
def repl(match: re.Match[str]) -> str:
indent = match.group(1)
call = match.group(2)[:-1]
return f"{indent}$response = {call};\n{indent}print_r($response);"
return pattern.sub(repl, code, count=1)
def add_response_print(language: str, code: Any) -> Any:
if isinstance(code, dict):
return {key: add_response_print(language, value) for key, value in code.items()}
if not isinstance(code, str) or not code:
return code
lang = language.upper()
if lang == "PYTHON":
return add_python_response_print(code)
if lang == "GO":
return add_go_response_print(code)
if lang == "JAVA":
return add_java_response_print(code)
if lang == "PHP":
return add_php_response_print(code)
return code
def scrub_unusable_json_examples(value: Any) -> Any:
if isinstance(value, dict):
return {key: scrub_unusable_json_examples(item) for key, item in value.items()}
if isinstance(value, list):
return [scrub_unusable_json_examples(item) for item in value]
if isinstance(value, str):
return scrub_unusable_json_example_text(value)
return value
def scrub_unusable_json_example_text(value: str) -> str:
value = re.sub(
r"['\"]?[A-Za-z][A-Za-z0-9_]*\.\d+\.[A-Za-z0-9_]+\s*=\s*[^'\"\s&]+(?:&[A-Za-z][A-Za-z0-9_]*\.\d+\.[A-Za-z0-9_]+\s*=\s*[^'\"\s&]+)*['\"]?",
"1",
value,
)
return value
def format_code_result(
response: dict[str, Any],
language: str | None,
mocked_params: dict[str, Any] | None = None,
) -> dict[str, Any]:
result = response.get("Result") or {}
demo_sdk = result.get("DemoSdk") or {}
normalized = {str(k).upper(): v for k, v in demo_sdk.items()}
normalized = {
key: add_response_print(key, value)
for key, value in normalized.items()
}
normalized = scrub_unusable_json_examples(normalized)
if mocked_params:
normalized = {
key: annotate_mocked_code(key, value, mocked_params)
for key, value in normalized.items()
}
selected = normalize_language(language)
if selected:
return {
"available_languages": sorted(normalized.keys()),
"selected_language": selected,
"code": normalized.get(selected),
"raw_demo_sdk": normalized,
}
return {
"available_languages": sorted(normalized.keys()),
"selected_language": None,
"raw_demo_sdk": normalized,
}
def mock_notice(mocked_params: dict[str, Any]) -> str:
names = ", ".join(sorted(mocked_params))
return f"必填参数 {names} 使用了 mock 值,调用 API 前请替换为真实值。"
def snake_case(value: str) -> str:
value = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", value)
value = re.sub(r"[^A-Za-z0-9]+", "_", value)
return value.strip("_").lower()
def append_line_comment(line: str, comment: str) -> str:
newline = "\n" if line.endswith("\n") else ""
body = line[:-1] if newline else line
if comment in body:
return line
return f"{body} {comment}{newline}"
def mock_literal_candidates(mock_value: Any) -> list[str]:
if isinstance(mock_value, str):
return [mock_value]
if isinstance(mock_value, bool):
return [str(mock_value), str(mock_value).lower()]
if isinstance(mock_value, (int, float)):
return [str(mock_value)]
return []
def line_assigns_mocked_param(language: str, line: str, param_name: str) -> bool:
lang = language.upper()
if lang == "PYTHON":
return bool(re.search(rf"\b{re.escape(snake_case(param_name))}\s*=", line))
if lang == "GO":
return bool(re.search(rf"\b{re.escape(param_name)}\s*:", line))
if lang == "NODEJS":
return bool(re.search(rf"\b{re.escape(param_name)}\s*:", line))
if lang == "JAVA":
return f"set{param_name}(" in line
if lang == "PHP":
return f"set{param_name}(" in line
return False
def mocked_annotation_items(param_name: str, mock_value: Any) -> list[tuple[str, Any]]:
items: list[tuple[str, Any]] = [(param_name, mock_value)]
if isinstance(mock_value, dict):
for child_name, child_value in mock_value.items():
items.extend(mocked_annotation_items(str(child_name), child_value))
elif isinstance(mock_value, list):
for child_value in mock_value:
if isinstance(child_value, dict):
for child_name, nested_value in child_value.items():
items.extend(mocked_annotation_items(str(child_name), nested_value))
elif child_value not in (None, ""):
items.append((param_name, child_value))
return items
def annotate_mocked_assignment_line(language: str, line: str, param_name: str, mock_value: Any) -> str:
candidates = mock_literal_candidates(mock_value)
lang = language.upper()
assigns_param = line_assigns_mocked_param(language, line, param_name)
if candidates and not any(candidate in line for candidate in candidates):
return line
if not candidates and not assigns_param:
return line
if lang == "PYTHON" and assigns_param:
return append_line_comment(line, "# mock 值,调用前请替换")
if lang == "GO" and assigns_param:
return append_line_comment(line, "// mock 值,调用前请替换")
if lang == "JAVA" and assigns_param:
return append_line_comment(line, "// mock 值,调用前请替换")
if lang == "PHP" and assigns_param:
return append_line_comment(line, "// mock 值,调用前请替换")
if lang == "NODEJS" and assigns_param:
return append_line_comment(line, "// mock 值,调用前请替换")
if lang == "CURL":
return line
return line
def annotate_mocked_code(language: str, code: Any, mocked_params: dict[str, Any]) -> Any:
if isinstance(code, dict):
return {k: annotate_mocked_code(language, v, mocked_params) for k, v in code.items()}
if not isinstance(code, str) or not code:
return code
lines = code.splitlines(keepends=True)
annotation_items: list[tuple[str, Any]] = []
for param_name, mock_value in mocked_params.items():
annotation_items.extend(mocked_annotation_items(param_name, mock_value))
for idx, line in enumerate(lines):
for param_name, mock_value in annotation_items:
line = annotate_mocked_assignment_line(language, line, param_name, mock_value)
lines[idx] = line
return "".join(lines)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--query", help="Deprecated for discovery; use scripts/rg_rank.py instead.")
parser.add_argument("--service-code")
parser.add_argument("--api-version", "--version", dest="api_version")
parser.add_argument("--action")
parser.add_argument("--region")
parser.add_argument("--language")
parser.add_argument("--params-json")
parser.add_argument("--params-file")
parser.add_argument("--x-language", default="zh")
parser.add_argument("--list-candidates", action="store_true", help="List local candidates for explicit direct-mode filters.")
parser.add_argument("--refresh-swagger", action="store_true")
parser.add_argument("--output", choices=("json", "text"), default="json")
args = parser.parse_args()
if args.query and not args.action:
print_json(
{
"error": "query_discovery_disabled",
"message": "Use scripts/rg_rank.py for local API discovery, then call make_code.py with --service-code, --api-version, and --action.",
"query": args.query,
}
)
return 2
records = load_records()
params = load_params(args)
candidates = find_local_candidates(
records,
query=args.query,
service_code=args.service_code,
action=args.action,
api_version=args.api_version,
)
if args.list_candidates:
print_json({"candidates": candidates})
return 0
if not candidates:
print_json({"error": "api_not_found", "query": args.query})
return 2
if len(candidates) > 1:
top_score = record_score(candidates[0], args.query or args.action or "")
second_score = record_score(candidates[1], args.query or args.action or "")
exact_action = args.action and norm_key(candidates[0].get("action")) == args.action.lower()
inferred_service = infer_service_code_from_query(args.query, records)
top_exact_service_create = (
inferred_service
and "创建" in (args.query or "")
and norm_key(candidates[0].get("service_code")) == inferred_service.lower()
and re.sub(r"\s+", "", norm_key(candidates[0].get("name_cn")))
== f"创建{inferred_service.lower()}"
)
if not exact_action and not top_exact_service_create and second_score >= max(40, top_score - 15):
print_json({"error": "ambiguous_api", "candidates": candidates[:5]})
return 3
record = candidates[0]
swagger = fetch_swagger(
record,
x_language=args.x_language,
refresh=args.refresh_swagger,
)
payload, param_info = make_payload(record, swagger, params, args.region)
final_params, mocked_params = apply_missing_required_mocks(params, param_info)
payload["Params"] = final_params
unknown = [name for name in params if name not in param_info["known_params"]]
response = call_make_code(payload, x_language=args.x_language)
code_result = format_code_result(response, args.language, mocked_params)
output = {
"api": record,
"payload": payload,
"warnings": {
"unknown_params": unknown,
"mocked_required_params": mocked_params,
"mock_notice": mock_notice(mocked_params) if mocked_params else "",
},
**code_result,
}
if args.output == "text":
print_text(output)
else:
print_json(output)
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except Exception as exc:
print_json({"error": "exception", "message": str(exc)})
raise SystemExit(1)
#!/usr/bin/env python3
# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd.
# SPDX-License-Identifier: MIT
"""Fetch Volcengine SDK install/dependency info for an API (on demand).
Returns the per-language install command (`RunCommand`) plus package and version
from the API Explorer `sdk-info` endpoint. The result is service-level: only
`ServiceCode` and `APIVersion` matter; `APIAction` is not required.
Only call this when the user explicitly asks how to install the SDK or which
package/version to use. Do not run it during normal code generation.
"""
from __future__ import annotations
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
API_BASE = "https://api.volcengine.com/api/common"
# Map user language input to the endpoint's `Language` values.
LANG_ALIASES = {
"python": "Python",
"py": "Python",
"go": "Go",
"golang": "Go",
"java": "Java",
"php": "Php",
"node": "Node.js",
"nodejs": "Node.js",
"node.js": "Node.js",
}
def http_get_json(url: str, *, timeout: int = 20) -> dict:
headers = {
"Accept": "application/json, text/plain, */*",
"User-Agent": "volcengine-sdk-info-skill/1.0",
}
req = urllib.request.Request(url, headers=headers, method="GET")
try:
with urllib.request.urlopen(req, timeout=timeout) as resp:
return json.loads(resp.read().decode("utf-8"))
except urllib.error.HTTPError as exc:
body = exc.read().decode("utf-8", errors="replace")
raise RuntimeError(f"HTTP {exc.code} {url}: {body}") from exc
def fetch_sdk_info(service_code: str, api_version: str) -> list[dict]:
params = urllib.parse.urlencode(
{"ServiceCode": service_code, "APIVersion": api_version}
)
data = http_get_json(f"{API_BASE}/explorer/sdk-info?{params}")
result = data.get("Result") or {}
entries = result.get("SdkInfo") or []
# Keep only entries that actually carry install info (drop Curl / empty).
return [
e
for e in entries
if isinstance(e, dict) and not e.get("NoSDKInfo") and e.get("RunCommand")
]
def normalize_language(language: str | None) -> str | None:
if not language:
return None
return LANG_ALIASES.get(language.strip().lower(), language)
def format_text(entries: list[dict]) -> str:
blocks = []
for e in entries:
lines = [
f"{e.get('Language')} {e.get('SdkVersion')} "
f"({e.get('SdkPackageManagePlatform')})"
]
if e.get("SdkPackage"):
lines.append(f" package: {e['SdkPackage']}")
run = (e.get("RunCommand") or "").rstrip("\n")
indented = "\n".join(" " + ln for ln in run.splitlines())
lines.append(f" install:\n{indented}")
blocks.append("\n".join(lines))
return "\n\n".join(blocks)
def main() -> int:
parser = argparse.ArgumentParser(
description="Fetch Volcengine SDK install/dependency info for an API."
)
parser.add_argument("--service-code", required=True)
parser.add_argument(
"--api-version", "--version", dest="api_version", required=True
)
parser.add_argument(
"--language",
help="Filter to one language (e.g. go, python, java, php, nodejs).",
)
parser.add_argument("--output", choices=("text", "json"), default="text")
args = parser.parse_args()
try:
all_entries = fetch_sdk_info(args.service_code, args.api_version)
except Exception as exc: # surface a clean message to the agent
print(f"error: {exc}", file=sys.stderr)
return 1
entries = all_entries
selected = normalize_language(args.language)
if selected:
entries = [e for e in all_entries if e.get("Language") == selected]
if not entries:
avail = ", ".join(e.get("Language") for e in all_entries)
print(
f"error: no SDK info for language '{args.language}'. "
f"Available: {avail}",
file=sys.stderr,
)
return 1
if args.output == "json":
print(json.dumps(entries, ensure_ascii=False, indent=2))
else:
print(format_text(entries))
return 0
if __name__ == "__main__":
raise SystemExit(main())