Skip to content

[M10b] Add remote sub-agent token usage to the lead's totals - #297

Merged
LinuxDevil merged 3 commits into
mainfrom
lou-m10b-remote-usage
Oct 2, 2026
Merged

LinuxDevil merged 3 commits into
mainfrom
lou-m10b-remote-usage

Conversation

@LinuxDevil

Copy link
Copy Markdown
Owner

Closes #234

What

A lead that delegates to a remoteAgent() now adds the remote run's token usage to its own result.usage, the same way it does for local sub-agents. Before this, the remote run's usage was dropped.

  • RemoteRunOptions.onUsage?: (usage: AgentEventUsage) => void (additive; run() still returns Promise<string>). remoteAgent().run calls it once per remote turn with the run.done usage, before outcome(), so a turn that paused reports its usage too. This holds for fresh turns and for approval continuations.
  • runRemoteTask converts the usage with the new fromEventUsage(usage, 'remote:<name>'), then calls the same onDelegatedUsage hook local children use. Totals, usage.delegated and byModel['remote:<name>'] are updated.
  • byModel['remote:...'] entries keep the cost the remote reported. refreshDerived does not re-price them, because there is no model id to price by. When the remote sends no cost, the lead's costUsd becomes undefined.
  • No double counting on continuation: a remote run resumed after an approval reports its usage from the start of the run, including the turn before the pause. The test confirms this against the real routes. The remote pause snapshot now keeps the remote's usage so far (snapshot.usage), and the continuation adds only usageSince(now, before). Chained pauses work the same way.
  • Background remote tasks roll up through the same hook. A remote that sends no usage (older server) adds nothing.
  • Not done (optional in the ticket): the richer protocol fields (cachedInputTokens / reasoningTokens on AgentEventUsage) were left out to keep the event schema unchanged.

Tests

  • src/subagents/remoteAgent.test.ts: 6 new tests:
    • totals, delegated and byModel['remote:remote']
    • the reported cost is kept, and onUsage is called with the turn's usage
    • pause then approve: 330/33 tokens, not 430
    • continuation pauses again: each remote call is counted once
    • background task
    • older server with no usage
  • src/execution/runUsage.test.ts (new): fromEventUsage, cost merging and restore, unknown cost, usageSince clamping.
  • src/subagents/remoteAgent.test-d.ts (new): a hand-written RemoteSubagent still type-checks.
  • src/subagents/remoteUsage.live.test.ts (new): runs only under npm run test:live, and skips without OPENROUTER_API_KEY.

Docs

  • docs/sub-agents.md:
    • "How it works" paragraph now mentions remote sub-agents
    • new paragraph at the end of "Remote sub-agents"
    • inherit table row
  • docs/models-and-cost.md: the "Delegation" bullet.
  • No headings were added or renamed. CHANGELOG entry under Fixed. llms.txt and llms-full.txt were regenerated.

Verification (after git merge origin/main, all exit 0)

npx tsc --noEmit                                   exit 0
npm run lint                                       exit 0 (--max-warnings 0)
npm run build                                      exit 0
npm run build --workspace=packages/create-lousho-agent  exit 0
npm run test:types                                 exit 0 (12 files, 58 tests, no type errors)
npm run docs:verify-snippets -- --skip-build       exit 0 (all 208 snippets type-check; 8 also run)
npm run docs:llms:check                            exit 0
npm run test:coverage                              exit 0
npm run fallow                                     exit 0 (0 above threshold, maintainability 89.7)
npm run typecheck --workspace apps/agent-forge     exit 0
npm run typecheck:server --workspace apps/agent-forge  exit 0
npm run test --workspace apps/agent-forge -- --run exit 0 (13 files, 112 tests)
npm run test:server --workspace apps/agent-forge   exit 0 (14 files, 122 tests)
npm run pack-smoke                                 exit 0 (all checks passed)

Live test

Skipped. The OpenRouter account is out of credit: /credits returned total_usage 10.20 against total_credits 10 on 2026-10-02. The key counter shows usage 0 and limit_remaining 10, but calls would fail with 402. Live test spend: before 0, after 0 (no calls made). The step is listed on #260.

🤖 Generated with Claude Code

LinuxDevil and others added 3 commits October 2, 2026 19:26
A lead delegating to a remoteAgent() now adds the remote run's reported
run.done usage to result.usage (totals, usage.delegated, and
byModel['remote:<name>'] with the remote's own costUsd). A continuation after
a remote approval adds only what it spent after the pause; background remote
tasks roll up the same way; a remote without usage adds nothing.
RemoteRunOptions gains an optional onUsage callback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[M10b] Add remote sub-agent token usage to the lead's totals

1 participant