Skip to content

Better log the usage: tokens, cost #6

@cmoulliard

Description

@cmoulliard

Improvement: Add proper UsageUpdate type and PromptResponse usage field - ACP

Context

The ACP agent (Claude) sends two forms of usage data that are currently not properly handled:

  1. usage_update session notifications — streamed during prompt processing with fields used, size, cost. Currently deserialized as a raw Map causing a DEBUG log: "Unknown session update type: usage_update". Handled via instanceof Map in the client default branch.

  2. usage field in the final PromptResponse — returned in the JSON-RPC result with token details (inputTokens, outputTokens, cachedReadTokens, cachedWriteTokens, totalTokens). Currently
    silently dropped because PromptResponse only has stopReason.

Neither type is defined in the ACP schema JSON — they are agent extensions. We add Java records to handle them properly.

Changes

1. Create UsageUpdate record

File: schema/src/main/java/io/quarkiverse/agentclientprotocol/sdk/spec/schema/v1/UsageUpdate.java

Fields based on observed JSON: _meta, used (Integer), size (Integer), cost (Map<String, Object> — contains amount and currency).

Follows the same pattern as ConfigOptionUpdate, CurrentModeUpdate, etc.

2. Register usage_update in SESSION_UPDATE_TYPES

File: core/src/main/java/io/quarkiverse/agentclientprotocol/sdk/client/AcpAsyncClient.java

Add: Map.entry("usage_update", UsageUpdate.class) to the map.

This eliminates the "Unknown session update type" debug log.

3. Add usage field to PromptResponse

File: schema/src/main/java/io/quarkiverse/agentclientprotocol/sdk/spec/schema/v1/PromptResponse.java

Add @JsonProperty("usage") Map<String, Object> usage to capture token data. Using Map<String, Object> since this is an agent extension not standardized in the schema.

4. Update handleSessionUpdate in both clients

Files:

  • client/src/main/java/io/quarkiverse/acp/AcpAgentCommand.java
  • client/src/main/java/io/quarkiverse/acp/AcpAgentCli.java

Replace the default branch instanceof Map check with a typed case UsageUpdate branch. Log: [Usage] used=X size=Y cost=Z.

5. Log token usage from PromptResponse

Files:

  • client/src/main/java/io/quarkiverse/acp/AcpAgentCommand.java
  • client/src/main/java/io/quarkiverse/acp/AcpAgentCli.java

After logging stop reason, log response.usage() if present. Example:
Done! Stop reason: END_TURN
[Tokens] input=9 output=3972 cachedRead=176852 cachedWrite=35080 total=215913

Verification

  • mvn compile -pl client -am should succeed
  • Run with -l DEBUG — no more "Unknown session update type: usage_update" log
  • [Usage] line should still appear with used, size, cost
  • After "Done!" line, token details should be logged

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions