Files
pydantic--pydantic-ai/.github/workflows/shared/prompts/pydantic-ai-roundtrip-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
Harness Compat / harness compat (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
chore: import upstream snapshot with attribution
2026-07-13 13:27:52 +08:00

5.2 KiB
Raw Blame History

Pydantic AI Round-Trip Sweep

Objective

Find one concrete state-loss bug across a serialize → deserialize boundary — the highest-density reproducible cluster in this repo. Pick one boundary per run and audit it deeply:

  • ModelMessagesTypeAdapter / to_jsonable_pythonModelMessage round-trip.
  • Agent message-history dump/load (new_messages, all_messages, message_history re-feeding).
  • AG-UI adapter and Vercel AI adapter request/response conversion.
  • Temporal / durable-exec serialization (value_to_type, activity payloads).
  • Deferred-tool / tool-approval round-trip across a run boundary.

How to Verify — mandatory

Construct messages that include the edge-case parts most likely to be lost: thinking/reasoning parts, tool calls + tool returns (with ids), multimodal/binary content, retry/error parts, builtin-tool calls, usage and timestamps, custom result_type/output objects. Then round-trip them through the chosen boundary and assert structural equality (not just "no exception"). Write this as a new minimal test; do not run and report the existing suite. The bug must be one you triggered and observed.

What to Look For

  • Fields silently dropped or defaulted (timestamps, ids, part kinds, usage).
  • Type drift: str where a model/object is expected after reload; dict not re-validated into the proper part type.
  • Ordering changes (tool call/return pairing broken after reload).
  • Asymmetric adapters (encode then decode ≠ identity).
  • Re-fed message_history changing run behavior vs the original run.

What to Skip

  • Speculation without a failing reproduction.
  • By-design lossy fields explicitly documented as such.
  • Behavior already tracked by an open issue or fixed by an open PR — search both first.

Deduplication — mandatory BEFORE filing an issue

The gap may already be tracked by an open issue or already fixed by an open PR — check both. List them through the proxied gh CLI and filter locally — the /search/issues endpoint is blocked by the firewall proxy and there are no mcp__github__* tools.

(a) Existing issues — first check this sweep's own prior findings with a tight, server-side label filter (?labels= on the issue-list endpoint is allowed even though /search/issues is not):

gh api 'repos/pydantic/pydantic-ai/issues?state=open&labels=roundtrip-sweep&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 "round-trip", "serialize", and the boundary/function you investigated:

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

(b) Existing PRs — a fix may already be open (and even approved). List open PRs and scan for one touching the failing symbol or file:

gh api --paginate 'repos/pydantic/pydantic-ai/pulls?state=open&per_page=100' \
  --jq '.[] | {number, title}'

If a matching open issue or PR exists, call mcp__safeoutputs__noop immediately instead of filing. If a PR looks related but you cannot confirm it covers this exact gap, still file but fill in the optional Possibly addressed by #<N> row at the top of the body template (see Issue Format), linking that PR.

Sandbox notes

  • Read files in large ranges (500+ lines per call). Do NOT read in 3080 line chunks.
  • Use the native Grep and Glob tools for codebase search.

Quality Gate — When to Noop

mcp__safeoutputs__noop is the expected outcome most runs. Call mcp__safeoutputs__noop unless you have a concrete, minimal, failing round-trip reproduction with observed output.

Issue Format

Title: <boundary>: <what is lost> on round-trip

Body: (include the first row only for an uncertain PR match; omit it otherwise)

Possibly addressed by # — [link the related open PR]

Impact

[Who is affected; e.g. resumed runs, Temporal workflows, AG-UI clients]

Boundary & Code Path

[Which serialize/deserialize path; file:line]

Reproduction

[The new round-trip test you wrote — full code — and the command]

Expected vs Actual

Expected: input == output. Actual: [diff of what changed]

Evidence

  • [Captured output / diff; path:line references]

Adversarial review

  • Reproduced on main: [exact command + real captured output]
  • Existing tests checked: [adapter/serialization tests read; none assert this loss is intentional, and the fix doesn't break them]
  • Ruled out by-design: [programmatic-only field / request-vs-response union placement / maintainer decision checked]
  • Not a duplicate: [label-filtered dedup returned nothing]