fix: recover unclassified Responses output items - #29
Open
bjoerndanz wants to merge 1 commit into
Open
Conversation
Signed-off-by: bjoern.danz <bjoern.danz@openrouter.ai> Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Contributor
Original prompt from bjoern.danz
|
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
abhinav-pola
approved these changes
Aug 13, 2026
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.
TL;DR
Recover Responses output items the SDK cannot classify, so an agent loop no longer replays an
UNKNOWNwrapper as an input item and kill the sample on the next request.What changed?
recoverOutputItemsrebuilds an unclassified output item from its raw payload, adds only the envelope fields the SDK requires, and revalidates the result throughoutputItemsFromJSON.idis filled with a deterministic synthetic value derived from the response id and the item index, so a repeated turn produces the same id. Role, status, content, arguments and call ids are never altered.consumeStreamreturns recovered items inoutputand derivestextfrom them, so every downstream consumer and the conversation the agent loop accumulates see typed items only.Why?
An upstream that omits required response-envelope fields also omits them on individual output items. The SDK is forward compatible, so an output message missing
idcomes back as{ type: "UNKNOWN", is_unknown: true, raw: { ... } }rather than raising.The agent loop appends whatever a turn returned into the conversation without restricting item types, so that wrapper is sent as an input item on the following turn.
UNKNOWNmatches none of the 44 accepted input item types, so the SDK rejects the outbound request before any HTTP call withInput validation failed, and the sample is recorded as a model error. The generation that produced the item completed and was billed.Dropping such items instead of recovering them would silently remove an assistant turn or a tool call from the transcript, which corrupts the conversation rather than fixing it, so recovery is attempted first and only genuine failures are dropped and logged.
How to test
Drive a multi-turn tool-bearing exchange against an upstream whose Responses output message items omit
id. Before this change the third request fails withInput validation failednaming an input item deep in the accumulated conversation. After it, the exchange continues, the recovered item carries asynthetic-<response id>-<index>id, and the upstream accepts the replayed item.Benchmark impact
Agentic benchmarks against such an upstream lose whole samples today, which suppresses the affected arm's completion rate without affecting the model's actual output. Recovering the items restores those samples. No dataset, solver or scorer logic changes, and behavior against an upstream that emits complete items is unchanged, since recovery only runs for items the SDK failed to classify.
Reviewer focus
Checklist
Link to Devin session: https://openrouter.devinenterprise.com/sessions/014dc0a17f314a0fb5a8741be8e66fba
Requested by: @bjoerndanz