Conversation
The embedded translation agent (search_events, search_issues,
search_issue_events) is stochastic: it occasionally exhausts its step
budget without emitting structured output, which surfaces as a
UserInputError ("could not construct a valid query"). An identical retry
almost always succeeds — observed live in prod, where a
count_unique-per-hour timeseries query failed on the first attempt and
worked on an identical second one.
Retry once on NoOutputGeneratedError / unrescued NoObjectGeneratedError
before mapping to a user-facing error. callEmbeddedAgent is split into a
retry loop, a single-attempt runner (runEmbeddedAgentAttempt), and the
terminal error mapper (mapEmbeddedAgentError) so the retry policy is
explicit and the attempt body is unchanged. Benefits every embedded-agent
tool, and only the failing tail pays the extra call (capped at 2).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Member
Author
|
Superseded by #1309. Switching from a blind full retry to a framework-native final-output turn (prepareStep + toolChoice:'none' on the closing step), which keeps the agent's context and addresses the root cause (the model never committing to output before its step budget runs out) rather than re-running from scratch. |
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.
Problem
The embedded translation agent (used by
search_events,search_issues,search_issue_events) is stochastic. It occasionally exhausts its step budget without emitting structured output, whichcallEmbeddedAgentturns into aUserInputError— "could not construct a valid query". An identical retry almost always succeeds.This was observed live in prod right after the time-series feature (#1305) shipped:
unique users affected per hourfailed on the first attempt with that exact error, then returned a correct series on an identical retry. So the query was fine — the model just missed once.What this does
Retry the agent once on the transient no-output failure before surfacing it:
NoOutputGeneratedErrorand unrescuedNoObjectGeneratedError(the "model gave us nothing usable this time" cases).Benefits every embedded-agent tool, not just time series.
How
callEmbeddedAgentis split into three pieces so the retry policy is explicit and the attempt body is untouched:callEmbeddedAgent— the retry loop.runEmbeddedAgentAttempt— one attempt: translate, capture tool calls, parse output, and rescueNoObjectGeneratedError(per attempt). Throws raw on any other failure.mapEmbeddedAgentError— maps a terminal (post-retry) failure to the typed error handlers expect. Behaviour and messages are unchanged from the old catch block.Test plan
pnpm --filter @sentry/mcp-core tsc— clean;biome lint/format— clean; full mcp-core suite — 1421 passed.NoOutputGeneratedError→ second attempt succeeds → result returned,generateTextcalled twice, retry logged, no Sentry issue filed.callEmbeddedAgenttests (provider errors, rescue, give-up-with-UserInputError, config errors) still pass unchanged.Notes
withProviderFallbackfallback — was not done here: that fallback has no time-series path and would not have recovered the query above.🤖 Generated with Claude Code