Developer Dashboard

Conversation State with the Responses API

The Responses API can keep short workflow state for you by linking one response to the next with previous_response_id. Use it when a model needs to continue a conversation, inspect prior tool results, or fork from an earlier response without resending the full transcript.

Adapted from OpenAI's official conversation state documentation, the OpenAI Cookbook, and openai/openai-cookbook, with AvalAI endpoint, API key, and model changes.

When to Use API-Managed State

Use previous_response_id when:

  • a user continues the same task across turns
  • you want to avoid rebuilding the full message list on every request
  • a reasoning or tool workflow needs the model to see prior response items
  • you want to fork from a known response and compare alternative next steps

Keep your own application database as the source of truth for user identity, permissions, long-term memory, business records, and audit logs. API-managed state is a convenience for model context, not a replacement for application state.

For selected facts that must survive independent sessions, build an application-owned layer such as Durable Agent Memory with Embeddings; do not treat an API-managed response chain as long-term memory.

Choose a State Strategy

StrategyUse WhenTradeoff
previous_response_idYou want the API to link turns and preserve recent reasoning or tool contextEasiest to implement, but keep resending important instructions; previous context can still count as input usage
Manual item replayYou need stateless control, custom trimming, or strict auditabilityMore code, but you decide exactly which response.output items return in the next input
Persistent conversation objectYour route explicitly supports the OpenAI-style conversation parameter or Conversations APIUseful for durable server-side threads, but availability is account and route dependent; do not combine it with previous_response_id
CompactionA workflow runs for many turns or has long tool resultsUse server-side or standalone compaction only when the route supports it, preserve returned compaction items, or summarize durable facts, IDs, tool outcomes, assumptions, blockers, and next action yourself

For regulated or data-minimizing workflows, prefer manual item replay with store=False. If reasoning context must continue without stored state, preserve the returned output items your next turn needs instead of relying on the full transcript.

previous_response_id is context management, not free memory. Budget chained requests as if the relevant previous inputs are still part of the model context, and compact or replay only the items you need when a thread grows.

When you rely on previous_response_id, make stored-state intent explicit with store=True/store: true on responses that you plan to continue. When you set store=False, prefer the manual replay pattern below and carry forward the required response.output items yourself.

When a supported route returns a compaction item, treat it as opaque state: do not edit it, summarize over it, or display it to users. For standalone /v1/responses/compact, pass the returned compacted window into the next /v1/responses call as-is.

Storage, Retention, And Billing Notes

OpenAI's native Responses flow stores response objects by default, currently documents a 30-day default retention window for Response objects, and lets you retrieve them later unless you set store=False. OpenAI conversation objects and items are durable outside that Response-object TTL. AvalAI follows the same OpenAI-compatible request shape where supported, but exact retention, zero-retention behavior, and Conversations API availability can vary by route, provider, and account configuration. For production systems, record the AvalAI response ID, your internal request ID, model, user/tenant context, and token usage in your own database instead of relying on hosted state as the only audit trail.

Even when previous_response_id hides transcript plumbing from your code, the relevant prior context still consumes input budget. If a chain grows, summarize durable facts and tool outcomes into a compact state object, then continue with manual item replay or a fresh response chain.

Treat the context window as a shared budget for input, generated output, and—on reasoning models—reasoning tokens. Set an output-token limit that leaves room for the answer, and compact or trim older turns before a growing workflow starts crowding out the model's next response.

If a selected AvalAI route supports Responses WebSocket Mode, treat previous_response_id as the same logical continuation mechanism as HTTP. Keep a full-context recovery path: OpenAI's reference WebSocket behavior uses connection-local state for the most recent previous response, so an uncached or unavailable response ID should fall back to a new turn with full input context instead of assuming the server can always recover the chain.

Continue a Conversation

python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["AVALAI_API_KEY"],
    base_url="https://api.avalai.ir/v1",
)

first = client.responses.create(
    model="gpt-5.5",
    instructions="You are a concise AvalAI onboarding assistant.",
    input="Create a short onboarding checklist for a new API user.",
    store=True,
)

follow_up = client.responses.create(
    model="gpt-5.5",
    instructions="You are a concise AvalAI onboarding assistant.",
    previous_response_id=first.id,
    input="Make it specific to a Python backend developer.",
    store=True,
)

print(follow_up.output_text)
javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.AVALAI_API_KEY,
  baseURL: "https://api.avalai.ir/v1",
});

const first = await client.responses.create({
  model: "gpt-5.5",
  instructions: "You are a concise AvalAI onboarding assistant.",
  input: "Create a short onboarding checklist for a new API user.",
  store: true,
});

const followUp = await client.responses.create({
  model: "gpt-5.5",
  instructions: "You are a concise AvalAI onboarding assistant.",
  previous_response_id: first.id,
  input: "Make it specific to a Python backend developer.",
  store: true,
});

console.log(followUp.output_text);
bash
FIRST_ID=$(curl https://api.avalai.ir/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -d '{
    "model": "gpt-5.5",
    "instructions": "You are a concise AvalAI onboarding assistant.",
    "input": "Create a short onboarding checklist for a new API user.",
    "store": true
  }' | jq -r '.id')

curl https://api.avalai.ir/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AVALAI_API_KEY" \
  -d "{
    \"model\": \"gpt-5.5\",
    \"instructions\": \"You are a concise AvalAI onboarding assistant.\",
    \"previous_response_id\": \"$FIRST_ID\",
    \"input\": \"Make it specific to a Python backend developer.\",
    \"store\": true
  }"

Fork from an Earlier Response

Reusing the same previous_response_id lets you compare alternative next turns from the same base state.

python
base = client.responses.create(
    model="gpt-5.5",
    input="Draft a support reply for a user whose API request returned 429.",
    store=True,
)

technical = client.responses.create(
    model="gpt-5.5",
    previous_response_id=base.id,
    input="Rewrite it for a senior backend engineer.",
    store=True,
)

nontechnical = client.responses.create(
    model="gpt-5.5",
    previous_response_id=base.id,
    input="Rewrite it for a non-technical account owner.",
    store=True,
)

Retrieve a Stored Response

If store is enabled, retrieve a response later for logging, debugging, or delayed processing.

python
response = client.responses.retrieve("resp_abc123")
print(response.output_text)

Set store=False for requests that should not be retained for later retrieval.

Manual Context Carry-Forward

When you do not use previous_response_id, append the previous response.output items you still need to the next input. Preserve item types such as message, reasoning, function_call, and function_call_output; dropping tool or reasoning items can make the next turn less reliable.

For tool-heavy GPT-5-style flows, also preserve any assistant phase value returned in the output items. Intermediate assistant updates may use phase: "commentary" and completed answers may use phase: "final_answer"; if you replay assistant output manually, pass those values through unchanged so an intermediate preamble is not treated like the final answer.

For reasoning models in stateless or zero-retention-style flows, request encrypted reasoning items when your selected AvalAI route supports them: include=["reasoning.encrypted_content"]. Then replay the returned output items in the next request instead of exposing or inventing reasoning text yourself.

python
first = client.responses.create(
    model="gpt-5.5",
    input="Extract the action items from this support note: ...",
    store=False,
    include=["reasoning.encrypted_content"],  # omit if the route does not support it
)

next_input = [
    *first.output,
    {
        "role": "user",
        "content": "Now turn those action items into a customer-safe reply.",
    },
]

second = client.responses.create(
    model="gpt-5.5",
    input=next_input,
    store=False,
    include=["reasoning.encrypted_content"],
)

Best Practices

  • Store response IDs in your own database alongside the user, task, and permission context.
  • Keep instructions explicit on each turn when they are important; top-level instructions from a previous response are not automatically carried into the next previous_response_id request.
  • Do not send previous_response_id together with a conversation object or conversation ID; choose one state mechanism for the request.
  • When manually replaying assistant output, preserve returned phase fields such as commentary and final_answer instead of rewriting assistant history.
  • Use metadata to attach application identifiers such as tenant_id, workflow_id, or request_id.
  • For long-running agents, compact old context into durable facts, open questions, completed actions, and the next concrete goal.
  • Record request IDs and token usage for cost and audit workflows, especially when using chained state.
  • Use Streaming Responses for long responses or realtime UI updates.
  • Use Function Calling when the workflow needs deterministic access to your systems.