Open AI Responses API
-
Conversation = the long-lived thread (the big container you append to over time).
-
Response = one model run (the container for this run’s outputs).
-
Item = the atomic node (user/assistant messages, tool calls, tool results, images, structured outputs, etc.). Items can link to each other (forming a little step/tree inside a Response).
Who contains whom?
-
A Conversation stores the full history as a timeline of Items.
-
Each Response produces a set of Items (including your input item and the assistant/tool outputs) and appends them into a target Conversation when you use a
conversation_id. -
Items live inside Responses and are saved under the Conversation; tool calls and tool results are separate Items that reference each other, which is why they can look like a small tree.
Conversation and Response
Example 1 — One conversation, several responses
Conversation C-123 (long-lived thread)
└── Response R-1
│ ├─ Item: user_message("What’s the weather in SF?")
│ ├─ Item: tool_call(getWeather, id=tc1)
│ ├─ Item: tool_result(for tc1, data="72°F, sunny")
│ └─ Item: assistant_message("72°F and sunny.")
│
└── Response R-2
├─ Item: user_message("Plan a 3-hr walk.")
├─ Item: tool_call(routePlanner, id=tc2)
├─ Item: tool_result(for tc2, data="route.json")
└─ Item: assistant_message("Here’s a scenic route…")
-
C-123 contains everything from R-1 and R-2.
-
Each Response groups the Items created in that single run; tool call/result Items link by ID (a small tree).
Example 2 — Two separate conversations (different threads)
Conversation TRAVEL-1
└─ Response A-1
├─ Item: user_message("Find cheap flights to Tokyo.")
├─ Item: tool_call(searchFlights, id=tcA)
├─ Item: tool_result(for tcA, data="price list")
└─ Item: assistant_message("Best options are…")
Conversation WORK-1
└─ Response B-1
├─ Item: user_message("Draft a PRD outline.")
└─ Item: assistant_message("Here’s a PRD template…")
-
Items never cross between conversations; each thread is its own container.
Example 3 — Conversation and responses
E.g. 3.1 — All under the same conversation_id (shared timeline)
Conversation C-123 (long-lived thread)
└── Response R-1
│ └─ (start of the thread)
│
├── Response R-2 (previous_response_id = R-1)
│ └─ (branch A from R-1)
│
└── Response R-3 (previous_response_id = R-1)
└─ (branch B from R-1)
# Now create R-4 from R-2:
└── Response R-4 (previous_response_id = R-2)
NOTE: Because all of these live in the same Conversation C-123,
R-4 will usually "see" R-3 as well (shared context), subject to the model’s context window and truncation.
E.g. 3.2 — No conversation_id, only chaining with previous_response_id (isolated branches)
Chain A
└── Response R-1
└── Response R-2 (previous_response_id = R-1)
└── Response R-4 (previous_response_id = R-2)
Chain B
└── Response R-3 (previous_response_id = R-1)
NOTE: Here, R-4 inherits context only from its own chain (R-2 → R-1).
It does NOT include the sibling branch R-3.
One-liner:
-
Same conversation → branches can see each other (within context limits).
-
Only
previous_response_idchains (no conversation) → branches are isolated.
Response and Item
Example — Zoom-in on one Response’s item tree
Response R-2 (from Example 1)
├─ Item: user_message("Plan a 3-hr walk.")
├─ Item: tool_call(routePlanner, id=tc2)
│ ├─ Item: tool_call(elevationAPI, id=tc2a) (optional nested step)
│ │ └─ Item: tool_result(for tc2a)
│ └─ Item: tool_result(for tc2)
└─ Item: assistant_message("Here’s a scenic route…")
-
This is the in-Response step/tree made of Items (calls ↔ results ↔ final message).
Why the API is designed this way (in brief)
The Responses API unifies message types as Items, supports tool use (tool calls/results as Items), and makes it easy to append state to a Conversation. It’s the recommended foundation for agent-style apps (multi-turn, tool-using).
No comments:
Post a Comment