Summary
When a sub-agent runs, none of its LLM calls are recorded in token metrics. Sub-agents are completely invisible to netclaw stats — all their internal token expenditures (input, output, thinking, cached) are lost.
This is not a regression; the sub-agent path has never implemented token tracking.
What Works (Main Session)
LlmSessionActor.FireLlmCall()
→ StreamingResponseReader.ReadAsync() returns ChatResponse with Usage
→ LlmResponseReceived handler:
HandleToolCallResponse(lastMessage, ..., response.Usage) // ← passes Usage
HandleTextResponse(lastMessage, response.Usage, ...) // ← passes Usage
→ _sessionMetrics.RecordTokenUsage(input, output) // line 3516
→ EmitUsageOutput(usage) → UsageOutput event to Seq // line 3532
What is Broken (Sub-Agent)
SubAgentActor.InvokeLlmAsync()
→ StreamingResponseReader.ReadAsync() returns ChatResponse with Usage ← data is HERE
→ LlmResponseReceived handler:
var response = msg.Response // ← has .Usage but never read!
HandleToolCalls(lastMessage, toolCalls) // ← no response.Usage passed
// or
Complete(true, text, ...) // ← no response.Usage extracted
→ SubAgentResult returned with {Success, Output, AgentName, Outcome, Findings}
// ← NO token fields at all
Three Data Loss Points
1. Sub-agent handler never reads response.Usage
The ChatResponse from StreamingResponseReader has token usage, but the sub-agent handler in SubAgentActor.cs:317-424 ignores it entirely. No RecordTokenUsage call, no EmitUsageOutput.
2. No _sessionMetrics injected into SubAgentActor
SubAgentActor has no ISessionMetrics dependency. It cannot record tokens even if it wanted to.
3. SubAgentResult carries no token fields
When the sub-agent finishes, it returns SubAgentResult with only {Success, Output, AgentName, Outcome, Findings, FindingsCount}. No token data on the wire. Parent receives it via CompletedSubAgentRun (in LlmMessages.cs) which also has no token fields.
Impact
netclaw stats shows parent session token counts but zero sub-agent contribution
- Parent only sees its own single LLM call (which includes the sub-agents final output text but not the sub-agents internal token expenditures)
- No way to see how many tokens a sub-agent consumed or how many LLM calls it made
- Cannot correlate sub-agent cost with its duration or tool usage
Required Fixes
A. SubAgentActor must record token usage per LLM call
- Inject
ISessionMetrics into SubAgentActor constructor
- In the
LlmResponseReceived handler, after getting the response, call _sessionMetrics?.RecordTokenUsage(response.Usage?.InputTokenCount ?? 0, response.Usage?.OutputTokenCount ?? 0) for each LLM call
- Optionally emit a
UsageOutput event to Seq for sub-agent-level observability
B. Propagate token data back to parent
- Add token fields to
SubAgentResult record (SubAgentProtocol.cs)
- Add token fields to
CompletedSubAgentRun record (LlmMessages.cs)
- Parent session should aggregate sub-agent tokens and record them in its own
ISessionMetrics
C. Logging enhancement
- Log token counts in the sub-agent summary line at
SubAgentActor.cs:757-762 (currently only logs tool counts and duration)
Files Involved
| File |
Change |
SubAgentActor.cs |
Inject ISessionMetrics, extract response.Usage in handler, record per-call |
SubAgentProtocol.cs |
Add InputTokens/OutputTokens to SubAgentResult |
LlmMessages.cs |
Add InputTokens/OutputTokens to CompletedSubAgentRun |
SubAgentSpawner.cs |
Pass ISessionMetrics through ToolExecutionContext or resolve in actor factory |
LlmSessionActor.cs |
Aggregate sub-agent tokens when receiving CompletedSubAgentRun |
Test Coverage Needed
- Unit test: sub-agent LLM response handler extracts and records token counts
- Integration test: parent session aggregates sub-agent token data in stats
- Verify
netclaw stats output includes sub-agent tokens
Summary
When a sub-agent runs, none of its LLM calls are recorded in token metrics. Sub-agents are completely invisible to
netclaw stats— all their internal token expenditures (input, output, thinking, cached) are lost.This is not a regression; the sub-agent path has never implemented token tracking.
What Works (Main Session)
What is Broken (Sub-Agent)
Three Data Loss Points
1. Sub-agent handler never reads
response.UsageThe
ChatResponsefromStreamingResponseReaderhas token usage, but the sub-agent handler inSubAgentActor.cs:317-424ignores it entirely. NoRecordTokenUsagecall, noEmitUsageOutput.2. No
_sessionMetricsinjected intoSubAgentActorSubAgentActorhas noISessionMetricsdependency. It cannot record tokens even if it wanted to.3.
SubAgentResultcarries no token fieldsWhen the sub-agent finishes, it returns
SubAgentResultwith only{Success, Output, AgentName, Outcome, Findings, FindingsCount}. No token data on the wire. Parent receives it viaCompletedSubAgentRun(inLlmMessages.cs) which also has no token fields.Impact
netclaw statsshows parent session token counts but zero sub-agent contributionRequired Fixes
A. SubAgentActor must record token usage per LLM call
ISessionMetricsintoSubAgentActorconstructorLlmResponseReceivedhandler, after getting the response, call_sessionMetrics?.RecordTokenUsage(response.Usage?.InputTokenCount ?? 0, response.Usage?.OutputTokenCount ?? 0)for each LLM callUsageOutputevent to Seq for sub-agent-level observabilityB. Propagate token data back to parent
SubAgentResultrecord (SubAgentProtocol.cs)CompletedSubAgentRunrecord (LlmMessages.cs)ISessionMetricsC. Logging enhancement
SubAgentActor.cs:757-762(currently only logs tool counts and duration)Files Involved
SubAgentActor.csISessionMetrics, extractresponse.Usagein handler, record per-callSubAgentProtocol.csInputTokens/OutputTokenstoSubAgentResultLlmMessages.csInputTokens/OutputTokenstoCompletedSubAgentRunSubAgentSpawner.csISessionMetricsthroughToolExecutionContextor resolve in actor factoryLlmSessionActor.csCompletedSubAgentRunTest Coverage Needed
netclaw statsoutput includes sub-agent tokens