Skip to main content

Conversations & Persistence

Create a CaesuraO conversation once and save its returned ID. Reuse it for each turn; create another conversation for each independent chat.

Create once and reuse​

import OpenAI from 'openai';
import { createCaesura } from '@caesura-io/openai';

const client = createCaesura(new OpenAI(), { mode: 'sync' });
const conversationId = await client.createConversation({ name: 'Support session' });
if (!conversationId) throw new Error('Could not create a saved conversation.');

await client.responses.create(
{ model: 'gpt-5.4-mini', input: 'Can you help me?' },
{ caesura: { conversationId, turn: { id: 'customer-1', origin: 'customer' } } },
);
from openai import OpenAI
from caesura_core import AnalysisContext, AnalyzeMessage, CustomerTurn
from caesura_openai import CaesuraOpenAIOptions, create_caesura

client = create_caesura(OpenAI(), CaesuraOpenAIOptions(mode="sync"))
conversation_id = client.create_conversation(name="Support session")
if conversation_id is None:
raise RuntimeError("Could not create a saved conversation.")

client.responses.create(
model="gpt-5.4-mini",
input="Can you help me?",
caesura_conversation_id=conversation_id,
caesura_context=AnalysisContext(
turn=CustomerTurn("customer-1", AnalyzeMessage("user", "Can you help me?")),
),
)

The AI SDK middleware also exposes createConversation(). With Python async clients, await create_conversation() and model calls. Under the default continue policy, recoverable creation failures are reported through error hooks and return JavaScript undefined or Python None. The examples above stop when creation fails because they require a saved conversation.

There is no shared default session or automatic mapping from local chat labels. Stateful calls require a conversation ID even with persist: false / persist=False. Explicit stateless calls can omit it, as shown below. Keep your application's local chat identifier separately if needed.

History and customer turns​

Supply customer messages and actual agent replies on every call. The conversation ID does not retrieve history or restore the SDK's guidance store. Keep application history separate from SDK-injected requests.

Use a distinct customer turn ID for each new message, including repeated text. Reuse that ID for retries and tool continuations. System instructions, tool results, retrieval text, and internal events are not customer turns. When your model input mixes dialogue with other content, use explicit dialogue selection as described in the integration guide.

Reusing a turn ID can retry failed message storage, but does not rerun analysis already attempted for that turn. With failurePolicy: 'throw' / failure_policy="raise", a previous failed or unresolved analysis causes the retry to fail too. Check the recorded analysis outcome before deciding how to recover.

What is saved​

HTTP persistence is enabled by default. The SDK saves customer turns and completed agent replies to the same CaesuraO conversation, including customer turns skipped by the analysis cadence. Only customer turns trigger analysis; their results attach to the saved message. Tools, retrieval content, and system instructions are not saved as participant messages.

Consume streams to completion to save their replies. Cancelled, failed, or interrupted replies are not uploaded as completed messages. Record application-provided greetings explicitly with a stable message ID; the SDK cannot observe text your application displays without a model call.

Set persist: false / persist=False to disable this server-side save. Conversation identity, analysis, and guidance injection still work.

To also save a copy in your own storage, configure JavaScript persistMessages or Python persist_transcript. These application callbacks are independent of HTTP persistence. Required analysis-result storage uses persistAnalysis / persist_result.

Message IDs are unique within a conversation. Retry with the same ID, text, and speaker index; changing the saved content or speaker index produces a conflict. Persistence failures follow the configured failure policy. A completed model response cannot be undone if saving it fails, so report the failure and retry the save with the same message ID.

Continuing after storage failures​

Under the default continue policy, a failed save to CaesuraO still permits analysis without hosted persistence for that customer turn. Failed analysis permits a model reply without new guidance; a failed reply save does not withhold the reply. Later calls with the existing conversation ID attempt persistence again. Failed writes are not replayed automatically.

If creation fails, explicitly select a stateless call to continue without an ID:

const conversationId = await client.createConversation({ name: 'Support session' });
await client.responses.create(
{ model: 'gpt-5.4-mini', input: 'Can you help me?' },
{ caesura: conversationId ? { conversationId } : { stateless: true } },
);
conversation_id = client.create_conversation(name="Support session")
client.responses.create(
model="gpt-5.4-mini",
input="Can you help me?",
caesura_conversation_id=conversation_id,
caesura_stateless=conversation_id is None,
)

For AI SDK, pass the same JavaScript options in providerOptions.caesura. Save the returned ID only when creation succeeds. Stateless calls retain no guidance across calls, and application hooks must accept a missing conversation ID. Use sync for guidance in the current reply; background results remain available through completion hooks and flush() / drain().

Use JavaScript failurePolicy: 'throw' or Python failure_policy="raise" when required work must succeed. Caller cancellation and deadlines still stop the call under either policy; ordinary dependency timeouts follow the failure policy. Required application storage hooks retain their own contracts. Configure onError / on_error to observe failures.

Application-provided greetings​

Recording a greeting requires a successfully created conversation. Record greetings you display without a model call. Reuse the message ID when retrying the save, and include the same text in your application dialogue history.

if (conversationId) await client.caesura.recordMessages(conversationId, [{
id: 'greeting-1', role: 'agent', text: 'Hello! How can I help?',
}]);
from caesura_core import TranscriptMessage

if conversation_id is not None:
client.persist_messages(conversation_id, [
TranscriptMessage(id="greeting-1", role="agent", text="Hello! How can I help?"),
])

With Python async clients, await persist_messages(). Recording a greeting does not trigger analysis.

Conversations page​

HTTP-created conversations belong to the account associated with the CaesuraO API key. After messages are saved, find them under API in the source filter on the Conversations page. Select the appropriate date range.

Empty conversations are hidden by default. With persistence disabled, the SDK does not populate the saved conversation.

Application restarts​

The default SDK store is in memory. It retains guidance and assigned message IDs for retries. Save the conversation ID and application history, and use a durable SDK store to retain guidance and retry identities across restarts. Without saved SDK state, previously submitted messages may be saved again. Coordinate concurrent writes to the same conversation; a shared store alone does not coordinate multiple workers.

JavaScript examples · Python examples