Skip to content

Commit 1fcb6d4

Browse files
committed
Updated doc to mention how you'd use previous_response_id
1 parent c1f1613 commit 1fcb6d4

1 file changed

Lines changed: 58 additions & 10 deletions

File tree

docs/guides/respond-to-user-message.md

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class MyRequestContext:
3333

3434
### Implement your `ChatKitServer`
3535

36-
Subclass `ChatKitServer` and implement `respond`. It runs once per user turn and should yield the events that make up your response. Well keep this example simple for now and fill in history loading and model calls in later sections.
36+
Subclass `ChatKitServer` and implement `respond`. It runs once per user turn and should yield the events that make up your response. We'll keep this example simple for now and fill in history loading and model calls in later sections.
3737

3838
```python
3939
from collections.abc import AsyncIterator
@@ -175,17 +175,21 @@ class MyPostgresStore(Store[RequestContext]):
175175
# Implement the remaining Store methods following the same pattern.
176176
```
177177

178-
Customize ID generation by overriding `generate_thread_id` and `generate_item_id` if you need external or deterministic IDs. Store metadata such as `previous_response_id` on `ThreadMetadata` to drive your inference pipeline.
178+
Customize ID generation by overriding `generate_thread_id` and `generate_item_id` if you need external or deterministic IDs. Store metadata such as a model `last_response_id` on `ThreadMetadata` to drive your inference pipeline.
179179

180180
## Generate a response using your model
181181

182-
Inside `respond`, youll usually:
182+
Inside `respond`, you'll usually:
183183

184184
1. Load recent thread history.
185185
2. Prepare model input for your agent.
186186
3. Run inference and stream events back to the client.
187187

188-
### Load thread history inside `respond`
188+
### Prepare model input
189+
190+
Before you call your model, decide what conversation context you want the model to see.
191+
192+
#### Load thread history (recommended default)
189193

190194
Fetch recent items so the model sees the conversation state before you build the next turn:
191195

@@ -200,24 +204,68 @@ items_page = await self.store.load_thread_items(
200204
items = list(reversed(items_page.data))
201205
```
202206

203-
### Prepare model input
204-
205-
Use the defaults first: `simple_to_agent_input` converts user items into Agents SDK inputs, and `ThreadItemConverter` handles other item types. Override converter methods if you need special handling for hidden context, attachments, or tags.
206-
207-
Respect any `input.inference_options` the client sends (model, tool choice, etc.) when you build your request to the model.
207+
- Start with the defaults: `simple_to_agent_input(items)` is a convenience wrapper around the **default** `ThreadItemConverter` (it calls `ThreadItemConverter().to_agent_input(items)` under the hood).
208+
- Customize for your integration: some item types require app-specific translation into model input (for example: **attachments**, **tags**, and some **hidden context items**). In those cases, subclass `ThreadItemConverter` and call your converter directly instead of `simple_to_agent_input`. (If your thread includes attachments/tags and you haven't implemented the converter hooks, conversion will raise `NotImplementedError`.)
208209

209210
```python
210211
from agents import Runner
211-
from chatkit.agents import AgentContext, simple_to_agent_input
212212

213+
from chatkit.agents import AgentContext, ThreadItemConverter, simple_to_agent_input
214+
215+
216+
# Option A (defaults):
213217
input_items = await simple_to_agent_input(items)
218+
219+
# Option B (your integration-specific converter):
220+
# input_items = await MyThreadItemConverter().to_agent_input(items)
221+
214222
agent_context = AgentContext(
215223
thread=thread,
216224
store=self.store,
217225
request_context=context,
218226
)
219227
```
220228

229+
Respect any `input.inference_options` the client sends (model, tool choice, etc.) when you build your request to the model.
230+
231+
#### Using `previous_response_id` (OpenAI Responses API only)
232+
233+
If you are using OpenAI models through the **Responses API**, you can pass `previous_response_id` to `Runner.run_streamed(...)` and (often) send only the *new* user message as model input. This can simplify input construction when the provider can retrieve prior context server-side.
234+
235+
Terminology note: Agents exposes the ID of the most recent model response as `result.last_response_id`. On the *next* turn, you pass that saved value as the `previous_response_id` parameter.
236+
237+
**Important restrictions:**
238+
239+
- **OpenAI Responses API only.** Other model providers won't be able to follow a `previous_response_id`, so you must send thread history yourself.
240+
- **Only includes model-visible history.** If your integration streams ChatKit-only items (e.g. widgets/workflows emitted directly to the client), the model won't know about them unless you also include them in `input_items`.
241+
- **Works only while the referenced response is retrievable.** Persist `result.last_response_id` and ensure responses are stored (`store=True` / `ModelSettings(store=True)`); otherwise fall back to rebuilding input from thread items.
242+
243+
Example:
244+
245+
```python
246+
# `ThreadMetadata.metadata` is a free-form dict for integration-specific state.
247+
# ChatKit does not define a first-class `last_response_id` field on `ThreadMetadata`;
248+
# your integration can store it under a key and reuse it on the next turn.
249+
last_response_id = thread.metadata.get("last_response_id")
250+
last_response_id = last_response_id if isinstance(last_response_id, str) else None
251+
252+
# Often: send only the new message as input when chaining on the server.
253+
input_items = await simple_to_agent_input(input)
254+
255+
result = Runner.run_streamed(
256+
assistant_agent,
257+
input_items,
258+
context=agent_context,
259+
previous_response_id=last_response_id,
260+
auto_previous_response_id=True,
261+
)
262+
263+
# Persist the new response ID so the next turn can chain again.
264+
if result.last_response_id:
265+
thread.metadata["last_response_id"] = result.last_response_id
266+
await self.store.save_thread(thread, context=context)
267+
```
268+
221269
### Run inference and stream events
222270

223271
Run your agent and stream events back to the client. `stream_agent_response` converts an Agents run into ChatKit events; you can also yield events manually.

0 commit comments

Comments
 (0)