External Publication
Visit Post

`responses` corrupts previous conversations `assistant` item

OpenAI Developer Community May 2, 2026
Source

Thank you for your time on the matter, I was hoping it was something obvious, but I’m still scratching my head. Here’s a bash script to replicate my issue:

#!/usr/bin/env bash
set -eu

: "${OPENAI_API_KEY:?Set OPENAI_API_KEY first}"

BASE="https://api.openai.com/v1"
MODEL="${MODEL:-gpt-5.4-mini}"
SLEEP_AFTER_ASSISTANT_ADD="${SLEEP_AFTER_ASSISTANT_ADD:-2}"

AUTH=(
  -H "Authorization: Bearer $OPENAI_API_KEY"
  -H "Content-Type: application/json"
)

SYSTEM_TEXT="System message containing instructions."
USER_TEXT="Initial user message"
ASSISTANT_TEXT="Assistant message that will disappear."
RESPONSES_INPUT_TEXT="Has the user provided answers to the outstanding fields? "

list_items() {
  curl -sS --globoff \
    "$BASE/conversations/$CONV_ID/items?order=asc&include[]=message.input_image.image_url&limit=100" \
    "${AUTH[@]}"
}

retrieve_item() {
  local item_id="$1"
  curl -sS --globoff \
    "$BASE/conversations/$CONV_ID/items/$item_id?include[]=message.input_image.image_url" \
    "${AUTH[@]}"
}

echo
echo "1) Create conversation with initial system message"

CREATE_CONV_JSON=$(
  jq -n --arg text "$SYSTEM_TEXT" '{
    items: [
      {
        role: "system",
        content: $text,
        type: "message"
      }
    ]
  }'
)

CREATE_CONV_RESPONSE=$(
  curl -sS "$BASE/conversations" \
    "${AUTH[@]}" \
    -d "$CREATE_CONV_JSON"
)

echo "$CREATE_CONV_RESPONSE" | jq .

CONV_ID=$(echo "$CREATE_CONV_RESPONSE" | jq -r '.id')

if [[ "$CONV_ID" == "null" || -z "$CONV_ID" ]]; then
  echo "ERROR: Failed to create conversation"
  exit 1
fi

echo "CONV_ID=$CONV_ID"


echo
echo "2) Add user message to conversation"

ADD_USER_JSON=$(
  jq -n --arg text "$USER_TEXT" '{
    items: [
      {
        type: "message",
        role: "user",
        content: [
          {
            type: "input_text",
            text: $text
          }
        ]
      }
    ]
  }'
)

ADD_USER_RESPONSE=$(
  curl -sS "$BASE/conversations/$CONV_ID/items" \
    "${AUTH[@]}" \
    -d "$ADD_USER_JSON"
)

echo "$ADD_USER_RESPONSE" | jq .

USER_ITEM_ID=$(echo "$ADD_USER_RESPONSE" | jq -r '.data[0].id')
echo "USER_ITEM_ID=$USER_ITEM_ID"


echo
echo "3) Add hard-coded assistant EasyInputMessage to conversation"

ADD_ASSISTANT_JSON=$(
  jq -n --arg text "$ASSISTANT_TEXT" '{
    items: [
      {
        type: "message",
        role: "assistant",
        content: $text,
        phase: "final_answer"
      }
    ]
  }'
)

ADD_ASSISTANT_RESPONSE=$(
  curl -sS "$BASE/conversations/$CONV_ID/items" \
    "${AUTH[@]}" \
    -d "$ADD_ASSISTANT_JSON"
)

echo "$ADD_ASSISTANT_RESPONSE" | jq .

ASSISTANT_ITEM_ID=$(echo "$ADD_ASSISTANT_RESPONSE" | jq -r '.data[0].id')

if [[ "$ASSISTANT_ITEM_ID" == "null" || -z "$ASSISTANT_ITEM_ID" ]]; then
  echo "ERROR: Failed to create assistant item"
  exit 1
fi

echo "ASSISTANT_ITEM_ID=$ASSISTANT_ITEM_ID"


echo
echo "4) Retrieve hard-coded assistant item before Responses call"

RETRIEVE_BEFORE=$(retrieve_item "$ASSISTANT_ITEM_ID")
echo "$RETRIEVE_BEFORE" | jq .


echo
echo "5) List all items before Responses call"

LIST_BEFORE=$(list_items)
echo "$LIST_BEFORE" | jq .

echo
echo "5a) Check hard-coded assistant item is present before Responses call"

if echo "$LIST_BEFORE" | jq -e --arg id "$ASSISTANT_ITEM_ID" '.data[] | select(.id == $id)' >/dev/null; then
  echo "OK: Assistant item is present in list before Responses call"
else
  echo "ERROR: Assistant item is already missing before Responses call"
  exit 1
fi


echo
echo "6) Wait briefly to rule out immediate write/read timing issues"
echo "Sleeping ${SLEEP_AFTER_ASSISTANT_ADD}s..."
sleep "$SLEEP_AFTER_ASSISTANT_ADD"


echo
echo "7) Create model response using SAME conversation ID"

CREATE_RESPONSE_JSON=$(
  jq -n \
    --arg model "$MODEL" \
    --arg conv "$CONV_ID" \
    --arg text "$RESPONSES_INPUT_TEXT" \
    '{
      model: $model,
      conversation: $conv,
      store: true,
      input: [
        {
          content: $text,
          role: "system",
          type: "message"
        }
      ]
    }'
)

CREATE_RESPONSE_RESPONSE=$(
  curl -sS "$BASE/responses" \
    "${AUTH[@]}" \
    -d "$CREATE_RESPONSE_JSON"
)

echo "$CREATE_RESPONSE_RESPONSE" | jq .

RESPONSE_ID=$(echo "$CREATE_RESPONSE_RESPONSE" | jq -r '.id')
echo "RESPONSE_ID=$RESPONSE_ID"


echo
echo "8) Retrieve original hard-coded assistant item after Responses call"

RETRIEVE_AFTER=$(retrieve_item "$ASSISTANT_ITEM_ID")
echo "$RETRIEVE_AFTER" | jq .


echo
echo "9) List all items after Responses call"

LIST_AFTER=$(list_items)
echo "$LIST_AFTER" | jq .


echo
echo "10) Repro checks"

echo
echo "Check A: Is original hard-coded assistant item still present in the list?"

if echo "$LIST_AFTER" | jq -e --arg id "$ASSISTANT_ITEM_ID" '.data[] | select(.id == $id)' >/dev/null; then
  echo "NOT REPRODUCED: Original assistant item is still present in the conversation list"
else
  echo "REPRODUCED: Original assistant item is missing from the conversation list after Responses call"
fi


echo
echo "Check B: Does direct retrieval now return role=unknown and <unknown message>?"

if echo "$RETRIEVE_AFTER" | jq -e '
  .role == "unknown"
  and (.content | length > 0)
  and (.content[0].text == "<unknown message>")
' >/dev/null; then
  echo "REPRODUCED: Direct retrieval returns role=unknown and <unknown message>"
else
  echo "NOT REPRODUCED: Direct retrieval did not return the unknown-message placeholder"
fi


echo
echo "Check C: Show before/after summary for the original assistant item"

echo "Before:"
echo "$RETRIEVE_BEFORE" | jq '{
  id,
  role,
  type,
  status,
  content
}'

echo "After:"
echo "$RETRIEVE_AFTER" | jq '{
  id,
  role,
  type,
  status,
  content
}'


echo
echo "Done."
echo "CONV_ID=$CONV_ID"
echo "ASSISTANT_ITEM_ID=$ASSISTANT_ITEM_ID"
echo "MODEL=$MODEL"

Here’s a play by play of what I’m doing. Hopefully this will make apparent what amateur hour mistake I’ve made.

I create a conversation:

curl --location 'https://api.openai.com/v1/conversations' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer TOKEN' \
--data '{
    "items": [
        {
            "role": "system",
            "content": "System message containing instructions.",
            "type": "message"
        }
    ]
}'

I get the expected response:

{
    "id": "conv_69f5871bb0948193bd42bd2a8649e89f08829a4c83cbc622",
    "object": "conversation",
    "created_at": 1777698587,
    "metadata": {}
}

I add a user message to the conversation:

curl --location 'https://api.openai.com/v1/conversations/conv_69f5871bb0948193bd42bd2a8649e89f08829a4c83cbc622/items' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer TOKEN' \
--data '{
    "items": [
        {
            "type": "message",
            "role": "user",
            "content": [
                {
                    "type": "input_text",
                    "text": "Initial user message"
                }
            ]
        }
    ]
}'

I get the expected response:

{
    "object": "list",
    "data": [
        {
            "id": "msg_69f5878674a481939362d4e7bed94b3808829a4c83cbc622",
            "type": "message",
            "status": "completed",
            "content": [
                {
                    "type": "input_text",
                    "text": "Initial user message"
                }
            ],
            "role": "user"
        }
    ],
    "first_id": "msg_69f5878674a481939362d4e7bed94b3808829a4c83cbc622",
    "has_more": false,
    "last_id": "msg_69f5878674a481939362d4e7bed94b3808829a4c83cbc622"
}

I then add a hard coded assistant message. This message will eventually become corrupted and disappear from the list:

curl --location 'https://api.openai.com/v1/conversations/conv_69f5871bb0948193bd42bd2a8649e89f08829a4c83cbc622/items' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer TOKEN' \
--data '{
    "items": [
        {
            "type": "message",
            "role": "assistant",
            "content": "Assistant message that will disappear.",
            "phase": "final_answer"
        }
    ]
}'

I get the expected response:

{
    "object": "list",
    "data": [
        {
            "id": "msg_69f587a159c881939bd111a2c71142c908829a4c83cbc622",
            "type": "message",
            "status": "completed",
            "content": [
                {
                    "type": "input_text",
                    "text": "Assistant message that will disappear."
                }
            ],
            "role": "assistant"
        }
    ],
    "first_id": "msg_69f587a159c881939bd111a2c71142c908829a4c83cbc622",
    "has_more": false,
    "last_id": "msg_69f587a159c881939bd111a2c71142c908829a4c83cbc622"
}

To double check that the message was added to the conversation, I make a call to get all items in the conversation so far:

curl --location --globoff 'https://api.openai.com/v1/conversations/conv_69f5871bb0948193bd42bd2a8649e89f08829a4c83cbc622/items?order=asc&include[]=message.input_image.image_url&limit=100' \
--header 'Authorization: Bearer TOKEN'

The hard coded assistant message is there:

{
    "object": "list",
    "data": [
        {
            "id": "msg_69f5871bb0bc8193be30f0b1e80313a208829a4c83cbc622",
            "type": "message",
            "status": "completed",
            "content": [
                {
                    "type": "input_text",
                    "text": "System message containing instructions."
                }
            ],
            "role": "system"
        },
        {
            "id": "msg_69f5878674a481939362d4e7bed94b3808829a4c83cbc622",
            "type": "message",
            "status": "completed",
            "content": [
                {
                    "type": "input_text",
                    "text": "Initial user message"
                }
            ],
            "role": "user"
        },
        {
            "id": "msg_69f587a159c881939bd111a2c71142c908829a4c83cbc622",
            "type": "message",
            "status": "completed",
            "content": [
                {
                    "type": "input_text",
                    "text": "Assistant message that will disappear."
                }
            ],
            "role": "assistant"
        }
    ],
    "first_id": "msg_69f5871bb0bc8193be30f0b1e80313a208829a4c83cbc622",
    "has_more": false,
    "last_id": "msg_69f587a159c881939bd111a2c71142c908829a4c83cbc622"
}

I then make a call to the responses endpoint:

curl --location 'https://api.openai.com/v1/responses' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer TOKEN' \
--data '{
    "model": "gpt-5.4-mini",
    "conversation": "conv_69f5871bb0948193bd42bd2a8649e89f08829a4c83cbc622",
    "input": [
        {
            "content": "Has the user provided answers to the outstanding fields? ",
            "role": "system",
            "type": "message"
        }
    ]
}'

And get a response from it:

{
    "id": "resp_08829a4c83cbc6220069f587f985c88193a5a04f15b4d5406e",
    "object": "response",
    "created_at": 1777698810,
    "status": "completed",
    "background": false,
    "billing": {
        "payer": "developer"
    },
    "completed_at": 1777698811,
    "conversation": {
        "id": "conv_69f5871bb0948193bd42bd2a8649e89f08829a4c83cbc622"
    },
    "error": null,
    "frequency_penalty": 0.0,
    "incomplete_details": null,
    "instructions": null,
    "max_output_tokens": null,
    "max_tool_calls": null,
    "model": "gpt-5.4-mini-2026-03-17",
    "moderation": null,
    "output": [
        {
            "id": "msg_08829a4c83cbc6220069f587fafab48193bcb5c61162b541a5",
            "type": "message",
            "status": "completed",
            "content": [
                {
                    "type": "output_text",
                    "annotations": [],
                    "logprobs": [],
                    "text": "No."
                }
            ],
            "phase": "final_answer",
            "role": "assistant"
        }
    ],
    "parallel_tool_calls": true,
    "presence_penalty": 0.0,
    "previous_response_id": null,
    "prompt_cache_key": null,
    "prompt_cache_retention": "in_memory",
    "reasoning": {
        "effort": "none",
        "summary": null
    },
    "safety_identifier": null,
    "service_tier": "default",
    "store": true,
    "temperature": 1.0,
    "text": {
        "format": {
            "type": "text"
        },
        "verbosity": "medium"
    },
    "tool_choice": "auto",
    "tools": [],
    "top_logprobs": 0,
    "top_p": 0.98,
    "truncation": "disabled",
    "usage": {
        "input_tokens": 45,
        "input_tokens_details": {
            "cached_tokens": 0
        },
        "output_tokens": 6,
        "output_tokens_details": {
            "reasoning_tokens": 0
        },
        "total_tokens": 51
    },
    "user": null,
    "metadata": {}
}

I then make another call to get all items in the conversation:

curl --location --globoff 'https://api.openai.com/v1/conversations/conv_69f5871bb0948193bd42bd2a8649e89f08829a4c83cbc622/items?order=asc&include[]=message.input_image.image_url&limit=100' \
--header 'Authorization: Bearer TOKEN'

But now that hard coded assistant message has disappeared:

{
    "object": "list",
    "data": [
        {
            "id": "msg_69f5871bb0bc8193be30f0b1e80313a208829a4c83cbc622",
            "type": "message",
            "status": "completed",
            "content": [
                {
                    "type": "input_text",
                    "text": "System message containing instructions."
                }
            ],
            "role": "system"
        },
        {
            "id": "msg_69f5878674a481939362d4e7bed94b3808829a4c83cbc622",
            "type": "message",
            "status": "completed",
            "content": [
                {
                    "type": "input_text",
                    "text": "Initial user message"
                }
            ],
            "role": "user"
        },
        {
            "id": "msg_08829a4c83cbc6220069f587fa76f48193aee927a5bcde3104",
            "type": "message",
            "status": "completed",
            "content": [
                {
                    "type": "input_text",
                    "text": "Has the user provided answers to the outstanding fields? "
                }
            ],
            "role": "system"
        },
        {
            "id": "msg_08829a4c83cbc6220069f587fafab48193bcb5c61162b541a5",
            "type": "message",
            "status": "completed",
            "content": [
                {
                    "type": "output_text",
                    "annotations": [],
                    "logprobs": [],
                    "text": "No."
                }
            ],
            "role": "assistant"
        }
    ],
    "first_id": "msg_69f5871bb0bc8193be30f0b1e80313a208829a4c83cbc622",
    "has_more": false,
    "last_id": "msg_08829a4c83cbc6220069f587fafab48193bcb5c61162b541a5"
}

If I ask for it specifically:

curl --location --globoff 'https://api.openai.com/v1/conversations/conv_69f5871bb0948193bd42bd2a8649e89f08829a4c83cbc622/items/msg_69f587a159c881939bd111a2c71142c908829a4c83cbc622?order=asc&include[]=message.input_image.image_url&limit=100' \
--header 'Authorization: Bearer TOKEN'

It returns the <unknown message> tag:

{
    "id": "msg_69f587a159c881939bd111a2c71142c908829a4c83cbc622",
    "type": "message",
    "status": "completed",
    "content": [
        {
            "type": "text",
            "text": "<unknown message>"
        }
    ],
    "role": "unknown"
}

Discussion in the ATmosphere

Loading comments...