Repository navigation
feat: recover from typed context-length rejections - #42
Merged
Merged
Conversation
danielkov
enabled auto-merge (squash)
October 19, 2026 14:13
danielkov
disabled auto-merge
October 19, 2026 14:49
danielkov
added a commit
that referenced
this pull request
Oct 19, 2026
## Summary Prepare releases for all unpublished package changes and the libraries that must move together with the new loop API. Update 17 package versions, their internal dependency requirements, and the workspace lockfile without changing external dependencies. ## Impact | Packages | Release | | --- | --- | | `agentkit-loop`, `agentkit-adapter-completions`, `agentkit-acp`, `agentkit-compaction`, `agentkit-reporting` | `0.11.0` | | All nine `agentkit-provider-*` crates | `0.11.0` | | `agentkit` facade | `0.12.0` | | `agentkit-mcp` | `0.11.3` | | `how-cli` | `0.10.7` | ## Technical details ### Changes included since published releases Four packages have unpublished source changes relative to their latest non-yanked crates.io archives: loop, OpenAI, and Anthropic include context-rejection recovery and classification from #42; MCP includes advertised catalog subscription capability handling from #41. Anthropic's cached-token usage fix from #38 is already included in published `0.10.11`. The other 12 publishable packages have no unpublished package changes and retain their versions. The existing publish script covers all 29 publishable workspace members in dependency order; no publish-script change is needed. ### Coordinated minor versions The new `ContextRecoveryDeadlineExceeded` variant extends the public, exhaustive `LoopError` enum, requiring a minor release before 1.0. Providers, the completions adapter, compaction, ACP, and reporting expose loop traits or types and therefore move to `0.11.0` together. The facade moves to `0.12.0`; binary-only `how-cli` takes a patch bump. All affected version-bearing internal dependency edges are aligned, including optional facade dependencies and integration-test requirements, so registry builds do not mix incompatible loop type identities. Compaction and reporting receive explicit versions rather than raising the inherited workspace version for unchanged crates. The lockfile changes only the 17 workspace package versions.
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.
Summary
Preserve typed context-length rejections and add opt-in, bounded transcript recovery at the model-request boundary. Hosts can compact canonical history and retry the rejected inference without replaying completed tools.
Motivation
Usage reports can lag unexpectedly large requests. Recovering after a provider rejects the context requires both reliable error classification and a mutation point before the loop terminates the logical turn.
Impact
Recovery is disabled by default. Hosts opt in with
ContextRecoveryPolicyand handleMutationPoint::ContextLengthRejected; AgentKit does not choose what history to remove or estimate whether a request fits. Hosts retaining transcript state must implementTranscriptObserver::on_transcript_replacedto persist committed recovery replacements rather than staged mutator edits.OpenAI Responses HTTP, SSE, and WebSocket paths preserve exact context-length codes, including subscription requests. Confirmed context rejections bypass unchanged-request provider retries. OpenAI chat-completions HTTP and Anthropic HTTP/SSE prompt-length rejections also receive typed classification; generic compatible-provider and completions SSE coverage is unchanged.
Technical details
Transactional and bounded recovery
Recovery mutators edit a staged transcript. The driver validates it and checks cancellation and the shared deadline before committing and notifying replacement observers. Unchanged candidates stop recovery. The retry preserves session/turn identity, tools, and cache settings; any exposed response delta or tool call prevents recovery, including output later superseded by the provider.
Attempt limits and one absolute deadline cover recovery mutations and replacement generation from the first rejection. Production deadline handling remains runtime-agnostic, using the already-locked
futures-timerdependency without introducing package versions or features.Provider-confirmed classification
LoopError::is_context_length_exceeded()uses a sanitized typed code, not rendered error text or generic HTTP 400 status. OpenAI error-body inspection is byte/time bounded. Anthropic classification requires its structured invalid-request envelope and specific prompt-length message prefix. Confirmed errors retain no prompt or error-body text.Integration compatibility
The replacement observer method has a default no-op implementation. Existing mutation-point encodings are unchanged; closed downstream decoders need to recognize
ContextLengthRejectedwhen opting into recovery. The new upstream error kind retains the existing unknown-value fallback.