Skip to content

ACP: PromptResponse.usage reports only the final LLM request of the turn (neither session-cumulative nor per-turn totals) #46092

Closed as duplicate

Description

@panghy

Summary

Over ACP, PromptResponse.usage reports the token usage of the final LLM request of the turn — not session-cumulative totals (what the ACP schema documents) and not a per-turn sum either. Multi-step (tool-calling) turns and multi-message turns systematically under-report: all but the last request's tokens are invisible on this surface.

Where (v1.18.18)

Two levels of "last wins":

  1. Within one assistant message: every step-finish replaces the message's tokens (ctx.assistantMessage.tokens = usage.tokens) while cost accumulates (cost += usage.cost) — packages/opencode/src/session/processor.ts:444-445. A multi-step message therefore carries only its final LLM request's tokens.
  2. Across the turn: each outer loop iteration creates a new assistant message (packages/opencode/src/session/prompt.ts:1186-1200), and session/prompt returns lastAssistant(sessionID) (prompt.ts:1338-1340); the ACP layer builds usage: buildUsage(info) from that single message (packages/opencode/src/acp/service.ts:823-838, packages/opencode/src/acp/usage.ts:90-103).

Net: PromptResponse.usage = tokens of the turn's final LLM request.

Why it matters

The ACP SDK schema documents Usage fields as session-cumulative ("Total input tokens across all turns", "Sum of all token types across session"). There is an open discussion about clarifying the session-usage RFD to per-turn instead (agentclientprotocol/claude-agent-acp#390) — but last-request semantics matches neither reading, so clients cannot recover turn or session totals from this surface no matter which aggregation they apply.

Note the asymmetry within opencode's own reporting: usage_update.cost is session-cumulative (acp/usage.ts:111-115 sums info.cost over all assistant messages), while the token counters on PromptResponse.usage are last-request — the two halves of the usage report cover different windows.

Concrete downstream impact: intentd (intent-hq/intent) ingests PromptResponse.usage with the schema's cumulative-REPLACE semantics, so opencode sessions are undercounted in its token accounting — tracked in intent-hq/intent#3801.

Suggested fix

Report session-cumulative token totals in PromptResponse.usage (e.g. sum the disjoint token buckets across all assistant messages of the session, mirroring what totalSessionCost already does for cost). If the RFD lands on per-turn semantics instead, summing the steps of the turn's messages would satisfy that reading — either is strictly better than last-request.

Happy to provide the full audit trail (line-cited) if useful.

Activity

  1. github-actions commented on Aug 29, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    You may want to coordinate with those issues or add detail there rather than tracking separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions