Operations
turing-cli operations queries usage, costs, tokens, models, and request details on the Turing Platform/Core.
In agentic workflows, you can use the commands on this page alongside the Turing Operations skill on SkillHub. If you also need to read billing statements, spreadsheets, PDFs, or PowerPoint files first, pair it with the Documents skill and call turing-cli documents convert. You can also configure your own skills according to your agent or IDE conventions.
Query models fall into two categories. Before making any calls, use capabilities to read the current caller's effective permissions and business contract:
dashboards: query subject (--type, pick 1) × individual breakdowns (--include, multiple allowed) + metrics
grouped-usage: query subject (--type, pick 1) × two-dimensional combination (--group-by, pick 1 pair) + metrics
Portal / CoWork (turing-claw, openclaw) are not --type values and are not query filter conditions; they are groups within the by_channel response. To answer "how much did Portal spend / how much did API Keys spend," use --include by_channel. For example, to get a specific person's Portal / CoWork (turing-claw) usage, first query that person's total usage with --type username --value X, then read the corresponding group from by_channel.
To drill down into a specific API Key, typically first obtain the non-sensitive api_key_id (ak_...) from a person's or client's by_apikey result, then query that key's by_service or by_day using --type api_key_id --value ak_xxx. The default quota aggregate bucket has no single ID; when a specific default key is needed, obtain its ak_... ID from the key management capability. Do not pass sk-... secret keys to Operations commands.
The newly added
api_key_idandgrouped-usagedepend on corresponding Backend capabilities. At release, the Backend must be deployed before publishing the new CLI and this documentation. This document does not declare a minimum CLI version for features not yet finalized.
Query Workflow
For each Operations task, an agent first reads the current caller's effective contract, then plans subsequent requests:
operations capabilities -> confirm identity, effective permissions, available includes/group-bys, and Relay scope
operations search -> find the exact type/value within the authorized scope
operations dashboards -> query summary or required by_* breakdowns
operations grouped-usage -> query permitted two-dimensional combinations
API Keys are not searched via operations search. First query the owner's or client's by_apikey, read the api_key_id from the specific key row, then drill down by key.
operations capabilities
turing-cli operations capabilities
# equivalent alias
turing-cli operations my-capabilities
This command does not query usage. Instead, it returns a self-describing contract for the current caller, appended with the local CLI's command contract. Agents must call this once at the start of each task and comply with the following:
- "Me / my" uses only
subject.preferred_self_target; do not infer username from email prefix or display name. subject.oais only for displaying verified OA name, employee ID, and department context; it does not grant department-level permissions.subjectdoes not contain an internaluser_id.- Query targets are determined solely by
authorization.targets.*.mode/resource_types/actions;mode=none, missing actions, orallowed=falseall mean the target is not callable. --include/--group-byonly uses theallowed_includes/allowed_group_byreturned by the corresponding action.- Relay parameters are read from
query_options.relay; other actions are executed only according to the effective contract returned byauthorization.targets.*.actionsorauthorization.actions. - Do not probe permissions by inducing
403responses; re-read capabilities after permission changes.
Only when the Backend explicitly returns 404 / 501 for capabilities may an older client narrow-degrade to using a username/email that the caller has explicitly provided or previously verified, as well as self-owned api_key_id values discovered from the caller's own results. 401 / 403, 5xx, network errors, unknown schema, or a local CLI that does not recognize the capabilities command must not be treated as degradable or as "possibly authorized."
operations search
turing-cli operations search [flags]
Fuzzy-search for users, departments, and clients by keyword. Returns only identity fields, not costs.
| Flag | Default | Description |
|---|---|---|
-q, --q QUERY | empty | Fuzzy keyword; when empty, lists users visible to the current caller's permissions |
--start DATE | First day of current month | Start date, format YYYY-MM-DD, interpreted in Beijing time |
--end DATE | Today | End date, format YYYY-MM-DD, inclusive |
--limit N | 50 | Page size, valid range 1–500 |
--offset N | 0 | Pagination offset |
--include-admin | false | Include admin service accounts |
--include-relay | false | Include Relay only for person-dimension activity probing; does not change identity search results |
-h, --help | Show command help |
Search dimensions:
| Dimension | Description |
|---|---|
username | Username |
email | Email address |
realname | Full name |
employee_id | Employee ID |
oa_path | Full department path (any depth, e.g., 鸿鹄实验室/云与物联技术中心/AI应用开发部); the path field provides ordered components; departments with the same name are distinguished by path; availability subject to capabilities |
client | Application / client / billing tenant |
Examples:
turing-cli operations search -q zhang
turing-cli operations search -q 鸿鹄 --limit 100
turing-cli operations search --start 2026-05-01 --end 2026-05-27 -q san.zhang
has_usage_in_window reflects a real activity probe only when a person-dimension result is matched. Department and client matches always return false, meaning "not probed / unknown" — this does not indicate zero usage. Continue with dashboards to query actual costs.
operations dashboards
turing-cli operations dashboards --type TYPE --value VALUE [flags]
Query usage, costs, and breakdown details for a precise type/value. Returns only summary by default; use --include or --all to request by_* breakdowns.
| Flag | Required | Default | Description |
|---|---|---|---|
--type TYPE | Yes | empty | Query subject; see the --type table below |
--value VALUE | Conditionally required | empty | Resource value; exact match, case-sensitive; not required for platform |
--start DATE | No | First day of current month | Start date, format YYYY-MM-DD, interpreted in Beijing time |
--end DATE | No | Today | End date, format YYYY-MM-DD, inclusive |
--include LIST | No | empty | Data breakdowns, comma-separated; typically only summary is returned; conditional defaults are determined by capabilities |
--include-relay | No | false | Include Relay in regular queries; use only when allowed by capabilities |
--all | No | false | Return all permitted standard breakdowns; does not implicitly include Relay |
-h, --help | No | Show command help |
When --include is completely omitted, the window does not exceed 366 days, and the capability allows it, the platform may return by_billing_pool per default_includes. Callers must not hardcode this conditional default as a permanent rule.
Query Subject --type
--type specifies "who to query" — only one can be selected per call. Valid values are determined by the CLI's validResourceTypes:
| Subject Family | type | value |
|---|---|---|
| person | username | Username, e.g., san.zhang |
| person | email | Email address |
| person | realname | Full name |
| person | employee_id | Employee ID |
| org | oa_path | Full department path, any depth; department hits from search can be used directly; availability subject to capabilities |
| org | ldap_1 / ldap_2 / ldap_3 | Legacy hierarchical department name; same-name departments are merged across subtrees; new queries should use oa_path |
| client | client | Client name, e.g., co-patent |
| platform | platform | No --value needed; authorized platform regular usage, excludes Relay by default, not unconditionally all clients |
| API Key | api_key_id | Non-sensitive key ID, e.g., ak_xxx; do not pass sk-... secret keys |
The api_key_id scope targets a specific key and currently supports by_service and by_day. Availability is subject to the API Key target grant in capabilities; knowing an api_key_id alone does not bypass backend authorization.
Data Breakdowns --include
--include specifies "how to break down the data" — multiple values can be selected, comma-separated:
| include | Description | Compatibility |
|---|---|---|
by_client | Breakdown by client; under platform, shows client rankings | person / org / client / platform |
by_day | Breakdown by date in Beijing time | Universal, including API Key scope |
by_user | Breakdown by user | org / client only; person is inherently 1 user; not returned for platform |
by_apikey | Breakdown by API Key; each row includes a nullable api_key_id; default quota is still aggregated as (default), custom keys by name (unnamed shown as (unnamed)); only shows non-deleted keys | person / client only (must target a single subject); not returned for org / platform / API Key |
by_service | Breakdown by model or service | Universal, including API Key scope |
by_region | Breakdown by region / environment | client / platform only |
by_channel | Coarse billing-pool breakdown (preferred): portal vs api_key (further split into turingclaw / aicoding / other); fixed 4 rows, total always equals summary.bill_usd | person / org / client / platform |
by_billing_pool | Cost-source breakdown; availability and conditional defaults are determined by capabilities. The relay cost pool is not the same dimension as the Relay client query scope | Capability-controlled |
by_tool | Deprecated compatibility shim: mirrors by_channel for portal / turingclaw / aicoding rows; other group is labeled unclassified; new usage should always use by_channel | person / org / client / platform |
all | Return all permitted standard breakdowns; does not implicitly include Relay | Still subject to capability and dimension compatibility constraints |
description / display_name appear only in the client dimension or in by_client rows.
Metrics
summary always returns these metrics; each breakdown row returns the corresponding fields per the API schema:
| Metric | Meaning |
|---|---|
bill_usd | Cost in USD (formerly total / total_usd, compatibility aliases removed after 2026-08-05) |
request_count | Number of requests |
user_count | Deduplicated active user count; null for platform summary |
tokens | Total tokens |
input_tokens / output_tokens | Input / output tokens |
Authoritative cost, request count, and token metrics are aggregated across cn_live, cn_test, eu_live, and sg_live for all query subjects. by_region and region,service are limited to client / platform — this is a scope restriction on region breakdowns, not an indication that totals for persons, orgs, or API Keys are counted only in the China live environment.
Common Queries
Personal totals with breakdown by billing pool, model, and client. Portal / API Key costs are read from by_channel — they are not separate filter conditions:
turing-cli operations dashboards \
--type username \
--value san.zhang \
--include by_channel,by_service,by_client
List API Keys belonging to a person:
turing-cli operations dashboards \
--type username \
--value san.zhang \
--include by_apikey
Each row in by_apikey includes a nullable api_key_id; when by_apikey_truncated=true, only the top 100 rows by cost are shown. Individually identifiable keys return a non-sensitive ak_... ID, which can be used to drill down into that key's model and date breakdowns:
turing-cli operations dashboards \
--type api_key_id \
--value ak_xxx \
--include by_service,by_day
name="(default)" still represents the aggregate bucket for multiple default-quota keys, with api_key_id set to null; this aggregate row itself cannot be used to drill down into a specific key. If you have obtained the explicit ak_... ID of a specific default key through the key management capability, you can still query directly by that ID. name="(unnamed)" simply means the key has no display name; if the row has an api_key_id, it can still be drilled into by ID.
Client totals with breakdown by region, model, and user:
turing-cli operations dashboards \
--type client \
--value co-patent \
--include by_region,by_service,by_user \
--start 2026-05-01 \
--end 2026-05-31
Query a person by email:
turing-cli operations dashboards \
--type email \
--value san.zhang@tcl.com
Department dimension (use the full path returned from a department hit in search):
turing-cli operations dashboards \
--type oa_path \
--value "鸿鹄实验室/云与物联技术中心/AI 算法平台部" \
--start 2026-05-01 \
--end 2026-05-27
Platform total plus client rankings:
turing-cli operations dashboards --type platform --include by_client
Relay Query Scope and usage_scope
Person-dimension activity probing in search, dashboards, and grouped-usage exclude Relay costs, requests, tokens, and user counts by default. Pass --include-relay only when the user explicitly requests it and query_options.relay.allowed=true in capabilities:
turing-cli operations dashboards --type platform --include-relay
turing-cli operations grouped-usage \
--type platform \
--group-by client,service \
--include-relay
The CLI flag is --include-relay, corresponding to the Backend parameter include_relay=true. When querying a Relay client or an api_key_id belonging to Relay precisely, the Backend will force inclusion.
Every response containing a usage scope should be checked:
{
"usage_scope": {
"relay": {
"client": "efficiency-center",
"requested": false,
"included": false,
"forced": false
}
}
}
requested: Whether the caller explicitly requested Relay inclusion.included: The final effective query scope after applying defaults and forced rules; does not imply non-zero Relay usage.forced: Whether the Backend forced inclusion because the target is a specific Relay client or API Key.
The user-facing name is "Relay"; efficiency-center is the technical client identifier in the current response. by_billing_pool.relay is a subscription cost pool — it is a different business dimension from the Relay client scope described above. When an older response lacks usage_scope, it only means the scope is not self-described; do not infer scope on your own.
operations grouped-usage
turing-cli operations grouped-usage --type TYPE --group-by PAIR [flags]
Returns two-dimensional grouped results within an authorized query subject. Unlike dashboards --include, which returns multiple independent one-dimensional lists, each row in grouped-usage — for example with service,day — simultaneously represents a service's metrics on a specific day.
| Flag | Required | Default | Description |
|---|---|---|---|
--type TYPE | Yes | empty | Query subject; same as dashboards, including api_key_id |
--value VALUE | Conditionally required | empty | Required for all subjects except platform; exact match, case-sensitive |
--group-by PAIR | Yes | empty | Two-dimensional combination; see table below; only one pair can be selected per call |
--start DATE | No | First of month | Start date, format YYYY-MM-DD, interpreted in Beijing time; when only --end is provided, defaults to the first day of that month |
--end DATE | No | Today | End date, format YYYY-MM-DD, inclusive |
--limit N | No | 100 | Page size, valid range 1–1000; omitting or passing 0 causes the CLI to omit the parameter and use the server default |
--offset N | No | 0 | Pagination offset, must be ≥ 0; omitting or passing 0 causes the CLI to omit the parameter and use the server default |
--include-relay | No | false | Include Relay; excluded by default; exact Relay targets are forced in by the Backend |
-h, --help | No | Show command help |
Both --start and --end are inclusive. After the server fills in defaults, the grouped usage query window is at most 366 days; exceeding this limit returns HTTP 400.
The initial version strictly supports the following combinations:
--group-by | Applicable Query Subjects | Question Answered |
|---|---|---|
service,day | person / org / client / platform / API Key | How does each service's usage change over time for a subject |
client,service | platform | Which services does each client use |
region,service | client / platform | Which services are used in each region and environment |
Reversed input of the above combinations is also accepted; the CLI normalizes to the order shown in the table (e.g., day,service is converted to service,day). Other combinations and additional dimensions are rejected before the request is made. User × Service is not currently supported; to analyze one person, use dashboards --include by_service for that person; for a specific key, use dashboards --include by_service for that key.
View a key's service daily trend:
turing-cli operations grouped-usage \
--type api_key_id \
--value ak_xxx \
--group-by service,day \
--start 2026-07-01 \
--end 2026-07-14
View platform-wide Client × Service:
turing-cli operations grouped-usage \
--type platform \
--group-by client,service \
--limit 100
View a client's Region × Service:
turing-cli operations grouped-usage \
--type client \
--value co-patent \
--group-by region,service \
--limit 100
The response is paginated JSON. total is the number of matched grouped rows before pagination, not a cost figure; limit / offset are the pagination values used for this request. Each row's metrics are at the row's top level; dimension values are under dimensions:
{
"dimension": {
"resource_type": "client",
"resource_value": "co-patent"
},
"group_by": ["region", "service"],
"total": 1,
"limit": 100,
"offset": 0,
"rows": [
{
"dimensions": {
"service": "turing/gpt-5.5",
"region": {
"code": "cn-north-1",
"environment": "live",
"label": "中国正式"
}
},
"bill_usd": 12.5,
"request_count": 100,
"tokens": 60000,
"input_tokens": 50000,
"output_tokens": 10000
}
]
}
Top-level fields:
| Field | Meaning |
|---|---|
dimension | The query subject for this request, including resource_type / resource_value and optional display information |
group_by | Normalized two-dimensional combination array |
total | Total number of matched grouped rows before pagination, not a cost figure |
limit / offset | The pagination values actually applied and echoed back by the server |
rows | Grouped rows for the current page; each row contains dimensions and usage metrics |
org_filter | Optional department roster diagnostic returned only for org subjects (oa_path and legacy ldap_1 / ldap_2 / ldap_3); omitted for other subjects |
Org subjects use the same cap of up to 20,000 users as dashboards. The semantics of org_filter are:
{
"org_filter": {
"matched_users": 20000,
"truncated": true,
"truncation_cap": 20000
}
}
matched_users: The number of usernames actually included in the aggregation for this request.truncated: Whether the department roster was truncated due to exceeding the cap.truncation_cap: The cap applied when truncation occurred; omitted when not truncated.os_users_covered: Appears when the department size exceeds the OpenSearch limit; indicates thatby_channel/by_billing_poolonly covers this many users (cost totals still cover the full roster).
When truncated=true, results cover at most 20,000 resolved users and must not be treated as the department's complete usage.
Partial-Return Indicators
When a list is truncated by a limit, the response states this explicitly — it never silently returns partial data:
| Location | Indicator | Meaning |
|---|---|---|
| search response top level | truncated: true | The underlying scan hit its ceiling; total is a lower bound — re-query with a more specific keyword |
| dashboard response | by_apikey_truncated: true | by_apikey shows only the top 100 rows by cost, not all keys |
| org subjects | org_filter.truncated / os_users_covered | Roster truncated / OpenSearch breakdown coverage insufficient |
| grouped-usage | total vs limit / offset | total is the pre-pagination row count; if it exceeds the returned row count, more pages exist |
TypeScript response reference:
interface GroupedUsageRegion {
code: string;
environment: string;
label: string;
}
interface GroupedUsageDimensions {
service?: string;
day?: string; // YYYY-MM-DD, Beijing time
client?: string;
client_display_name?: string;
region?: GroupedUsageRegion;
}
interface GroupedUsageRow {
dimensions: GroupedUsageDimensions;
bill_usd: number;
request_count: number;
tokens: number;
input_tokens: number;
output_tokens: number;
}
interface GroupedUsageResponse {
dimension: {
resource_type: string;
resource_value: string;
display_name?: string;
description?: string;
};
group_by:
| ["service", "day"]
| ["client", "service"]
| ["region", "service"];
total: number;
limit: number;
offset: number;
rows: GroupedUsageRow[];
org_filter?: {
matched_users: number;
truncated: boolean;
truncation_cap?: number;
};
}
dimensions returns only the fields relevant to the current combination:
| Combination | dimensions Fields |
|---|---|
service,day | service, day; day is YYYY-MM-DD in Beijing time |
client,service | client, service, optional client_display_name |
region,service | service, region; region is a {code, environment, label} object; China live and test environments are distinct grouping values |
Grouped usage follows a completeness-first strategy. If any expected regional data source among cn_live, cn_test, eu_live, or sg_live fails, the entire request returns HTTP 503 — it will never silently return a 200 response missing data from some regions.
Compatibility Matrix
The table below shows structural compatibility for standard one-dimensional breakdowns. The actual permitted items are always determined by the allowed_includes returned by capabilities for the target action.
Query Subject --type | by_client | by_day | by_user | by_apikey | by_service | by_region | by_channel | by_tool |
|---|---|---|---|---|---|---|---|---|
person: username / email / realname / employee_id | ✓ | ✓ | - | ✓ | ✓ | - | ✓ | ✓ |
org: oa_path (legacy ldap_1 / ldap_2 / ldap_3 same) | ✓ | ✓ | ✓ | - | ✓ | - | ✓ | ✓ |
client: client | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
platform: platform | ✓ | ✓ | - | - | ✓ | ✓ | ✓ | ✓ |
API Key: api_key_id | - | ✓ | - | - | ✓ | - | - | - |
For API Key scope, explicitly use --include by_service,by_day; do not use --all to request incompatible breakdowns.
by_billing_pool is a capability-controlled cost-source breakdown; do not infer permissions from the table above.
Output Fields
| Field | Meaning |
|---|---|
dimension.resource_type / dimension.resource_value | The account dimension queried |
summary.bill_usd | Total cost in USD; authoritative cost is based on backend billing data |
summary.request_count | Number of requests |
summary.tokens | Total tokens |
summary.input_tokens / summary.output_tokens | Input / output tokens |
summary.user_count | Deduplicated active user count; null for platform |
usage_scope | requested / included / forced for the Relay scope of this request; included does not prove non-zero Relay usage |
org_filter | Department roster diagnostic for org subjects: matched_users, truncated, and optional truncation_cap; semantics are consistent between dashboard and grouped usage; roster cap is 20,000 users |
by_apikey | Breakdown by API Key (person / client only); each row includes a nullable api_key_id, name (custom key name / (default) / (unnamed)), and usage metrics; the (default) aggregate bucket has ID null; contains only non-deleted keys |
by_service | Breakdown by service / model |
by_region | Breakdown by region + environment |
by_channel | Coarse billing-pool breakdown: portal row (Portal app pool + legacy Portal web traffic) has group set to null; api_key rows are split by group into turingclaw / aicoding (coding tool tags include CoWork, and coding agents identified by TCoder / Cline / similar UA) / other (remaining traffic including openclaw, Office plugins, image/video generation, and direct API calls); the 4 rows always sum to summary.bill_usd; cross-region differences are counted in other |
by_billing_pool | Capability-controlled direct / relay cost-source breakdown; relay here is not equal to the Relay client query scope |
by_tool | Deprecated compatibility shim: mirrors by_channel for portal / turingclaw / aicoding rows |
by_tool_scope | Tag source scope for by_tool; needed alongside unclassified when querying cross-region client / platform |
unclassified | Traffic rendered into the legacy field from the by_channel other group: untagged traffic, openclaw, Office plugins, image/video generation, and direct API calls (including sk- API Key traffic through the portal client) |
Self-Describing Permissions
Callers do not need to know or infer roles and internal authorization rules. First call turing-cli operations capabilities, then strictly plan queries based on the returned authorization.targets, target actions, allowed_includes, and allowed_group_by. Do not call targets or actions not present in the response; OA information is only for interpreting the current identity and does not expand data access.
Whether by_billing_pool is returned conditionally by default when --include is fully omitted for platform is also determined by default_includes.by_billing_pool in the current caller's capabilities.
The API Key scope is authorized based on key ownership first; knowing an ak_... ID alone does not imply view permission. Unauthorized queries return HTTP 403. Every call outputs [trace] trace_xxx on stderr; stdout remains pure JSON.
Troubleshooting
| Error | Action |
|---|---|
HTTP 400 | Check date order and window length, --include, --group-by, and whether the combination is compatible with the query subject; grouped usage supports at most 366 days |
HTTP 422 | Check date format and pagination range; limit for grouped usage must be in the range 1–1000 |
HTTP 403 | Stop the current target, re-read capabilities, do not probe by trying different dimensions repeatedly; retain the trace from stderr |
HTTP 404 | Resource does not exist; for regular subjects, use operations search first; for specific keys, obtain the ID from by_apikey within the visible scope |
HTTP 503 | Backend or an expected regional data source is unavailable; grouped usage does not return partial results — retry later and retain the trace |
connection refused / timeout | Check network, proxy configuration, or backend service status |