mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix: strip reasoning item IDs from Responses API input when store=False (#10217)
With store=False (our default for the Responses API), the API does not persist response items. When reasoning items with 'id' fields were replayed on subsequent turns, the API attempted a server-side lookup for those IDs and returned 404: Item with id 'rs_...' not found. Items are not persisted when store is set to false. The encrypted_content blob is self-contained for reasoning chain continuity — the id field is unnecessary and triggers the failed lookup. Fix: strip 'id' from reasoning items in both _chat_messages_to_responses_input (message conversion) and _preflight_codex_input_items (normalization layer). The id is still used for local deduplication but never sent to the API. Reported by @zuogl448 on GPT-5.4.
This commit is contained in:
parent
e69526be79
commit
a4e1842f12
2 changed files with 28 additions and 13 deletions
13
run_agent.py
13
run_agent.py
|
|
@ -3589,7 +3589,12 @@ class AIAgent:
|
|||
item_id = ri.get("id")
|
||||
if item_id and item_id in seen_item_ids:
|
||||
continue
|
||||
items.append(ri)
|
||||
# Strip the "id" field — with store=False the
|
||||
# Responses API cannot look up items by ID and
|
||||
# returns 404. The encrypted_content blob is
|
||||
# self-contained for reasoning chain continuity.
|
||||
replay_item = {k: v for k, v in ri.items() if k != "id"}
|
||||
items.append(replay_item)
|
||||
if item_id:
|
||||
seen_item_ids.add(item_id)
|
||||
has_codex_reasoning = True
|
||||
|
|
@ -3730,8 +3735,10 @@ class AIAgent:
|
|||
continue
|
||||
seen_ids.add(item_id)
|
||||
reasoning_item = {"type": "reasoning", "encrypted_content": encrypted}
|
||||
if isinstance(item_id, str) and item_id:
|
||||
reasoning_item["id"] = item_id
|
||||
# Do NOT include the "id" in the outgoing item — with
|
||||
# store=False (our default) the API tries to resolve the
|
||||
# id server-side and returns 404. The id is still used
|
||||
# above for local deduplication via seen_ids.
|
||||
summary = item.get("summary")
|
||||
if isinstance(summary, list):
|
||||
reasoning_item["summary"] = summary
|
||||
|
|
|
|||
|
|
@ -1249,13 +1249,17 @@ def test_chat_messages_to_responses_input_deduplicates_reasoning_ids(monkeypatch
|
|||
]
|
||||
items = agent._chat_messages_to_responses_input(messages)
|
||||
|
||||
reasoning_ids = [it["id"] for it in items if it.get("type") == "reasoning"]
|
||||
# rs_aaa should appear only once (first occurrence kept)
|
||||
assert reasoning_ids.count("rs_aaa") == 1
|
||||
# rs_bbb and rs_ccc should each appear once
|
||||
assert reasoning_ids.count("rs_bbb") == 1
|
||||
assert reasoning_ids.count("rs_ccc") == 1
|
||||
assert len(reasoning_ids) == 3
|
||||
reasoning_items = [it for it in items if it.get("type") == "reasoning"]
|
||||
# Dedup: rs_aaa appears in both turns but should only be emitted once.
|
||||
# 3 unique items total: enc_1 (from rs_aaa), enc_2 (rs_bbb), enc_3 (rs_ccc).
|
||||
assert len(reasoning_items) == 3
|
||||
encrypted = [it["encrypted_content"] for it in reasoning_items]
|
||||
assert encrypted.count("enc_1") == 1
|
||||
assert "enc_2" in encrypted
|
||||
assert "enc_3" in encrypted
|
||||
# IDs must be stripped — with store=False the API 404s on id lookups.
|
||||
for it in reasoning_items:
|
||||
assert "id" not in it
|
||||
|
||||
|
||||
def test_preflight_codex_input_deduplicates_reasoning_ids(monkeypatch):
|
||||
|
|
@ -1272,7 +1276,11 @@ def test_preflight_codex_input_deduplicates_reasoning_ids(monkeypatch):
|
|||
normalized = agent._preflight_codex_input_items(raw_input)
|
||||
|
||||
reasoning_items = [it for it in normalized if it.get("type") == "reasoning"]
|
||||
reasoning_ids = [it["id"] for it in reasoning_items]
|
||||
assert reasoning_ids.count("rs_xyz") == 1
|
||||
assert reasoning_ids.count("rs_zzz") == 1
|
||||
# rs_xyz duplicate should be collapsed to one item; rs_zzz kept.
|
||||
assert len(reasoning_items) == 2
|
||||
encrypted = [it["encrypted_content"] for it in reasoning_items]
|
||||
assert encrypted.count("enc_a") == 1
|
||||
assert "enc_b" in encrypted
|
||||
# IDs must be stripped — with store=False the API 404s on id lookups.
|
||||
for it in reasoning_items:
|
||||
assert "id" not in it
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue