# 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`