Files
pydantic--pydantic-ai/.github/workflows/shared/prompts/pydantic-ai-streaming-resilience-sweep.md
T
wehub-resource-sync 9201ef759e
CI / lint (push) Waiting to run
CI / mypy (push) Waiting to run
CI / docs (push) Waiting to run
CI / test on 3.10 (standard) (push) Waiting to run
CI / test on 3.11 (standard) (push) Waiting to run
CI / test on 3.12 (standard) (push) Waiting to run
CI / test on 3.10 (all-extras) (push) Waiting to run
CI / test on 3.11 (all-extras) (push) Waiting to run
CI / test on 3.12 (all-extras) (push) Waiting to run
CI / test on 3.13 (all-extras) (push) Waiting to run
CI / test on 3.14 (pydantic-evals) (push) Waiting to run
CI / test on 3.13 (standard) (push) Waiting to run
CI / test on 3.14 (standard) (push) Waiting to run
CI / test on 3.14 (all-extras) (push) Waiting to run
CI / test on 3.10 (pydantic-ai-slim) (push) Waiting to run
CI / test on 3.11 (pydantic-ai-slim) (push) Waiting to run
CI / test on 3.12 (pydantic-ai-slim) (push) Waiting to run
CI / test on 3.13 (pydantic-ai-slim) (push) Waiting to run
CI / test on 3.14 (pydantic-ai-slim) (push) Waiting to run
CI / test on 3.10 (pydantic-evals) (push) Waiting to run
CI / test on 3.11 (pydantic-evals) (push) Waiting to run
CI / test on 3.12 (pydantic-evals) (push) Waiting to run
CI / test on 3.13 (pydantic-evals) (push) Waiting to run
CI / test on 3.10 (lowest-versions) (push) Waiting to run
CI / test on 3.11 (lowest-versions) (push) Waiting to run
CI / test on 3.12 (lowest-versions) (push) Waiting to run
CI / test on 3.13 (lowest-versions) (push) Waiting to run
CI / test on 3.14 (lowest-versions) (push) Waiting to run
CI / test examples on 3.11 (push) Waiting to run
CI / test examples on 3.12 (push) Waiting to run
CI / test examples on 3.13 (push) Waiting to run
CI / test examples on 3.14 (push) Waiting to run
CI / coverage (push) Blocked by required conditions
CI / check (push) Blocked by required conditions
CI / deploy-docs (push) Blocked by required conditions
CI / deploy-docs-preview (push) Blocked by required conditions
CI / build release artifacts (push) Blocked by required conditions
CI / publish to PyPI (push) Blocked by required conditions
CI / Send tweet (push) Blocked by required conditions
Harness Compat / harness compat (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 13:27:52 +08:00

4.5 KiB

Pydantic AI Streaming Resilience Sweep

The streaming/agent-loop code is in pydantic_ai_slim/pydantic_ai/ (_agent_graph, result, messages, run) and the AG-UI / Vercel adapters.

Objective

Find one concrete bug in the streaming state machine. Streaming is the largest topical cluster and harbors hard-to-spot ordering and lifecycle bugs. Pick one focus area per run:

  • run_stream / StreamedRunResult lifecycle (early exit, double-consume, get_output() before/after completion).
  • agent.iter / _next_node graph node ordering and assertions.
  • event_stream_handler event sequence (start → deltas → end), including for tool calls and thinking parts.
  • Partial / aborted / cancelled streams (network drop, break, timeout) and cleanup.
  • AG-UI / Vercel adapter event ordering and terminal events.
  • Usage / final message assembly when the stream ends or errors mid-way.

How to Verify — mandatory

Use TestModel/FunctionModel or a recorded fixture to drive a deterministic stream. Write a new minimal test asserting the event/None sequence and final message — e.g. no deltas after the final part, tool-call/return pairing intact, usage populated on completion, no StopAsyncIteration/ assertion leakage on early exit. Do not run and report the existing suite.

What to Look For

  • Events emitted out of order, duplicated, or missing a terminal event.
  • State leaking between consumption attempts; get_output() returning stale or partial data.
  • Exceptions/asserts surfacing to the user on normal early termination.
  • Final ModelResponse/usage missing parts that were streamed.
  • Cancellation not cleaning up the underlying provider stream.

What to Skip

  • Provider-specific delta mapping bugs (→ provider mapping sweep).
  • Speculation without a deterministic failing reproduction.
  • Behavior already tracked by an open issue — search issues first.

Deduplication — mandatory BEFORE filing an issue

First narrow to streaming-labelled issues with a tight, server-side filter — the /search/issues endpoint is blocked by the firewall proxy and there are no mcp__github__* tools, but the ?labels= filter on the issue-list endpoint is allowed. This covers both prior [streaming-resilience-sweep] findings and human-filed streaming issues:

gh api 'repos/pydantic/pydantic-ai/issues?state=open&labels=streaming&per_page=100' \
  --jq '.[] | select(.pull_request == null) | {number, title}'

Only if that is inconclusive, widen to a full open-issue scan and grep locally for "stream_output" / "stream_text":

gh api --paginate 'repos/pydantic/pydantic-ai/issues?state=open&per_page=100' \
  --jq '.[] | select(.pull_request == null) | {number, title, labels: [.labels[].name]}'

If a matching issue exists, call mcp__safeoutputs__noop immediately.

Sandbox notes

  • Use FunctionModel with a simple stream function for reproductions — avoid complex model setups.

Quality Gate — When to Noop

mcp__safeoutputs__noop is the expected outcome most runs. Only file with a deterministic, minimal, failing streaming reproduction and captured event trace.

Issue Format

Title: Streaming: <short bug summary>

Body:

Impact

[Who is affected — streaming users, AG-UI clients, agent.iter users]

Focus Area & Code Path

[Which streaming surface; file:line]

Reproduction

[The new streaming test — full code — and the command]

Expected vs Actual

Expected event/result sequence:Actual: … [captured trace]

Evidence

  • [Captured event trace / output; path:line references]

Adversarial review

  • Reproduced on main: [exact command + real captured trace — confirm the asymmetry/failure actually exists, not a false premise]
  • Existing tests checked: [streaming tests read; none assert the current behavior, and the fix doesn't break them]
  • Ruled out by-design: [sibling streaming methods behave the same / nearby comment / maintainer decision checked]
  • Not a duplicate: [label-filtered dedup returned nothing]