Skip to content

Advisor (opus) token costs not tracked — data is in iterations[].type=advisor_message #1115

Closed

Description

@UberMouse

Summary

When Claude Code's advisor() tool is used (e.g. sonnet as primary model, opus as advisor), the advisor model's token costs are not counted by ccusage. The data is present in the JSONL — it's embedded in the message.usage.iterations array as entries with type: \"advisor_message\" — but ccusage doesn't parse the iterations array, so those tokens are silently dropped.

Where the data lives

Each type: \"assistant\" entry in the session JSONL has a message.usage.iterations array. When the advisor tool fires, a middle iteration of type: \"advisor_message\" is inserted between the two main-model iterations:

{
  "type": "assistant",
  "advisorModel": "claude-opus-4-7",
  "message": {
    "model": "claude-sonnet-4-6",
    "usage": {
      "input_tokens": 2,
      "output_tokens": 491,
      "cache_read_input_tokens": 226584,
      "cache_creation_input_tokens": 7853,
      "iterations": [
        {
          "type": "message",
          "input_tokens": 1,
          "output_tokens": 45,
          "cache_read_input_tokens": 109696,
          "cache_creation_input_tokens": 7192
        },
        {
          "type": "advisor_message",
          "model": "claude-opus-4-7",
          "input_tokens": 159419,
          "output_tokens": 7805,
          "cache_read_input_tokens": 0,
          "cache_creation_input_tokens": 0
        },
        {
          "type": "message",
          "input_tokens": 1,
          "output_tokens": 446,
          "cache_read_input_tokens": 116888,
          "cache_creation_input_tokens": 661
        }
      ]
    }
  }
}

Key observations from the above (sampled from a real session, 2026-05-22T02:34:40):

  • The advisor_message iteration carries its own model field (claude-opus-4-7) — the pricing is distinct from the main model
  • cache_read_input_tokens: 0 — the full transcript is forwarded uncached to the advisor, so these are billed at full input rate (not the cheaper cache-read rate)
  • The top-level cache_read_input_tokens: 226,584 is the sum of both main-model iterations only (109,696 + 116,888) — the advisor's 159K input tokens are separate and currently invisible to any external cost tool

Cost impact

In the example above:

  • 159,419 uncached input tokens at opus pricing disappear entirely from ccusage's accounting
  • 7,805 output tokens from opus also untracked

Since the advisor forwards the full conversation transcript each time it's called, these counts grow with session length. On a long session this can represent a substantial fraction of actual billing.

Proposed fix

When processing an assistant entry, check message.usage.iterations for any entries with type === \"advisor_message\". For each such entry:

  1. Read model from the iteration (e.g. claude-opus-4-7)
  2. Attribute input_tokens, output_tokens, cache_read_input_tokens, cache_creation_input_tokens to that model using its own pricing
  3. Do not also count those tokens toward the main session model — they are already excluded from the top-level usage totals

The advisorModel field at the top level of the JSONL entry is a reliable sentinel that the iterations array will contain an advisor_message entry, if you want to skip parsing iterations on unaffected turns.

Related

Activity

  1. github-actions commented on May 22, 2026

    @github-actions
    Contributor

    This issue was auto-closed. Issues from new contributors are auto-closed by default.

    Maintainers review auto-closed issues and reopen worthwhile ones. Issues that do not meet the quality bar in CONTRIBUTING.md may not be reopened or receive a reply.

    Keep the issue short, concrete, and written in your own voice.

    If a maintainer replies lgtmi, your future issues will stay open. If a maintainer replies lgtm, your future issues and PRs will stay open.

    See CONTRIBUTING.md.

  2. schliz commented on Jul 9, 2026

    @schliz

    @ryoppippi @ben-vargas This is a real issue and persists as of today. I can re-create the same problem with using claude-sonnet-5 with claude-opus-4-8 as the advisor. Here, ccusage only counts usage for claude-sonnet-5 and doesn't track the advisor at all.

    I use the advisor tool and my claude selects it regularly, which causes a lot of uncounted tokens.

  3. ryoppippi commented on Aug 31, 2026

    @ryoppippi
    Member

    Historical audit: this discussion was auto-closed by the legacy contributor gate. That closure did not assess technical importance.

    Audit result: resolved. A later merged change or the current main implementation covers this request. This item is kept for history and does not need to be reopened.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage:resolvedResolved by a later change or current implementation.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions