Skip to main content

Usage and billing metrics

This guide shows how to read token counts, context-window utilization, AI credit cost, and account quota from a Copilot SDK application. Examples are shown for TypeScript, Python, Go, .NET, Java, and Rust.

Each example is functionally equivalent across languages. The TypeScript snippet is expanded by default; select your language from the collapsible blocks to see the same logic in that SDK.

Overview

The SDK surfaces usage data through two complementary mechanisms:

  • Session events: ephemeral events the runtime emits as a turn runs. Subscribe to these for real-time, per-API-call data.
  • RPC methods: request/response calls you make on demand. Use these to snapshot accumulated totals or look up account-level quota.

The table below maps each signal to the API that exposes it.

SignalAPIScopeType
Per-call token countsassistant.usage eventSessionEvent
Context-window utilizationsession.usage_info eventSessionEvent
Context-window breakdown (on demand)session.metadata.contextInfoSessionRPC
Accumulated AI credit and token totalssession.usage.getMetricsSessionRPC
Per-model AI credit pricingmodels.listServerRPC
Account quota and premium interactionsaccount.getQuotaServerRPC

참고

session.usage.getMetrics, session.metadata.contextInfo, and session.metadata.recomputeContextTokens are marked experimental in the generated RPC surface. In .NET they raise the GHCP001 experimental diagnostic, which you suppress with #pragma warning disable GHCP001 or a project-level <NoWarn>GHCP001</NoWarn>. Pin both the SDK and the Copilot CLI runtime if your application depends on them.

The field tables below list only the fields used in the examples on this page. The complete, always-current field reference is the generated SDK types plus 스트리밍 세션 이벤트, which is regenerated from the CLI schema on every dependency bump. Treat those as the source of truth and this page as a task-oriented guide.

Per-call token counts

The assistant.usage event is emitted once for every model API call in a turn (including calls made by sub-agents). It carries the token counts and the billing multiplier for that single call.

The example below uses these fields. See 스트리밍 세션 이벤트 for the full list, including cache, reasoning, latency, and tracing fields.

FieldTypeDescription
modelstringModel identifier for this call
inputTokensnumberInput tokens consumed
outputTokensnumberOutput tokens produced
costnumberPremium request multiplier applied to this call

assistant.usage is ephemeral, so it is delivered live but not replayed when you resume a session. To read accumulated totals after the fact, call session.usage.getMetrics (see Accumulated AI credit and token totals).

코드 언어 navigation

TypeScript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
const session = await client.createSession({ streaming: true });

session.on("assistant.usage", (event) => {
    const { model, inputTokens, outputTokens, cost } = event.data;
    console.log(
        `${model}: in=${inputTokens ?? 0} out=${outputTokens ?? 0} cost=${cost ?? 0}`,
    );
});
session.on("assistant.usage", (event) => {
    const { model, inputTokens, outputTokens, cost } = event.data;
    console.log(
        `${model}: in=${inputTokens ?? 0} out=${outputTokens ?? 0} cost=${cost ?? 0}`,
    );
});

Context-window utilization

Token counts tell you what each call consumed. Context-window utilization tells you how full the model's prompt window is right now—useful for showing a progress bar or warning the user before automatic compaction kicks in.

Live updates with session.usage_info

The runtime emits a session.usage_info event whenever the context-window size changes. The example uses currentTokens and tokenLimit; see 스트리밍 세션 이벤트 for the complete payload.

FieldTypeDescription
currentTokensnumberTokens currently in the context window
tokenLimitnumberMaximum tokens for the model's context window

코드 언어 navigation

TypeScript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
const session = await client.createSession({ streaming: true });

session.on("session.usage_info", (event) => {
    const { currentTokens, tokenLimit } = event.data;
    const pct = Math.round((currentTokens / tokenLimit) * 100);
    console.log(`Context: ${currentTokens}/${tokenLimit} (${pct}%)`);
});
session.on("session.usage_info", (event) => {
    const { currentTokens, tokenLimit } = event.data;
    const pct = Math.round((currentTokens / tokenLimit) * 100);
    console.log(`Context: ${currentTokens}/${tokenLimit} (${pct}%)`);
});

On-demand breakdown with session.metadata.contextInfo

Events only fire when the context changes. To read the current breakdown at any moment—for example, right after resuming a session—call session.metadata.contextInfo. Pass 0 for promptTokenLimit to use the runtime default; pass 0 for outputTokenLimit if the value is unknown.

The result's contextInfo is null until the session has been initialized (the system prompt and tool metadata have been cached). It breaks the total down into systemTokens, conversationTokens, and toolDefinitionsTokens, alongside the promptTokenLimit.

코드 언어 navigation

TypeScript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
const session = await client.createSession({});

const { contextInfo } = await session.rpc.metadata.contextInfo({
    promptTokenLimit: 0,
    outputTokenLimit: 0,
});

if (contextInfo) {
    console.log(
        `Total ${contextInfo.totalTokens}/${contextInfo.promptTokenLimit} ` +
            `(system=${contextInfo.systemTokens}, conversation=${contextInfo.conversationTokens})`,
    );
}
const { contextInfo } = await session.rpc.metadata.contextInfo({
    promptTokenLimit: 0,
    outputTokenLimit: 0,
});

if (contextInfo) {
    console.log(
        `Total ${contextInfo.totalTokens}/${contextInfo.promptTokenLimit} ` +
            `(system=${contextInfo.systemTokens}, conversation=${contextInfo.conversationTokens})`,
    );
}

Accumulated AI credit and token totals

session.usage.getMetrics returns the running totals for the whole session in a single call. This is the cleanest way to read AI credit cost, because it aggregates every API call (main agent and sub-agents) for you.

The example uses the fields below. The generated UsageGetMetricsResult type is the full reference.

FieldTypeDescription
totalNanoAiunumberSession-wide AI credit cost, in nano-AI units
totalPremiumRequestCostnumberPremium request cost across all models, after multipliers
modelMetricsRecord<string, ModelMetric>Per-model breakdown; each entry has usage.inputTokens, usage.outputTokens, and totalNanoAiu

참고

Cost is reported in nano-AI units (the field is named totalNanoAiu). The exact conversion to AI credits and the precise meaning of premium request accounting are defined by GitHub Copilot billing, not by the SDK—treat GitHub's Copilot billing documentation as the source of truth and verify before surfacing currency-like values to users. The examples divide by 1e9 as a convenience, following the SI nano prefix; confirm this matches current billing before relying on it. The modelMetrics and tokenDetails maps are keyed by runtime strings (model IDs and token-type names) that the SDK type system does not validate.

코드 언어 navigation

TypeScript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();
const session = await client.createSession({});

const metrics = await session.rpc.usage.getMetrics();

const aiCredits = (metrics.totalNanoAiu ?? 0) / 1e9;
console.log(`AI credits used: ${aiCredits.toFixed(6)}`);
console.log(`Premium requests: ${metrics.totalPremiumRequestCost}`);

for (const [model, m] of Object.entries(metrics.modelMetrics)) {
    if (!m) continue;
    console.log(
        `${model}: in=${m.usage.inputTokens} out=${m.usage.outputTokens} ` +
            `nanoAiu=${m.totalNanoAiu ?? 0}`,
    );
}
const metrics = await session.rpc.usage.getMetrics();

const aiCredits = (metrics.totalNanoAiu ?? 0) / 1e9;
console.log(`AI credits used: ${aiCredits.toFixed(6)}`);
console.log(`Premium requests: ${metrics.totalPremiumRequestCost}`);

for (const [model, m] of Object.entries(metrics.modelMetrics)) {
    if (!m) continue;
    console.log(
        `${model}: in=${m.usage.inputTokens} out=${m.usage.outputTokens} ` +
            `nanoAiu=${m.totalNanoAiu ?? 0}`,
    );
}

Per-model AI credit pricing

To estimate cost before you run a turn, read each model's token prices from models.list. This is a server-scoped call on the client, so it does not need a session. Prices are expressed in AI credits per billing batch of tokens. The generated ModelBillingTokenPrices type lists every field, including cachePrice.

FieldTypeDescription
billing.multipliernumberPremium request cost multiplier relative to the base rate
billing.tokenPrices.inputPricenumberAI credit cost per batch of input tokens
billing.tokenPrices.outputPricenumberAI credit cost per batch of output tokens
billing.tokenPrices.batchSizenumberNumber of tokens per billing batch

참고

Price values change as plans and models evolve. Read them at runtime as shown below; never hard-code the numbers into your application.

코드 언어 navigation

TypeScript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();

const { models } = await client.rpc.models.list({});

for (const model of models) {
    const prices = model.billing?.tokenPrices;
    if (!prices) continue;
    console.log(
        `${model.id}: input=${prices.inputPrice} output=${prices.outputPrice} ` +
            `per ${prices.batchSize} tokens (x${model.billing?.multiplier ?? 1})`,
    );
}
const { models } = await client.rpc.models.list({});

for (const model of models) {
    const prices = model.billing?.tokenPrices;
    if (!prices) continue;
    console.log(
        `${model.id}: input=${prices.inputPrice} output=${prices.outputPrice} ` +
            `per ${prices.batchSize} tokens (x${model.billing?.multiplier ?? 1})`,
    );
}

Account quota and premium interactions

account.getQuota reports the authenticated user's remaining Copilot entitlement. The result's quotaSnapshots map is keyed by quota type—commonly premium_interactions, chat, and completions. Use it to show users how much of their monthly allowance is left, or to gate work before they hit a limit.

The example uses the fields below; the generated AccountQuotaSnapshot type is the full reference. The quotaSnapshots keys are runtime strings that the SDK type system does not validate, so guard your lookups.

FieldTypeDescription
entitlementRequestsnumberRequests included in the entitlement, or -1 for unlimited
usedRequestsnumberRequests used so far this period
remainingPercentagenumberPercentage of the entitlement remaining
resetDatestringISO 8601 date when the quota resets

To read quota for a specific user rather than the connection's global auth context (for example, in a multi-tenant backend), pass that user's GitHub token to getQuota. See 다중 테넌트 및 서버 배포.

코드 언어 navigation

TypeScript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();

const { quotaSnapshots } = await client.rpc.account.getQuota({});
const premium = quotaSnapshots["premium_interactions"];

if (premium) {
    console.log(
        `Premium interactions: ${premium.usedRequests}/${premium.entitlementRequests} ` +
            `(${premium.remainingPercentage.toFixed(1)}% left, resets ${premium.resetDate ?? "n/a"})`,
    );
}
const { quotaSnapshots } = await client.rpc.account.getQuota({});
const premium = quotaSnapshots["premium_interactions"];

if (premium) {
    console.log(
        `Premium interactions: ${premium.usedRequests}/${premium.entitlementRequests} ` +
            `(${premium.remainingPercentage.toFixed(1)}% left, resets ${premium.resetDate ?? "n/a"})`,
    );
}

Choosing the right API

Use this summary to decide which API fits your use case:

  • Render a live cost or token meter as a turn runs: subscribe to assistant.usage and session.usage_info.
  • Show a final cost summary after a turn or session: call session.usage.getMetrics.
  • Display context-window usage on resume, before any new turn: call session.metadata.contextInfo.
  • Estimate cost before running work: read models.list token prices.
  • Warn users before they exhaust their plan: call account.getQuota.

Further reading