SuperAPI AI Directory

volcengine-billing-and-cost-management

Office & productivity

View repository

Updated 10-27 17:06

About this skill

volcengine-billing-and-cost-management

This skill is used for cost anomaly analysis, fluctuation explanation, and root cause analysis (RCA) in FinOps scenarios. It is an orchestration-type analysis skill, but its internal tool calls follow stricter tool schema design principles:

  • First perform structured task identification
  • Then decide which analysis action to call
  • Chain multiple actions when necessary
  • Expose unified, stable, and minimized parameter semantics to the model
  • Map to the underlying OpenAPI interface through an adapter
  • All numerical conclusions come only from tool results; the model is not allowed to fabricate them
  • Finally output structured, explainable FinOps conclusions

Applicable scenarios

Use this skill when the user expresses any of the following intentions:

  • "Why did the cost go up / down"
  • "Help me do an RCA / root cause analysis"
  • "Which product, region, instance, or entity caused the anomaly"
  • "Was the anomaly caused by unit price, usage, discount, or other metrics"
  • "Help me locate the source of the cost anomaly"
  • "Help me look at the reason for the cost fluctuation of a certain customer / account / billing period"
  • "Help me explain a certain bill anomaly"

Not applicable to:

  • Pure terminology explanation
  • Pure permission issues
  • Static data queries that do not involve anomaly analysis

Runtime environment and identity

Requires Python 3.9+ and an available ve CLI in PATH, as well as the current user authentication context provided and isolated by the Host (CLI profile or environment credentials). It does not read, output, or copy AK/SK/token, and does not modify the global CLI login configuration.

Orchestration actions, script inputs, and OpenAPI Actions uniformly use QueryCostChangeDimensions、QueryCostChangeAmountComponents、QueryCostChangeDrivers,Always use --force generic invocation, with fixed billing、2022-01-01、POST and JSON Content-Type. It is not compatible with old action names or old analysis states; please create a new analysis task.--force only skips CLI metadata validation; the server still needs to publish the new interface and grant access permissions to the current identity. When the new interface is unavailable, handle it according to the tool failure path, and do not fall back to old interfaces or internal interfaces.

Each session/analysis task uses an independent directory and state-file. Initialization can receive --environment online|boe、--region、--endpoint、--profile、--timeout-seconds, and only uses the configuration provided by the Host/test environment; business context and hooks do not carry these fields. BOE must explicitly provide the endpoint. Initialization writes non-sensitive configuration to <state-file>.artifacts/openapi_config.json, and subsequent tool_command automatically follows it; do not rewrite the configuration. After switching identity, environment, or account authorization, create a new task and do not reuse the old analysis state.

For detailed configuration and response contracts, see references/api_mapping.md。

If the call returns VE_CLI_UPGRADE_REQUIRED(ve does not support --force), you must clearly prompt the user to first upgrade ve to a version that supports --force generic invocation, and then re-initiate the analysis; do not automatically retry repeatedly, remove --force , or fall back to old interfaces. Reporting only "Action not supported" cannot be directly determined as the version being too low; it is still necessary to distinguish among CLI, platform proxy, and interface release issues.

Default execution entry: run_rca_workflow.py

RCA analysis must be executed through the scripts/run_rca_workflow.py process of init / step / resume . This script is the default orchestration entry point of the skill, responsible for advancing the fixed workflow, calling analysis_state.py to complete state transitions, managing hook artifacts, validating input, and outputting the next action.

It is forbidden to bypass run_rca_workflow.py and directly manually call analysis_state.py next-step / apply-result according to the old process, or directly assemble call_openapi.py parameters.analysis_state.py remains the only state transition entry point for canonical state, but it is called by run_rca_workflow.py , not manually chained by the LLM.

Standard process:

1. 初始化:
   python3 scripts/run_rca_workflow.py init \
     --question "<用户问题>" \
     --context-json '<current_period/base_period 等业务上下文>' \
     --state-file <state.json>

2. 根据脚本输出 action 执行:
   - action=await_hook:读取 hook_request_file,按 hook_type 生成 hook_response.json,
     然后执行 resume --hook-response-file。
   - action=execute_tool:按脚本输出的 tool_command 参数数组执行 scripts/call_openapi.py,
     将工具结果写入 tool_result.json,然后执行 resume --tool-result-file。
   - action=final:输出脚本返回的 final_answer。

3. 每次 resume 后,继续按脚本返回的 action 执行,直到 action=final。

Three LLM hooks:

  • choose_task: from pending_tasks select one selected_task_id, and provide decision_reason。
  • interpret_result: interpret the tool result, output result_summary、findings、candidate_tasks、llm_decision。
  • draft_answer: after the script confirms stop_condition.final.should_stop=true , generate the final natural language answer based on findings.

Hook response is not analysis_state. The LLM can only return the lightweight JSON required by the hook schema, and must not hand-write the complete analysis_state, FSM state, or task queue. For the complete orchestrator design and hook examples, see references/rca_orchestrator_design.md。

Tool Definitions

This skill internally has 3 analysis tools:QueryCostChangeDimensions、QueryCostChangeAmountComponents、QueryCostChangeDrivers. Here only the information necessary for the model to perform Tool Choice is retained; the underlying OpenAPI request body, field mapping, and return structure details are uniformly placed in references/api_mapping.md。

General invocation principles

Model-layer unified parameters

When calling any tool, the model layer uniformly uses the following field names:

  • current_period: string, format YYYY-MM-01
  • base_period: string, format YYYY-MM-01
  • dimension: string, only used in QueryCostChangeDimensions used in
  • filters: object, filter condition, optional, used to constrain the upper-level scope
  • charge_item_code: string, only used in QueryCostChangeAmountComponents / QueryCostChangeDrivers used in

General constraints:

  • By default, analyze the currently authorized account, do not ask the user for the account ID, and do not pass account_id / AccountIDto OpenAPI. When the user specifies another account, first explain the current identity boundary; if there is no Host authorization switching capability, you cannot query on behalf of the user or silently change the query to the current account.
  • filters Only the following keys are allowed:product、instance_no、charge_item_code、project、region_code
  • The model only uses unified field names; underlying field differences are handled by the adapter or script layer

QueryCostChangeDimensions

Purpose: locate which objects the anomaly is mainly concentrated on.

Applicable questions:

  • Which product caused the increase / decrease
  • Which region is anomalous
  • Which instance is the most anomalous
  • Which objects contributed most of the fluctuation
  • Help me locate the source of the anomaly

Inapplicable questions:

  • The user is asking about changes in amount composition → do not prioritize using QueryCostChangeDimensions
  • The user is asking about usage / unit price drivers → do not prioritize using QueryCostChangeDimensions

Prerequisites:

  • Requires a billing period
  • Requires a clear localization dimension; if it is generalized RCA, by default start from dimension="product" start

QueryCostChangeAmountComponents

Purpose: analyze the amount composition changes of a certain charge_item_code .

Applicable questions:

  • Why did the payable amount increase / decrease
  • How did amount items such as original price, discounted price, refund, and voucher each change
  • What changed at the amount structure level

Prerequisites:

  • Can only be called when charge_item_code is known

Inapplicable questions:

  • The user is only asking where the anomaly is → do not use QueryCostChangeAmountComponents
  • The user is asking about usage / unit price drivers → switch to QueryCostChangeDrivers

QueryCostChangeDrivers

Purpose: analyze a certain charge_item_code change is caused by which driving factors.

Applicable questions:

  • Is it a volume issue or a unit price issue
  • Which factor is driving the increase / decrease
  • How much did usage, unit_price, and impact_factor each contribute

Preconditions:

  • Only when charge_item_code is known can it be called

Non-applicable questions:

  • The user is only asking about anomaly localization → do not use QueryCostChangeDrivers
  • The user is asking about amount composition → switch to QueryCostChangeAmountComponents

Tool Choice routing rules

This section is the core of this skill. The model does not directly schedule the next round of tools; whether to continue is determined by run_rca_workflow.py based on the canonical state outputting the next action. The model only makes narrow decisions when the script outputs a hook.

Intermediate state constraints

run_rca_workflow.py is the RCA main process orchestration entry point;analysis_state.py is the canonical analysis_state ofthe only migration entry point. The LLM is the policy decision-maker and does not directly generate/modify the complete analysis_state, nor manually chain low-level state commands.

The new version of analysis_state adopts the analysis-state-v0.3 protocol, and the core division of labor is:

  • The LLM is responsible for: responding to the hook output by run_rca_workflow.py , providing selected_task_id / decision_reason、findings / result_summary / candidate_tasks / llm_decision, as well as the final final_answer
  • The LLM is prohibited from: manually writing the complete analysis_state, deriving fsm.stateon its own, maintaining the task_queue on its own, or judging on its own to "give a restricted answer" to bypass the failure path
  • The Orchestrator is responsible for: deciding the next action, managing hook/tool artifacts, validating hook response, calling analysis_state.py, and atomically writing back the canonical state
  • The Runtime is responsible for: state structure validation,pending/current/completed/failed migration,task_key deduplication, precondition validation, hard guardrails such as max steps / no executable tasks / tool failure retries, FSM advancement, and stop condition calculation. The Runtime is the only writer of the canonical state.

Each round of state must contain top-level fields such as question、context、fsm、current_task、pending_tasks、completed_tasks、failed_tasks、findings、scheduler、progress_signals、stop_condition、dedup . For the complete JSON Schema, field descriptions, and state transition examples, see references/analysis_state.md。

During initialization, pass in the user question and context such as run_rca_workflow.py init through current_period/base_period . The Runtime will generate the initial task; when necessary business context is missing, the Runtime will generate the blocked state, clear the executable task pointer, and the Agent should ask the user to fill in the missing fields rather than continue calling tools.

Mandatory workflow (must be followed every round, driven by the action output by the orchestrator):

run_rca_workflow.py init
→ action=await_hook/choose_task
→ run_rca_workflow.py resume --hook-response-file
→ action=execute_tool
→ call_openapi.py
→ run_rca_workflow.py resume --tool-result-file
→ action=await_hook/interpret_result
→ run_rca_workflow.py resume --hook-response-file
→ [若 continue] action=await_hook/choose_task
→ [若 stop] action=await_hook/draft_answer
→ run_rca_workflow.py resume --hook-response-file
→ action=final

Failure handling rules:

  • run_rca_workflow.py init failure is a blocking error and must be retried, the user must be asked to fill in the missing context, or it must be terminated; it is not allowed to directly call call_openapi.py。
  • call_openapi.py when there is no canonical state. When a call fails, the failure result must be written to tool_result.json and enter the failure/interpretation path through run_rca_workflow.py resume --tool-result-file ; it is not allowed to skip the state transition and directly give a restricted answer or proceed to the next round.
  • run_rca_workflow.py resume failure is a blocking error and must be retried or terminated after correcting the hook response/tool result according to the error; it is not allowed to manually write state files, FSM states, or task queues.
  • Tool parameters must come from execute_tool.tool_args, and it is not allowed to bypass the orchestrator and manually assemble parameters.
  • In stop_condition.final.should_stop = false the final answer must not be given directly.

First-round selection principles

  • The initial task is generated by run_rca_workflow.py init calling runtime.
  • If the script outputs action=await_hook and hook_type=choose_task, you may only choose one hook_request_file from the pending_tasks of selected_task_id。
  • When selecting tasks, follow business priority: generalized RCA usually locates the product dimension first; for amount composition/driver factor questions, if charge_item_codeis missing, first fill in the billing items through a locating task.

Judgment principles after each round

After each tool result is obtained, the result must be written to tool_result.json and run_rca_workflow.py resume --tool-result-filemust be executed. The script then outputs the interpret_result hook; the LLM only fills in the hook response and does not modify state on its own:

  • The LLM provides a lightweight interpretation:result_summary、findings、candidate_tasks、progress_signals、llm_decision
  • Runtime automatically completes:current_task → completed_tasks/failed_tasks、findings merge,pending_tasks update,fsm.state advance,stop_condition calculation

If the finding indicates that the main billing item has been located, charge_item_code must be written to finding.scope.charge_item_code, and must not only be written in the summary text; Runtime derives progress_signals.has_primary_charge_itemonly based on the structured scope, and will not extract billing items from a natural language summary.

Runtime then updates stop_condition.runtime_guardrail and stop_condition.final. Continue only when the script outputs action=execute_tool or action=await_hook again; when the script outputs action=final , output the conclusion or explain the blocking reason based on the final_answer returned by the script.

Precondition rules

  • QueryCostChangeAmountComponents and QueryCostChangeDrivers can only be called when charge_item_code is known
  • If charge_item_codeis missing, it must first be filled in through QueryCostChangeDimensions Fill in
  • When the user provides only a month and does not specify a year, use the current year by default; when there is clear historical context, use that year.
  • If the billing period is missing, ask the user; handle credential or authorization failures according to OpenAPI errors, and adding an account ID cannot fix authentication.
  • If the initialization state has entered blockeddue to missing necessary context, you must ask for the missing fields based on stop_condition.final.reason , and must not call call_openapi.py
  • It is not allowed to skip preconditions and directly call explanatory tools
  • Tool parameters are synthesized by analysis_state.context + analysis_state.current_task.scope , and the model must not bypass the state object to temporarily assemble parameters from natural language context

Runtime files and sensitive information

  • state-file and its .artifacts directory store business state, hook requests, tool parameters/results, final replies, and non-sensitive OpenAPI configuration, and are used to advance the analysis process across commands.
  • Sensitive information such as Authorization, AK, SK, token, JWT, cookie, and API key must not be written to runtime files or console output.

Unified OpenAPI calls

All underlying analysis actions uniformly execute call_openapi.py through ve billing <Action> --force to call OpenAPI; the model does not directly assemble underlying HTTP requests or hand-write OpenAPI request bodies. Script inputs, action in the workflow, and gateway Actions all use the three new names, with no old-name mapping.

Execution entry principles

  • run_rca_workflow.py is the default orchestration entry for RCA analysis, and the Agent must advance according to the action it outputs
  • call_openapi.py is the execution entry for underlying OpenAPI analysis actions, and can only be used after run_rca_workflow.py outputs action=execute_tool according to the script-provided tool_command Call
  • analysis_state.py is the canonical analysis_state initialization, task selection, tool parameter construction, and state transitionsole authoritative entry point(not an auxiliary entry point), but is called by run_rca_workflow.py , not manually chained by the LLM
  • Standard execution chain:run_rca_workflow.py init → handle by action await_hook / execute_tool / final → run_rca_workflow.py resume → loop until action=final
  • The model is responsible for:
    • In the choose_task hook, select pending_tasks from selected_task_id, and explain decision_reason
    • In the interpret_result hook, interpret tool results and generate findings / candidate_tasks / llm_decision
    • In the draft_answer hook, generate the final answer
    • Do not directly hand-write the underlying OpenAPI request body; under the regular chain, do not directly assemble call_openapi.py 's model_args, but instead use run_rca_workflow.py output execute_tool.tool_args
  • call_openapi.py is responsible for:
    • Validate Action and key prerequisite parameters
    • When directly calling QueryCostChangeDimensions , validate dimension can only be product、charge_item_code、instance_no、region_code、project
    • Execute the adapter mapping from model-layer parameters to the OpenAPI request body
    • Handle underlying field naming differences across different Actions and fixed Metric
    • Initiate the OpenAPI call and return the result
  • Blocking prerequisites and task validity checks must be completed by indirectly calling run_rca_workflow.py through analysis_state.py next-step .
  • AdapterError is a script parameter error and is returned as structured failure JSON; the regular chain should use run_rca_workflow.py output execute_tool.tool_args, with parameter construction and prerequisite validation completed indirectly by the orchestrator.
  • The model is not responsible for:
    • Handling underlying field naming differences
    • Assembling the OpenAPI request body
    • Deciding fixed Metric values
    • Supporting underlying payload structures for different Actions

Call constraints

  • Must be called through the script; do not directly hand-write curl
  • Use a tool that can execute local commands to run tool_command; parameters must remain independent and be correctly quoted; do not treat JSON as shell code.
  • For Action mapping, adapter rules, request body format, field mapping, and return structure, see references/api_mapping.md

Output specification

The final answer should be generated based on the script return result, usingconclusion first, then elaborationexpression style, prioritizing business explanations users can directly understand, rather than raw fields or JSON.

Output principles

  • First use 1–2 sentences to state the overall conclusion: whether costs rose or fell, and mainly by what object or factor they were driven
  • Then expand key evidence as needed, possibly combining short paragraphs and tables
  • The narrative part should highlight causality, not merely list numbers
  • Tables should show only key data, not pile up underlying fields
  • Numeric values should uniformly retain two decimal places, and amounts should use thousands separators
  • If anomalies are highly concentrated, show only Top1 and explain that concentration is high
  • If the current results are insufficient to support a clear conclusion, directly state that the signal is insufficient or prerequisites are missing; do not fabricate reasons

Expression requirements

  • Express for business users, prioritizing the explanation of "why"
  • Do not directly paste raw JSON
  • Do not expose underlying OpenAPI field names as the main body of the text
  • In scenarios such as amount composition, attribution paths, and factor decomposition, tables may be selectively displayed as needed for the question
  • At the end, 1–2 directions for further follow-up questions may be added

Relationship with api_mapping.md relationship with

Implementation details such as the field extraction method in the returned structure, TopN selection rules, amount composition sorting rules, and factor aggregation rules are uniformly described in references/api_mapping.md。

Constraints

  1. Directly writing SQL to query data is prohibited, and all data must be obtained through scripts
  2. Fabricating data is prohibited, and all numerical conclusions must come from the JSON output by the scripts
  3. If script execution fails, you must explain which step it got stuck at and what the error message is, and distinguish based on the error among credential expiration, no permission, parameter error, timeout, or service exception; failure must not be interpreted as zero cost
  4. When key prerequisites are missing (such as billing period,charge_item_code), you must first ask the user or fill them in through prerequisite actions, and must not skip the conditions and directly output explanatory conclusions
  5. If the user asks a follow-up question at a finer granularity (such as "analyze by region"), you should continue to follow the Tool Choice and prerequisite rules and select the appropriate next-round analysis action
  6. The final answer is expressed for business users and does not output underlying script commands, OpenAPI request bodies, or implementation-layer field mappings as the main body of the text