Skip to main content

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_id and grouped-usage depend 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.oa is only for displaying verified OA name, employee ID, and department context; it does not grant department-level permissions. subject does not contain an internal user_id.
  • Query targets are determined solely by authorization.targets.*.mode/resource_types/actions; mode=none, missing actions, or allowed=false all mean the target is not callable.
  • --include / --group-by only uses the allowed_includes / allowed_group_by returned by the corresponding action.
  • Relay parameters are read from query_options.relay; other actions are executed only according to the effective contract returned by authorization.targets.*.actions or authorization.actions.
  • Do not probe permissions by inducing 403 responses; 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."

turing-cli operations search [flags]

Fuzzy-search for users, departments, and clients by keyword. Returns only identity fields, not costs.

FlagDefaultDescription
-q, --q QUERYemptyFuzzy keyword; when empty, lists users visible to the current caller's permissions
--start DATEFirst day of current monthStart date, format YYYY-MM-DD, interpreted in Beijing time
--end DATETodayEnd date, format YYYY-MM-DD, inclusive
--limit N50Page size, valid range 1–500
--offset N0Pagination offset
--include-adminfalseInclude admin service accounts
--include-relayfalseInclude Relay only for person-dimension activity probing; does not change identity search results
-h, --helpShow command help

Search dimensions:

DimensionDescription
usernameUsername
emailEmail address
realnameFull name
employee_idEmployee ID
oa_pathFull 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
clientApplication / 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.

FlagRequiredDefaultDescription
--type TYPEYesemptyQuery subject; see the --type table below
--value VALUEConditionally requiredemptyResource value; exact match, case-sensitive; not required for platform
--start DATENoFirst day of current monthStart date, format YYYY-MM-DD, interpreted in Beijing time
--end DATENoTodayEnd date, format YYYY-MM-DD, inclusive
--include LISTNoemptyData breakdowns, comma-separated; typically only summary is returned; conditional defaults are determined by capabilities
--include-relayNofalseInclude Relay in regular queries; use only when allowed by capabilities
--allNofalseReturn all permitted standard breakdowns; does not implicitly include Relay
-h, --helpNoShow 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 Familytypevalue
personusernameUsername, e.g., san.zhang
personemailEmail address
personrealnameFull name
personemployee_idEmployee ID
orgoa_pathFull department path, any depth; department hits from search can be used directly; availability subject to capabilities
orgldap_1 / ldap_2 / ldap_3Legacy hierarchical department name; same-name departments are merged across subtrees; new queries should use oa_path
clientclientClient name, e.g., co-patent
platformplatformNo --value needed; authorized platform regular usage, excludes Relay by default, not unconditionally all clients
API Keyapi_key_idNon-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:

includeDescriptionCompatibility
by_clientBreakdown by client; under platform, shows client rankingsperson / org / client / platform
by_dayBreakdown by date in Beijing timeUniversal, including API Key scope
by_userBreakdown by userorg / client only; person is inherently 1 user; not returned for platform
by_apikeyBreakdown 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 keysperson / client only (must target a single subject); not returned for org / platform / API Key
by_serviceBreakdown by model or serviceUniversal, including API Key scope
by_regionBreakdown by region / environmentclient / platform only
by_channelCoarse billing-pool breakdown (preferred): portal vs api_key (further split into turingclaw / aicoding / other); fixed 4 rows, total always equals summary.bill_usdperson / org / client / platform
by_billing_poolCost-source breakdown; availability and conditional defaults are determined by capabilities. The relay cost pool is not the same dimension as the Relay client query scopeCapability-controlled
by_toolDeprecated compatibility shim: mirrors by_channel for portal / turingclaw / aicoding rows; other group is labeled unclassified; new usage should always use by_channelperson / org / client / platform
allReturn all permitted standard breakdowns; does not implicitly include RelayStill 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:

MetricMeaning
bill_usdCost in USD (formerly total / total_usd, compatibility aliases removed after 2026-08-05)
request_countNumber of requests
user_countDeduplicated active user count; null for platform summary
tokensTotal tokens
input_tokens / output_tokensInput / 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.

FlagRequiredDefaultDescription
--type TYPEYesemptyQuery subject; same as dashboards, including api_key_id
--value VALUEConditionally requiredemptyRequired for all subjects except platform; exact match, case-sensitive
--group-by PAIRYesemptyTwo-dimensional combination; see table below; only one pair can be selected per call
--start DATENoFirst of monthStart date, format YYYY-MM-DD, interpreted in Beijing time; when only --end is provided, defaults to the first day of that month
--end DATENoTodayEnd date, format YYYY-MM-DD, inclusive
--limit NNo100Page size, valid range 1–1000; omitting or passing 0 causes the CLI to omit the parameter and use the server default
--offset NNo0Pagination offset, must be ≥ 0; omitting or passing 0 causes the CLI to omit the parameter and use the server default
--include-relayNofalseInclude Relay; excluded by default; exact Relay targets are forced in by the Backend
-h, --helpNoShow 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-byApplicable Query SubjectsQuestion Answered
service,dayperson / org / client / platform / API KeyHow does each service's usage change over time for a subject
client,serviceplatformWhich services does each client use
region,serviceclient / platformWhich 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:

FieldMeaning
dimensionThe query subject for this request, including resource_type / resource_value and optional display information
group_byNormalized two-dimensional combination array
totalTotal number of matched grouped rows before pagination, not a cost figure
limit / offsetThe pagination values actually applied and echoed back by the server
rowsGrouped rows for the current page; each row contains dimensions and usage metrics
org_filterOptional 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 that by_channel / by_billing_pool only 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:

LocationIndicatorMeaning
search response top leveltruncated: trueThe underlying scan hit its ceiling; total is a lower bound — re-query with a more specific keyword
dashboard responseby_apikey_truncated: trueby_apikey shows only the top 100 rows by cost, not all keys
org subjectsorg_filter.truncated / os_users_coveredRoster truncated / OpenSearch breakdown coverage insufficient
grouped-usagetotal vs limit / offsettotal 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:

Combinationdimensions Fields
service,dayservice, day; day is YYYY-MM-DD in Beijing time
client,serviceclient, service, optional client_display_name
region,serviceservice, 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 --typeby_clientby_dayby_userby_apikeyby_serviceby_regionby_channelby_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

FieldMeaning
dimension.resource_type / dimension.resource_valueThe account dimension queried
summary.bill_usdTotal cost in USD; authoritative cost is based on backend billing data
summary.request_countNumber of requests
summary.tokensTotal tokens
summary.input_tokens / summary.output_tokensInput / output tokens
summary.user_countDeduplicated active user count; null for platform
usage_scoperequested / included / forced for the Relay scope of this request; included does not prove non-zero Relay usage
org_filterDepartment 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_apikeyBreakdown 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_serviceBreakdown by service / model
by_regionBreakdown by region + environment
by_channelCoarse 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_poolCapability-controlled direct / relay cost-source breakdown; relay here is not equal to the Relay client query scope
by_toolDeprecated compatibility shim: mirrors by_channel for portal / turingclaw / aicoding rows
by_tool_scopeTag source scope for by_tool; needed alongside unclassified when querying cross-region client / platform
unclassifiedTraffic 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

ErrorAction
HTTP 400Check 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 422Check date format and pagination range; limit for grouped usage must be in the range 1–1000
HTTP 403Stop the current target, re-read capabilities, do not probe by trying different dimensions repeatedly; retain the trace from stderr
HTTP 404Resource does not exist; for regular subjects, use operations search first; for specific keys, obtain the ID from by_apikey within the visible scope
HTTP 503Backend or an expected regional data source is unavailable; grouped usage does not return partial results — retry later and retain the trace
connection refused / timeoutCheck network, proxy configuration, or backend service status