feat(sdk): ProviderSettings.storeResponses for OpenAI Responses API#97
Closed
ketankhairnar wants to merge 1 commit into
Closed
feat(sdk): ProviderSettings.storeResponses for OpenAI Responses API#97ketankhairnar wants to merge 1 commit into
ketankhairnar wants to merge 1 commit into
Conversation
Adds an opt-in `providers.openai.storeResponses?: boolean` knob on ProviderSettings. When set, an `onPayload` hook on the underlying agent runtime mutates OpenAI Responses API request payloads to include `store: <bool>` just before the request is sent. Default unset preserves current behavior (pi-ai hardcodes `store: false`). Resolves the multi-turn 404 reported in withastro#77: pi-ai's conversation converter emits item references (`fc_*`, `msg_*`) on later turns, but those items never get persisted server-side, so subsequent `session.task()` calls get a 404 from the OpenAI Responses API. Setting `store: true` opts the conversation into OpenAI's server-side storage so the references resolve. Scoped to `model.api === 'openai-responses'` only. The hook is a no-op for Codex (which rejects `store: true`), Azure, Anthropic, and every other provider — they see `undefined` from the hook and pi-ai keeps the payload unchanged. Usage: init({ providers: { openai: { storeResponses: true } }, }); Privacy note: enabling this opts the conversation into OpenAI's server-side storage and its retention policy. Default off is intentional.
Member
|
Thanks for digging into this @ketankhairnar — your diagnosis (pi-ai's hardcoded Landed in 83ba598 with two changes:
You're credited as co-author on the commit. Closing this in favor of the merged commit. Thanks again! |
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
Adds an opt-in
providers.openai.storeResponses?: booleanknob onProviderSettings. When set, the SDK injectsstore: <bool>into OpenAI Responses API request payloads via anonPayloadhook on the underlying agent runtime. Default unset preserves current behavior.Resolves the multi-turn 404 reported in #77.
Why
pi-ai (
@mariozechner/pi-ai) hardcodesstore: falseon the OpenAI Responses provider. The conversation converter then emits per-item references (fc_*,msg_*) on subsequent turns, but those items never get persisted server-side. So a secondsession.prompt()orsession.task()call on the same session returns a 404 from OpenAI: "Items are not persisted when store is set to false."The runtime exposes an
onPayloadhook that lets us mutate the request just before it's sent. Wiringstore: truethrough that hook is non-breaking and avoids forking pi-ai.What's in this PR
packages/sdk/src/types.ts— addsstoreResponses?: booleantoProviderSettings. Doc-commented with the multi-turn use case + the data-retention trade-off.packages/sdk/src/session.ts:buildOpenAIStorePayloadHook(providers)helper that returns anonPayloadcallback (orundefinedwhen the knob is unset).model.api === 'openai-responses'guarded — it's a no-op for Codex (which rejectsstore: true), Azure, Anthropic, and every other provider.Agentconstructor at session init.Net diff: +38 / -0 across 2 files.
Non-breaking by design
store: false) ships unchanged.model.apiguard means non-OpenAI-Responses models never see the mutation.store: trueserver-side; the guard prevents that path from ever firing foropenai-codex-responses.Usage
What's NOT in the PR
mainyet; matching the same deferral pattern as feat(sdk): optional saveDelta hook on SessionStore #95. Fake-stream + payload-assertion tests will land in a follow-up after the test infra branch (feat/test-infra) merges.Design notes
The flat
storeResponses: booleanshape was chosen over a nestedopenai: { store: boolean }for readability. If reviewers prefer the nested shape (e.g. to keep room for future Responses-only flags likeservice_tierorprompt_cache_retention), happy to reshape — discussed in MEMO.The naming (
storeResponsesvsstore) is intentional.storewould be ambiguous with persistence-layer concepts (theSessionStoreinterface uses the same word for client-side persistence).storeResponsesmakes it clear this is server-side conversation storage on the provider, distinct from any local persistence the user has wired up.Open question (verified, no blocker)
Per RECIPE.md analysis: in pi-ai's openai-responses provider, the conversation converter currently passes per-item
ids but does not setprevious_response_id. OpenAI's Responses API supports both linking strategies. Settingstore: truealone is sufficient — the per-item references resolve once items are persisted. If a future change wants to also passprevious_response_id, the sameonPayloadhook is the right seam.Refs
saveDelta?hook, also non-breaking SDK addition)Test plan
pnpm check:typespasses on thepackages/sdkworkspace.session.task()againstopenai/gpt-5succeeds whenstoreResponses: trueis set.