Skip to content

Chat Compatibility

The chat layer accepts Chat Completions-style messages and function tools and converts them into a Responses request.

completion = client.chat.completions.create(
    model="model",
    messages=[
        {"role": "system", "content": "Be concise."},
        {"role": "user", "content": "Hello"},
    ],
)
print(completion.choices[0].message.content)

System and developer messages are folded into instructions.

Function calls and finish reasons

Assistant tool history is converted to independent Responses function_call items. Tool results become function_call_output with the same call ID and no Chat role field. Function tool strict is retained.

Returned message.tool_calls uses Chat format:

{"id":"call_1","type":"function","function":{"name":"lookup","arguments":"{}"}}

Arguments remain strings. Streaming chunks carry stable index, initial ID/name, and incremental function.arguments; multiple calls can interleave. Concatenate arguments per index, rather than parsing each fragment. Complete terminal data is not emitted twice.

Finish reasons are tool_calls for completed function calls, stop for ordinary completion, length for a token-limited incomplete response, and content_filter for that incomplete reason. Other incomplete reasons raise StreamError with the provider reason in code. Custom tool output that cannot be represented as a Chat function is rejected; use native Responses for those items.

Optional Codex context

Pass preserve_context=True to request encrypted reasoning context. The result's assistant ChatMessage.provider_data is a versioned envelope containing version, provider, model, and output_items. Use message.to_dict() when saving or reusing it. The envelope is authoritative on replay; the client verifies that the public text and tools still match it and does not duplicate the items.

For streaming, retain the final ChatDelta.provider_data on the assembled assistant message alongside concatenated text and tools. It is a package extension, not a standard Chat Completions field. Preserve it in your persistence layer.

Replay requires the same Codex provider and exact model ID. Unknown versions, model changes, or edited messages raise ValueError before sending. To intentionally edit ordinary Chat history, remove provider_data; this loses opaque reasoning context. Do not decode or display encrypted_content as reasoning text. Incomplete responses do not receive a replay envelope. Context preservation is disabled by default. Both sync and async interfaces support the same options.

Migration

Older versions returned native Responses tool objects in message.tool_calls. Read call["function"]["name"] and call["function"]["arguments"] now, and use call["id"] to link results. Streaming consumers must handle tool deltas and the new finish reasons; incomplete is no longer always reported as stop.