feat(agents): enable conservative retries by default for transient errors#449
Open
MarioCadenas wants to merge 2 commits into
Open
feat(agents): enable conservative retries by default for transient errors#449MarioCadenas wants to merge 2 commits into
MarioCadenas wants to merge 2 commits into
Conversation
…ent errors
Agent stream defaults previously set retry { enabled: false }. Enable a
conservative default (attempts: 2, 500ms..4s backoff) so a transient serving
error (5xx / 429 / connection reset) doesn't fail the whole turn. Non-retryable
errors (4xx, AppKitError isRetryable=false) are still never retried.
Streaming safety: in executeStream the RetryInterceptor wraps only the
synchronous creation of the adapter async generator; token emission and tool
dispatch run during yield* iteration, outside the interceptor chain. A transient
error thrown after the first streamed event therefore cannot be retried, so
retries can never re-emit tokens or re-run a tool side-effect. Only a failure
during generator setup (before any output) is retried. Added defaults.test.ts
asserting the conservative values and proving no mid-stream replay.
Co-authored-by: Isaac
Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
Contributor
📦 Bundle size reportCompared against
|
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 686 KB (+60 B) | 240 KB (+40 B) |
| Type declarations | 268 KB | 91 KB |
| Source maps | 1.3 MB (+973 B) | 446 KB (+519 B) |
| Other | 11 KB | 3.7 KB |
| Total | 2.3 MB (+1.0 KB) | 780 KB (+559 B) |
Per-entry composition (own code — deps external (as shipped))
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
. |
74 KB | 2.5 KB | 76 KB | external | 243 KB |
./beta |
39 KB (+17 B) | 231 B | 39 KB (+17 B) | external | 117 KB (+41 B) |
./type-generator |
18 KB | 0 B | 18 KB | external | 53 KB |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
. |
index.js |
initial | 70 KB |
. |
utils.js |
initial | 4.0 KB |
. |
remote-tunnel-manager.js |
lazy | 2.5 KB |
./beta |
beta.js |
initial | 30 KB |
./beta |
databricks.js |
initial | 5.7 KB |
./beta |
service-context.js |
initial | 3.1 KB |
./beta |
client-options.js |
initial | 220 B |
./beta |
databricks.js |
lazy | 128 B |
./beta |
index.js |
lazy | 103 B |
./type-generator |
index.js |
initial | 18 KB |
@databricks/appkit-ui
npm tarball (packed): 298 KB — gzipped download (dist + bin; excludes release-only docs/NOTICE).
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 354 KB | 117 KB |
| Type declarations | 204 KB | 73 KB |
| Source maps | 676 KB | 220 KB |
| CSS | 16 KB | 3.3 KB |
| Total | 1.2 MB | 413 KB |
Per-entry composition (consumer bundle — deps bundled, peerDeps external)
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
./js |
4.2 KB | 49 KB | 54 KB | 208 KB | 11 KB |
./js/beta |
20 B | 0 B | 20 B | 0 B | 0 B |
./react |
429 KB | 49 KB | 477 KB | 1.3 MB | 166 KB |
./react/beta |
20 B | 0 B | 20 B | 0 B | 0 B |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
./js |
index.js |
initial | 4.1 KB |
./js |
chunk |
initial | 120 B |
./js |
apache-arrow |
lazy | 49 KB |
./js/beta |
beta.js |
initial | 20 B |
./react |
index.js |
initial | 427 KB |
./react |
tslib |
initial | 2.1 KB |
./react |
apache-arrow |
lazy | 49 KB |
./react/beta |
beta.js |
initial | 20 B |
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.
What
Agents previously disabled retries entirely —
agentStreamDefaultssetretry: { enabled: false }. A single transient serving error (5xx, 429, connection reset) would fail the whole turn.This enables a conservative default that reuses the existing
RetryInterceptor(exponential backoff with full jitter, only retries transient/retryable errors):AppKitErrorwithisRetryable=false) are still never retried — seeisRetryableErrorininterceptors/retry.ts.No new retry logic was added; only the default config value changed.
Streaming / non-idempotency safety (the scope applied)
The agents plugin consumes
retryin exactly one place: the streaming/chatpath viaexecuteStream(agents.ts:1162). This change is streaming-replay-safe by construction, not by configuration:executeStream, the interceptor chain wrapswrappedFn = async () => fn(signal), wherefnis the async generator function for the turn.wrappedFnresolves immediately and theRetryInterceptorsees success on attempt 1.yield*iteration — which runs outside the interceptor chain.The non-streaming
/invocationsand/responsespath (_runAgentNonStreaming) does not route throughexecute()/executeStream()at all, so this default does not affect it.Tests
Added
packages/appkit/src/plugins/agents/tests/defaults.test.ts:attempts === 2, bounded backoff caps).RetryInterceptorexactly asexecuteStreamdoes, throws a 5xx after the first yielded token, and asserts the generator body ran once and the tool side-effect fired once (no replay).Verification
pnpm --filter=@databricks/appkit typecheck— clean.retry.test.ts: 19 passed; newdefaults.test.ts: 3 passed.biome checkon changed files — no fixes/errors.This pull request and its description were written by Isaac.