For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Primary navigation

Events and items

Consume live updates and retrieve saved work.

Events report what happens as an agent works. Items are the saved messages and tool calls you can retrieve later. Use events to update your application in real time and items to display its saved history.

Your application sends input events to submit messages, cancel turns, or return tool results. The agent sends events that report output and changes to the session. See Run and continue sessions for sending input.

Consume a stream

Subscribe before sending work so your application receives the turn’s early events. Pass your API client, the conversation’s session ID, and an event handler:

Stream session events
def stream_session(client: OpenAI, session_id: str, handle_event):
    with client.beta.agents.sessions.events.stream(session_id) as events:
        for event in events:
            handle_event(event)
            match event.type:
                case "agent.session.idle":
                    continue
                case "error":
                    raise RuntimeError(event.error.message)
                case (
                    "agent.session.turn.completed"
                    | "agent.session.turn.failed"
                    | "agent.session.turn.cancelled"
                ):
                    if event.turn.subagent_id is None:
                        return
    raise RuntimeError("Stream closed before a turn ended. Retrieve the saved state.")

The helper passes each event to your handler, then checks common event types. It continues on agent.session.idle, raises on error, and closes on turn completion, failure, or cancellation. Your handler decides how to display output and handle the outcome. If the stream closes before a turn ends, the helper raises an error. See Recover a disconnected stream.

Send a message after subscribing

This version accepts a message and submits it after opening the stream:

Send and stream a message
def send_and_stream(client: OpenAI, session_id: str, text, handle_event):
    with client.beta.agents.sessions.events.stream(session_id) as events:
        client.beta.agents.sessions.events.create(
            session_id,
            events=[
                {
                    "type": "agent.session.input.message",
                    "input": [
                        {
                            "role": "user",
                            "content": [{"type": "input_text", "text": text}],
                        }
                    ],
                }
            ],
        )
        for event in events:
            handle_event(event)
            match event.type:
                case "agent.session.idle":
                    continue
                case "error":
                    raise RuntimeError(event.error.message)
                case (
                    "agent.session.turn.completed"
                    | "agent.session.turn.failed"
                    | "agent.session.turn.cancelled"
                ):
                    if event.turn.subagent_id is None:
                        return
    raise RuntimeError("Stream closed before a turn ended. Retrieve the saved state.")

Handle updates

Use the event’s type to decide what your application should do:

  • Display text: Append agent.session.turn.output_text.delta to the relevant content part. When agent.session.turn.output_text.done arrives, replace that part with its complete text. Deltas may be absent.
  • Track work: Session, turn, and item events report progress. Check for agent.session.turn.completed, agent.session.turn.failed, or agent.session.turn.cancelled to determine the turn’s outcome.
  • Provide required input: On agent.session.requires_action, retrieve the session and inspect required_actions. Your code may need to return a function result or connect an environment.

An idle session or a closed stream alone does not establish success. A completed turn also does not guarantee that every tool succeeded. Inspect the agent’s output.

Use item_id, output_index, and content_index to connect text updates to the same content part. For example, these abbreviated events update one part:

{
  "type": "agent.session.turn.output_text.delta",
  "item_id": "msg_789",
  "output_index": 0,
  "content_index": 0,
  "delta": "Acme competes"
}
{
  "type": "agent.session.turn.output_text.done",
  "item_id": "msg_789",
  "output_index": 0,
  "content_index": 0,
  "text": "Acme competes on price and distribution."
}

Each event has its own event_id. The shared item_id identifies the saved item, which includes the message’s content, status, and phase. See Retrieve saved work.

See the streaming events reference for all event types and fields. These stream events are distinct from webhooks. For subagent activity and command attribution, see Observe delegation.

Fetch items and turns

Use the session ID from your application’s conversation state to retrieve saved work:

  • Session items: List items to retrieve the root agent’s messages and tool calls across turns.
  • Turns: List turns to browse the session’s work. Retrieve a turn by ID to inspect its status, timestamps, usage, and error.
  • Items from one turn: For a root-agent turn, filter session items by turn_id. Each subagent has its own item history and a per-turn items endpoint.

List endpoints return one page at a time. Use SDK pagination helpers or the after cursor to retrieve more results. A single page may not contain every item for a turn. Use order: "asc" to read items from oldest to newest.

How to recover a disconnected stream

Streams do not replay missed events. To restore your application’s view:

  1. Open a new stream and buffer incoming events.
  2. Retrieve the session and its saved items while the stream stays connected.
  3. Restore your local state from those items, keyed by item ID.
  4. Apply buffered item updates using item_id. Discard updates for items that already reached their final state in the retrieved history.
  5. Resume handling live events.

An output_text.done event can replace a temporary text buffer with the complete text. Saved items let you recover completed work, but not every intermediate event you missed.