Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/codex-store-false.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@electric-ax/agents': patch
---

Stop forcing `store: true` on OpenAI Codex reasoning payloads. The ChatGPT-login Codex endpoint is stateless-only and rejects stateful requests with `{"detail":"Store must be set to false"}`, which broke every Codex (`gpt-5.x`) run. The stateful default now applies to the regular OpenAI Responses API only.
8 changes: 6 additions & 2 deletions packages/agents/src/model-catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,12 @@ function withProviderPayloadDefaults(
// OpenAI Responses reasoning/tool-call continuations replay rs_*
// reasoning items. With store:false, OpenAI does not persist those
// items server-side, which can make follow-up requests fail with
// "Item with id ... not found". Keep Responses stateful for built-ins.
store: true,
// "Item with id ... not found". Keep Responses stateful for the
// regular API. The ChatGPT-login Codex endpoint is the opposite:
// it is stateless-only and rejects any stateful request with
// `{"detail":"Store must be set to false"}`, so it must keep the
// upstream store:false default.
...(choice.provider === `openai` && { store: true }),
reasoning: {
...existingReasoning,
effort,
Expand Down
32 changes: 32 additions & 0 deletions packages/agents/test/model-catalog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,38 @@ describe(`model catalog`, () => {
expect(deepseekConfig.onPayload).toBeUndefined()
})

it(`keeps Codex reasoning model payloads stateless`, async () => {
// The ChatGPT-login Codex endpoint rejects stateful requests with
// `{"detail":"Store must be set to false"}` — the openai branch's
// store:true override must not leak into openai-codex payloads.
delete process.env.OPENAI_API_KEY
process.env.ELECTRIC_CODEX_ACCESS_TOKEN = `test-codex-token`

const catalog = await createBuiltinModelCatalog()
const config = resolveBuiltinModelConfig(catalog!, {
model: `openai-codex:gpt-5.4`,
})

expect(config).toMatchObject({
provider: `openai-codex`,
model: `gpt-5.4`,
})
expect(config.onPayload).toBeTypeOf(`function`)

const payload = config.onPayload!(
{ store: false, reasoning: { effort: `none` } },
{} as any
)

expect(payload).toEqual({
store: false,
reasoning: { effort: `low` },
})
expect(
config.onPayload!({ reasoning: { effort: `none` } }, {} as any)
).not.toHaveProperty(`store`)
})

it(`does not expose providers whose keys are rejected`, async () => {
vi.stubGlobal(
`fetch`,
Expand Down