Skip to content

bug(cost-tracking): Token usage and costs from subagents are not included in conversation summary, and data is lost on Ctrl+C interruption #2040

@dariuszkowalski-com

Description

@dariuszkowalski-com

Description

The Forge application has critical issues with token usage and cost tracking: (1) usage data from subagents is not aggregated into parent conversation statistics, and (2) accumulated usage data is lost when users interrupt operations with Ctrl+C.

Current Behavior

  1. Subagent usage exclusion: When main agents call subagents, each subagent creates an independent conversation. The final "TOKEN USAGE" summary only shows the main agent's direct API calls, completely omitting all subagent usage data.

  2. Data loss on interruption: When users press Ctrl+C during execution, the application logs the interruption but does not save the current conversation state. All accumulated usage data is lost, and no cost summary is displayed.

Expected Behavior

  1. Complete usage aggregation: The conversation summary should include aggregated token usage and costs from the entire agent execution tree, including all nested subagents.

  2. Graceful interruption handling: Ctrl+C should save the current conversation state with accumulated usage data and display the usage summary even for interrupted operations.

Steps to Reproduce

Subagent Usage Exclusion:
  1. Configure an agent that calls other agents as tools
  2. Execute a task that triggers subagent calls
  3. Wait for task completion and observe the "TOKEN USAGE" summary
  4. Compare reported costs with actual API usage (significant discrepancy)
Data Loss on Ctrl+C:
  1. Start any agent task that takes time to complete
  2. Press Ctrl+C during execution
  3. Observe that no usage summary is displayed
  4. Verify that no usage data was saved to the conversation

Environment

  • Forge Version: All
  • OS: All

Screenshots/Logs

Subagent isolation code:

// crates/forge_app/src/agent_executor.rs:54-66
let conversation = Conversation::generate().title(task.clone());
self.services
    .conversation_service()
    .upsert_conversation(conversation.clone())
    .await?;

Ctrl+C handler without data preservation:

// crates/forge_main/src/ui.rs:298-300
_ = tokio::signal::ctrl_c() => {
    tracing::info!("User interrupted operation with Ctrl+C");
    // Missing: conversation state save, usage data preservation
}

Missing parent relationship in Conversation:

// crates/forge_domain/src/conversation.rs:31-40
pub struct Conversation {
    pub id: ConversationId,
    pub title: Option<String>,
    pub context: Option<Context>,
    pub metrics: Metrics,
    pub metadata: MetaData,
}
// Missing: parent_id field for hierarchy

Additional Context

These issues significantly impact cost transparency and budget monitoring. The problems compound each other - users not only see incomplete cost data due to subagent exclusion, but also lose all tracking data when interrupting operations.

Impact severity: High - affects cost accuracy and user trust in usage reporting, particularly for:

  • Multi-level agent hierarchies (Main → SubAgent → SubSubAgent)
  • Long-running tasks with potential user interruption
  • Production environments requiring accurate cost tracking

Root causes:

  1. Architectural: Flat conversation model without hierarchy support
  2. Missing graceful shutdown: No signal handling for data preservation
  3. Incomplete state management: Usage data only persisted at task completion

Related to: #2032

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: bugSomething isn't working.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions