Skip to content

[BUG] [v0.0.7] SubagentExecutor summary turn skips total_tokens update — session.tokens_used under-reports when summary is requested (executor.rs:493-497) #18543

Description

@echoforge2200

Project

cortex

Description

When SubagentExecutor::run_subagent() requests a mandatory summary turn (lines 444-501 in executor.rs), it merges the summary turn's token counts into turn_ctx.tokens at lines 493-497:

// Update token counts
turn_ctx.tokens.input_tokens += summary_turn_ctx.tokens.input_tokens;
turn_ctx.tokens.output_tokens += summary_turn_ctx.tokens.output_tokens;
turn_ctx.tokens.cached_tokens += summary_turn_ctx.tokens.cached_tokens;
turn_ctx.tokens.reasoning_tokens += summary_turn_ctx.tokens.reasoning_tokens;

However, turn_ctx.tokens.total_tokens is not updated. The TokenUsage struct (defined in agent/mod.rs:234-247) stores total_tokens as a separate field — it is NOT computed from input_tokens + output_tokens. The proper way to update it is via TurnContext::add_tokens() (orchestrator.rs:85-88) which does self.tokens.total_tokens += input + output, but the manual addition at lines 493-497 skips this field entirely.

Later at line 533, session.record_turn(...) uses turn_ctx.tokens.total_tokens which now excludes the summary turn's tokens:

session.record_turn(
    turn_ctx.tool_results.len() as u32,
    turn_ctx.tokens.total_tokens as u64,  // Missing summary tokens
);

Error Message

No error — the token count is silently wrong.

Debug Logs

No response

System Information

Cortex version: v0.0.7
OS: Linux
Affected file: src/cortex-engine/src/tools/handlers/subagent/executor.rs (lines 493-497, 533)
Related: src/cortex-engine/src/agent/mod.rs (lines 234-247 — TokenUsage struct)
Related: src/cortex-engine/src/agent/orchestrator.rs (lines 85-88 — add_tokens method)

Steps to Reproduce

  1. Spawn a subagent that completes its task but does NOT include summary markers (e.g., "## Summary for Orchestrator") in its response.
  2. The executor detects missing summary at line 447: !has_summary_output(&result.response).
  3. A summary turn is executed (lines 454-469).
  4. If the summary succeeds, token counts are merged at lines 493-497 — but total_tokens is skipped.
  5. session.record_turn() at line 533 records turn_ctx.tokens.total_tokens which excludes the summary turn's tokens.
  6. SubagentSession.tokens_used and SubagentResult.token_usage under-report actual token consumption.

Expected Behavior

turn_ctx.tokens.total_tokens should be updated alongside the other token fields when merging summary turn tokens. The missing line should be:

turn_ctx.tokens.total_tokens += summary_turn_ctx.tokens.total_tokens;

Or equivalently, use turn_ctx.add_tokens(summary_turn_ctx.tokens.input_tokens, summary_turn_ctx.tokens.output_tokens) which correctly updates all three fields.

Actual Behavior

total_tokens is not updated with summary turn tokens, causing session.tokens_used to under-report. This affects billing/quota tracking and user-facing token usage reports in SubagentResult.token_usage and ProgressEvent::Completed.total_tokens.

Additional Context

The TokenUsage struct stores total_tokens independently:

pub struct TokenUsage {
    pub input_tokens: u32,
    pub output_tokens: u32,
    pub total_tokens: u32,    // NOT computed — must be updated manually
    pub cached_tokens: u32,
    pub reasoning_tokens: u32,
}

The add_tokens method correctly maintains the invariant total_tokens = input + output, but the manual field-by-field addition at lines 493-497 breaks it by omitting total_tokens.

Metadata

Metadata

Assignees

No one assigned

    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