Back to Openai Agents Python

Run Item Lifecycle

.agents/references/run-item-lifecycle.md

0.17.76.0 KB
Original Source

Run Item Lifecycle

Use this reference for changes to model output processing, RunItem types, tool call and output items, stream events, replay conversion, session history, or serialized run state.

Item Flow

The runtime carries one semantic item through several representations:

  1. A model adapter returns provider output in ModelResponse.output.
  2. process_model_response() converts recognized output into public RunItem objects and internal executable tool-run records in ProcessedResponse.
  3. Tool execution and handoffs add output items and choose a SingleStepResult.next_step.
  4. The resulting items feed RunResult, semantic stream events, session persistence, tracing, and RunState serialization.
  5. Replayable items convert back to model input through RunItem.to_input_item() or run_item_to_input_item() after SDK-only metadata is handled.

Keep provider payloads, public run items, and internal execution records distinct. A provider item may be observable without requiring local execution, while a local tool-run record may need to preserve the selected SDK tool object and routing identity.

Generated, Session, and Model Input Views

  • new_step_items describes items generated by the current step.
  • session_step_items preserves the full unfiltered sequence when session history must retain items that a handoff or input filter omitted from the next model request.
  • generated_items is the public observability view and prefers session_step_items when present.
  • Model input is a replay view, not the canonical storage view. Approval placeholders, SDK-only metadata, unsupported IDs, and orphaned calls may need filtering or normalization before an API request.

Do not force these views into one list. History persistence, user-visible results, and the next provider request have different correctness requirements.

Adding or Changing an Item Type

Update every applicable surface together:

  • src/agents/items.py for the public RunItem type, accessors, and replay conversion.
  • src/agents/run_internal/run_steps.py for processed response and executable tool-run records.
  • src/agents/run_internal/turn_resolution.py for provider output recognition, item creation, side effects, and next-step selection.
  • src/agents/run_internal/tool_execution.py, tool_actions.py, or tool_planning.py for execution, dedupe, approvals, and outputs.
  • src/agents/run_internal/items.py for normalization, replay conversion, fingerprints, dedupe, and provider-boundary metadata stripping.
  • src/agents/stream_events.py and streaming queue helpers for public semantic events.
  • src/agents/run_state.py for serialization and deserialization when the item can survive interruption.
  • src/agents/run_internal/session_persistence.py for session conversion, sanitization, and retry accounting.
  • Tracing and usage conversion when the item contributes observable tool or model work.

Compatibility Rules

  • Public stream event names are compatibility-sensitive. Do not rename an existing event, even to fix spelling, without an explicit breaking-change plan.
  • Preserve provider-supplied IDs and opaque provider data until the owning boundary deliberately removes them. Do not invent IDs or coerce malformed values to make replay appear valid.
  • Preserve SDK-only metadata needed for display, routing, approvals, tool origin, or resume, but strip it before sending payloads to a provider that does not accept it.
  • Tool call and output pairs must retain the same string call ID across execution, replay, session persistence, and resume.
  • Empty, falsey, structured, image, file, and custom tool outputs are valid values unless the public tool contract explicitly rejects them; do not use broad truthiness checks to decide whether output exists.

Replay Integrity

  • Prune orphan calls only from runner-generated or resumed history where the SDK owns call/output pairing. Preserve caller-supplied initial input unless an explicit public normalization contract says otherwise.
  • When dropping an orphan tool call, also drop reasoning items tied to that removed call so the provider does not receive a reasoning item without its required following item. Do not drop a lone reasoning item merely because its following item is absent locally; server-managed conversation state may own that item.
  • reasoning_item_id_policy="omit" strips IDs only from SDK-generated follow-up reasoning items. It does not rewrite initial caller input, must survive RunState resume, and can be superseded by a later call_model_input_filter that deliberately returns IDs.
  • Pair anonymous tool-search outputs with the latest compatible anonymous call and never pair a named call with an anonymous output. A missing call ID does not justify inventing a persistent provider identity.
  • provider_data and provider IDs have boundary-specific ownership. Preserve them for raw results and provider requests that accept them, but strip private or replay-unsafe metadata from session and server-conversation history where the SDK contract requires sanitized items.

Review Checklist

  1. Follow the item from provider response through result, stream, session, replay, and RunState.
  2. Test both typed provider objects and mapping payloads when adapters support both.
  3. Verify IDs, metadata, and output values survive every required round-trip.
  4. Test filtering and dedupe without losing the latest valid call/output pair.
  5. Compare streaming event order with the non-streaming item sequence.
  6. Test orphan pruning and reasoning pairing with client-managed replay and server-managed continuation separately.

Sources

  • src/agents/items.py
  • src/agents/stream_events.py
  • src/agents/run_internal/items.py
  • src/agents/run_internal/run_steps.py
  • src/agents/run_internal/turn_resolution.py
  • src/agents/run_internal/session_persistence.py
  • src/agents/run_state.py
  • tests/test_items_helpers.py
  • tests/test_run_internal_items.py
  • tests/test_stream_events.py
  • tests/test_run_state.py
  • docs/running_agents.md
  • docs/results.md