Repository navigation
fix(export): keep usage metadata on inline function handoff - #2721
Open
abhiramshaji-cyber wants to merge 1 commit into
Open
abhiramshaji-cyber wants to merge 1 commit into
abhiramshaji-cyber wants to merge 1 commit into
Conversation
When a model call ends by asking for an inline function, the exported Strands agent returned right after forwarding messageStop. Strands sends that call's metadata event, which carries the token usage, directly after messageStop, so the caller never received usage for the call that handed off the tool and could not account for it. The stream loop now marks the handoff and inspects only the next event: a metadata event is forwarded, anything else is dropped, and the stream ends. Both loop variants (with and without execution limits) share the change. Runs without an inline function are unaffected. Closes aws#2695
Author
|
@nborges-aws this is ready for a look whenever you have time. The CodeBuild end to end run passed, and the new test runs the real template stream loop under python3. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Agents exported from a harness now report token usage for the model call that hands work back to the caller through an inline function.
What this code is for
src/assets/python/http/strands/base/main.pyis the Strands agent the CLI writes when a harness is exported to a standalone agent. It streams model events to the caller the same way the harness does. When the model asks for an inline function (a tool the caller runs on its own side), the agent ends the stream so the caller can run the tool and send the result back in its next request.Before
Dana runs an exported harness agent and bills her users per request from the usage numbers in the stream.
messageStop(stop reasontool_use).messageStopand ends the stream right there.metadataevent, which carries the token counts and arrives right aftermessageStop, is never sent.After
Dana runs the same agent and sends the same prompt.
messageStop(stop reasontool_use).messageStopand looks at the very next event before ending the stream.metadatafor the same model call, so the agent forwards it and then ends the stream.flowchart LR subgraph BEFORE direction TB B1["Model asks for an inline function"] --> B2["Agent forwards messageStop"] B2 ==> B3["Agent ends the stream at once"] B3 --> B4["Usage of that call is never sent"] end subgraph AFTER direction TB A1["Model asks for an inline function"] --> A2["Agent forwards messageStop"] A2 ==> A3["THE CHANGE: agent checks the next event"] A3 --> A4["Next event is metadata: forwarded, then the stream ends"] A3 --> A5["Model sent no usage: stream ends, nothing extra sent"] end B1 ~~~ A1 linkStyle 1 stroke:#d32f2f,stroke-width:4px linkStyle 4 stroke:#2e7d32,stroke-width:4pxThe change
Both copies of the stream loop (with and without execution limits) used to
returnright after forwarding themessageStopthat follows an inline function call. They now sethanded_offinstead. On the next event, the loop forwards it only when it is ametadataevent, then returns. Nothing else is ever forwarded after the handoff, so the stream still ends at the same model call and the tool is still left for the caller to run. Strands sends a model call'smetadatadirectly after itsmessageStop, so checking only the next event is enough.The asset snapshot is updated. The new test
src/cli/templates/__tests__/strands-inline-function-stream.test.tsrenders the template, runs its real stream loop underpython3against a fake agent, and checks three runs for both loop copies: a handoff followed bymetadata, a handoff with nometadata, and a run with no inline function. The first case fails on the main branch before this change.What changes for a user
Usage numbers from an exported agent now cover every model call in a request, including the one that hands off an inline function, so per request totals match the agent's own traces. Everything else works as before: runs that end with a normal reply, regular tools, timeouts and execution limit stops stream the same events, and the follow up request that carries the tool result is handled the same way. This change covers the exported agent in this repository; the hosted harness service is not part of this repository.
Related Issue
Closes #2695
Documentation PR
None needed; no documented behavior changes.
Type of Change
Testing
How have you tested the change?
bun run test(444 files, 6386 tests passed, 2 skipped) andnpx vitest run --project integ(36 files, 355 tests passed, 1 skipped)bun run typecheck(no errors)bun run lint(0 errors) andbun run format:check(all files pass), plusbun run build(succeeds)src/assets/, I rannpm run test:update-snapshotsand committed the updated snapshots (I updated onlysrc/assets/__tests__/assets.snapshot.test.tswith--update)Checklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.