feat: add Limits and support it during invoke/stream#2360
Merged
notowen333 merged 2 commits intoMay 28, 2026
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
zastrowm
previously approved these changes
May 28, 2026
mypy narrows the loop key to a literal union, so the TypedDict access no longer needs the literal-required ignore.
zastrowm
approved these changes
May 28, 2026
7 tasks
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
Motivation
An agent loop today runs until the model stops requesting tools, a hook halts it, or it's cancelled. There's no caller-side guardrail on cost or runaway behavior — anyone wanting to bound a run has to wire a hook themselves or wrap the call in a timeout that races against the model rather than terminating cleanly at a turn boundary. This adds first-class, per-invocation budget caps so callers can put a ceiling on a single
invoke_async/stream_asyncwithout fighting the loop.Ports the equivalent TypeScript feature merged in strands-agents/sdk-typescript#1106.
Public API Changes
Agent.__call__,Agent.invoke_async, andAgent.stream_asyncaccept an optionallimitsargument with three caps:When a cap is reached the loop terminates gracefully at the next turn boundary and returns an
AgentResultwith one of three newstop_reasonvalues:"limit_turns","limit_output_tokens","limit_total_tokens". No exception is raised — this mirrors how"cancelled"already works, and leavesresult.messageandresult.metricsaccessible.The existing
"max_tokens"reason (andMaxTokensReachedException) is unchanged. That one signals the model provider's per-call output cap and still raises; the new caller-set caps are graceful.Caps are scoped to a single invocation — counters reset on each
invoke_async/stream_asynccall against the same agent. Tools requested by the previous turn always run to completion before a cap fires, soagent.messagesstays in a state the agent can be reinvoked from. On simultaneous trip the priority isturns→total_tokens→output_tokens, giving the most informative reason in the result. Caps are soft: a single oversized model response can overshoot the budget by one turn, since checks happen at turn boundaries, not within an individual model call.Each cap, when set, must be a positive
int; invalid values raiseTypeErrorat the start of the invocation. Backward compatible — omittinglimitspreserves prior behavior.Why a
limitsdict instead of top-level kwargsGrouping under
limitskeeps the top-level kwarg surface stable as future caps (wall-clock, cost, etc.) are added. The stop reasons keep alimit_prefix rather than collapsing to a single"limit_exceeded"so granular telemetry / log buckets are preserved — callers shouldn't have to derive which cap tripped fromresult.metricsplus thelimitsthey passed in.Use Cases
turnsbudget so a single stuck agent doesn't pin a worker.stop_reasoninstead of cancelling mid-stream.Related Issues
#2124
Documentation PR
N/A — will follow up.
Type of Change
New feature
Testing
How have you tested the change? Verify that the changes do not break functionality or introduce warnings in consuming repositories: agents-docs, agents-tools, agents-cli
hatch run prepareChecklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.