Skip to content

chore: merge 1.0-dev into main#992

Merged
ishymko merged 189 commits intomainfrom
1.0-dev
Apr 20, 2026
Merged

chore: merge 1.0-dev into main#992
ishymko merged 189 commits intomainfrom
1.0-dev

Conversation

@ishymko
Copy link
Copy Markdown
Member

@ishymko ishymko commented Apr 20, 2026

Consolidate 1.0 development and merge into main.

Known CI failures which are going to be ignored:

  1. TCK - is not ready for 1.0, will be disabled after merge.
  2. Lint - copy-paste detection fails due to GitHub API error as the PR has too large diff (link).

lkawka and others added 30 commits November 13, 2025 11:12
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
Co-authored-by: Yaroslav <yarolegovich@gmail.com>
Co-authored-by: Agent2Agent (A2A) Bot <a2a-bot@google.com>
Co-authored-by: agil.yolchuyev <agilyolchuyev@outlook.com>
Co-authored-by: yolagil <agil@peotic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com>
Co-authored-by: Luca Muscariello <muscariello@ieee.org>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…the specification (#511)

Commit:
a2aproject/A2A@0a9f629

This PR introduces support for the new `tasks/list` method, including:
- Automatically generated type definitions from the specification.
- Complete client-side and server-side implementations.

Fixes #515 🦕

---------

Co-authored-by: lkawka <lkawka@google.com>
Co-authored-by: lkawka <luk.kawka@gmail.com>
Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com>
Co-authored-by: Iva Sokolaj <102302011+sokoliva@users.noreply.github.com>
Co-authored-by: Agent2Agent (A2A) Bot <a2a-bot@google.com>
Co-authored-by: Tadaki Asechi <127199356+TadakiAsechi@users.noreply.github.com>
Co-authored-by: tadaki <tadaki.asechi@gmail.com>
Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com>
Co-authored-by: TadakiAsechi <tadaki.asechi@icould.com>
Co-authored-by: TadakiAsechi <tadaki.asechi@iclould.com>
## Summary

This PR migrates the a2a-python SDK from Pydantic-based types to
protobuf-generated types, completing the upgrade to A2A v1.0. Fixes #559

## Breaking Changes

- Replace Pydantic-based type system with protobuf types from `a2a_pb2`
- Update `Part` usage from `Part(root=TextPart(text=...))` to
`Part(text=...)`
- Update `Role` enum from `Role.user`/`Role.agent` to
`Role.ROLE_USER`/`Role.ROLE_AGENT`
- Update `TaskState` enum to use `TASK_STATE_*` prefix

## Changes

- Update all source files to use proto types directly from `a2a_pb2`
- Replace `model_dump()` with `MessageToDict()` for JSON serialization
- Replace `model_copy(deep=True)` with `CopyFrom()` for proto cloning
- Add new types module with proto imports and SDK-specific extras
- Add `proto_utils` module with identity conversion utilities
- Fix REST handler resource name formats for push notification configs
- Fix gRPC handler to use `SubscribeToTask` instead of
`TaskSubscription`
- Fix database task store to handle proto objects from ORM
- Update all test files for proto patterns and assertions
- Fix spelling check failures by updating allow list
- Fix inclusive language check failures:
    - Replace `master` with `main` in documentation
    - Rename `Dummy` classes to `Mock` in tests

## Testing

- **601 tests passing**
- 23 tests skipped (expected - require DB connections or cryptography
deps)

## Related

Builds on top of PR #556

Release-As: 1.0.0

---------

Signed-off-by: Luca Muscariello <muscariello@ieee.org>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Sam Betts <1769706+Tehsmash@users.noreply.github.com>
Co-authored-by: Lukasz Kawka <luk.kawka@gmail.com>
Co-authored-by: Agent2Agent (A2A) Bot <a2a-bot@google.com>
Co-authored-by: Didier Durand <2927957+didier-durand@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Iva Sokolaj <102302011+sokoliva@users.noreply.github.com>
Co-authored-by: Will Chen <36873565+chenweiyang0204@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
# Description

Do not use `NULLS LAST` which is not available in MySQL, coalesce nulls
to empty strings which will appear last in descending ordering (there
are tests for this behavior already, however CI wasn't enabled for this
branch).

Currently `NULLS LAST` fails MySQL tests:

```
(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULLS LAST, tasks.id DESC \n LIMIT 51' at line 3")
```
([actions
run](https://github.com/a2aproject/a2a-python/actions/runs/21520017047/job/62008309612?pr=651))

Enable tests run against `1.0-dev` to prevent it in the future.

Re #511 
Fixes #652 

---
Mark as "refactor" for release please as it's a fix for a non-released
feature, hence shouldn't get into a changelog.

BEGIN_COMMIT_OVERRIDE
refactor: use MySQL compatible syntax in list tasks
END_COMMIT_OVERRIDE
# Conflicts:
#	CHANGELOG.md
#	tests/client/transports/test_rest_client.py
#	tests/utils/test_proto_utils.py
# Description

Merge `main` into `1.0-dev` through an intermediate branch to resolve
conflicts. Opening a PR from `main` to `1.0-dev` required pushing to
`main` to resolve conflicts.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Iva Sokolaj <102302011+sokoliva@users.noreply.github.com>
Co-authored-by: Agent2Agent (A2A) Bot <a2a-bot@google.com>
Co-authored-by: Tadaki Asechi <127199356+TadakiAsechi@users.noreply.github.com>
Co-authored-by: tadaki <tadaki.asechi@gmail.com>
Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com>
Co-authored-by: TadakiAsechi <tadaki.asechi@icould.com>
Co-authored-by: TadakiAsechi <tadaki.asechi@iclould.com>
Co-authored-by: ShishirRmc <113575088+ShishirRmc@users.noreply.github.com>
Co-authored-by: Lukasz Kawka <luk.kawka@gmail.com>
Co-authored-by: Didier Durand <2927957+didier-durand@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Will Chen <36873565+chenweiyang0204@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Vinay Ramesh <vinay.r.ramesh@gmail.com>
# Description

Run linter on `1.0-dev`.
This reverts commit 40613ed.

Should be merged without squashing
## Description
Updates the SDK to support the A2A Protocol v1.0.0-rc specifications.

## Changes
- **Protocol Update**: Updated core types, definitions, `Client`, and
`Server` implementations to match Protocol v1.0.0-rc.
- **Bug Fixes**:
    - Fixed `RestTransport` URL construction.
- Resolved `pyright`, `ruff`, and `mypy` linting errors across the
codebase.
- Fixed import resolution issues for optional dependencies (`grpc`,
`sqlalchemy`, `opentelemetry`).
- **Tests**:
    - Fixed all failing unit and integration tests.
- Added support for running PostgreSQL and MySQL integration tests
(verified locally).
- **Cleanup**: Removed redundant `pyrightconfig.json`.

## Testing
- All unit and integration tests are passing.
- Database integration tests verified locally with Docker containers
(docker-compose file was used for verification but is not included in
the repo).

Re #559

---------

Signed-off-by: Luca Muscariello <muscariello@ieee.org>
To resolve existing merge issues first.
Fixes
#697 (comment),
bad merge in #696.

Cover "list tasks" in client-server integration tests which would
prevent it.

Re #559.
Bring back `.pre-commit-config.yaml` and disabled JSCPD linter.

Removal can be evaluated separately, for now bringing them back to make
diff against `main` more focused.

Re #559.
Tests basic functionality with real client and server with real
handlers, only agent executor is provided in test as it'd be in a real
usage.

Re #559
JSON-RPC diverged a bit, update it to match other transports. Domain
request handler returns `Task | Message` from `on_message_send` already.

Fixes
#697 (comment).

Re #559.
According to [the
spec](https://a2a-protocol.org/latest/specification/#314-list-tasks) all
response fields are mandatory. Update implementation and add tests to
cover.

Re #515
Active updates are happening to [A2A
repo](https://github.com/a2aproject/A2A/commits/main/) currently. Switch
`buf.gen.yaml` back to `main` (#699 switched it to the 1.0 RC tag to
progress with merge without regenerating files) and update code to work
with the latest changes.

Re #559.
Following

> The operation MUST return a Task object as the first event in the
stream

introduced in 1.0:
https://a2a-protocol.org/latest/specification/#316-subscribe-to-task

It also correctly uses `UnsupportedOperationError` as per the "Errors"
section from the documentation linked above.

Fixes #675

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
According to
https://a2a-protocol.org/latest/specification/#324-history-length-semantics.
It changes behavior so the fix was postponed till 1.0.

After changing to proto passing `.history_length` would not work anymore
due to the way how proto generated code works - optional values are
still translated to language defaults to avoid `None`s, while presence
should be checked via `HasField` - done in this PR.

Fixes #573

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
## Description

As per the 1.0 spec update (see [4.3.3. Push Notification
Payload](https://a2a-protocol.org/latest/specification/#433-push-notification-payload))
use `StreamResponse` as push notifications payload.

Fixes #678

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Use enum everywhere, data model uses `str` for protocol names, so custom
protocols won't be constrained with the enum.

Fixes #705
ishymko and others added 25 commits April 9, 2026 16:02
Based on
https://a2a-protocol.org/latest/specification/#312-send-streaming-message:
1. `Message` based flow.
2. Emit `Task` as a first event.

# TODO: switches to the old request handler as there are known issues in
the new one

With a new handler failures are caused by
1. `Task` events are not streamed 
2. `return_immediately` + direct message - V2 returns a phantom `Task`
before the executor produces its `Message`
# Description

Do one iteration to catch exceptions occurred beforehand to return an
error instead of sending headers for SSE.
Simplify ActiveTask.subscribe() and remove race condition between
_is_finished and slow enqueue.

Fixes #869 🦕
Fixes Task object handling when using new DefaultRequestHandlerV2.

Fixes #869🦕
🤖 I have created a release *beep* *boop*
---


##
[1.0.0-alpha.1](v1.0.0-alpha.0...v1.0.0-alpha.1)
(2026-04-10)


### ⚠ BREAKING CHANGES

* **client:** make ClientConfig.push_notification_config singular
([#955](#955))
* **client:** reorganize ClientFactory API
([#947](#947))
* **server:** add build_user function to DefaultContextBuilder to allow
A2A user creation customization
([#925](#925))
* **client:** remove `ClientTaskManager` and `Consumers` from client
([#916](#916))
* **server:** migrate from Application wrappers to Starlette route-based
endpoints for rest
([#892](#892))
* **server:** migrate from Application wrappers to Starlette route-based
endpoints for jsonrpc
([#873](#873))

### Features

* A2A Version Header validation on server side.
([#865](#865))
([b261ceb](b261ceb))
* Add GetExtendedAgentCard Support to RequestHandlers
([#919](#919))
([2159140](2159140))
* Add support for more Task Message and Artifact fields in the Vertex
Task Store ([#936](#936))
([605fa49](605fa49))
* Create EventQueue interface and make tap() async.
([#914](#914))
([9ccf99c](9ccf99c)),
closes [#869](#869)
* EventQueue - unify implementation between python versions
([#877](#877))
([7437b88](7437b88)),
closes [#869](#869)
* EventQueue is now a simple interface with single enqueue_event method.
([#944](#944))
([f0e1d74](f0e1d74))
* Implementation of DefaultRequestHandlerV2
([#933](#933))
([462eb3c](462eb3c)),
closes [#869](#869)
* InMemoryTaskStore creates a copy of Task by default to make it
consistent with database task stores
([#887](#887))
([8c65e84](8c65e84)),
closes [#869](#869)
* merge metadata of new and old artifact when append=True
([#945](#945))
([cc094aa](cc094aa))
* **server:** add async context manager support to EventQueue
([#743](#743))
([f68b22f](f68b22f))
* **server:** validate presence according to `google.api.field_behavior`
annotations
([#870](#870))
([4586c3e](4586c3e))
* Simplify ActiveTask.subscribe()
([#958](#958))
([62e5e59](62e5e59))
* Support AgentExectuor enqueue of a Task object.
([#960](#960))
([12ce017](12ce017))
* Support Message-only simplified execution without creating Task
([#956](#956))
([354fdfb](354fdfb))
* Unhandled exception in AgentExecutor marks task as failed
([#943](#943))
([4fc6b54](4fc6b54))


### Bug Fixes

* Add `packaging` to base dependencies
([#897](#897))
([7a9aec7](7a9aec7))
* **client:** do not mutate SendMessageRequest in
BaseClient.send_message
([#949](#949))
([94537c3](94537c3))
* fix `athrow()` RuntimeError on streaming responses
([#912](#912))
([ca7edc3](ca7edc3))
* fix docstrings related to `CallContextBuilder` args in constructors
and make ServerCallContext mandatory in `compat` folder
([#907](#907))
([9cade9b](9cade9b))
* fix error handling for gRPC and SSE streaming
([#879](#879))
([2b323d0](2b323d0))
* fix JSONRPC error handling
([#957](#957))
([6c807d5](6c807d5))
* fix REST error handling
([#893](#893))
([405be3f](405be3f))
* handle SSE errors occurred after stream started
([#894](#894))
([3a68d8f](3a68d8f))
* remove the use of deprecated types from VertexTaskStore
([#889](#889))
([6d49122](6d49122))
* Remove unconditional SQLAlchemy dependency from SDK core
([#898](#898))
([ab762f0](ab762f0)),
closes [#883](#883)
* remove unused import and request for FastAPI in pyproject
([#934](#934))
([fe5de77](fe5de77))
* replace stale entry in a2a.types.__all__ with actual import name
([#902](#902))
([05cd5e9](05cd5e9))
* wrong method name for ExtendedAgentCard endpoint in JsonRpc compat
version ([#931](#931))
([5d22186](5d22186))


### Documentation

* add Database Migration Documentation
([#864](#864))
([fd12dff](fd12dff))


### Miscellaneous Chores

* release 1.0.0-alpha.1
([a61f6d4](a61f6d4))


### Code Refactoring

* **client:** make ClientConfig.push_notification_config singular
([#955](#955))
([be4c5ff](be4c5ff))
* **client:** remove `ClientTaskManager` and `Consumers` from client
([#916](#916))
([97058bb](97058bb)),
closes [#734](#734)
* **client:** reorganize ClientFactory API
([#947](#947))
([01b3b2c](01b3b2c))
* **server:** add build_user function to DefaultContextBuilder to allow
A2A user creation customization
([#925](#925))
([2648c5e](2648c5e))
* **server:** migrate from Application wrappers to Starlette route-based
endpoints for jsonrpc
([#873](#873))
([734d062](734d062))
* **server:** migrate from Application wrappers to Starlette route-based
endpoints for rest
([#892](#892))
([4be2064](4be2064))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
…ent (#970)

# Description
Updates the sample agent and CLI to correctly follow the A2A streaming
event contract, where the first event in a stream must be a `Task` or a
`Message` object in `TASK_STATE_SUBMITTED` state.

# Changes
 **hello_world_agent.py** 
`SampleAgentExecutor.execute()` now enqueues a
`Task(TASK_STATE_SUBMITTED)` object as its very first event, before any
TaskUpdater calls. The initial user message is included in the Task's
history field, since the consumer sets message_to_save = None upon
receiving a Task event (expecting the task to carry the message itself).


**cli.py** 
Updates `_handle_stream` to match the new event contract:
The first event is now expected to be a `Message` or a `Task` (not an
(event, task) tuple), and its id is used to initialize
`current_task_id`.

**README.md**
Adds a `README.md` for the samples.

# Tested
```
uv run samples/cli.py 
Connecting to http://127.0.0.1:41241 (preferred transport: Any)

✓ Agent Card Found:
  Name: Sample Agent
  Picked Transport: JsonRpcTransport

Connected! Send a message or type /quit to exit.
You: hi
Task [state=TASK_STATE_SUBMITTED]
TaskStatusUpdate [state=TASK_STATE_WORKING]: Processing your question... 
TaskArtifactUpdate [name=response]: Hello World! Nice to meet you! 
TaskStatusUpdate [state=TASK_STATE_COMPLETED]: 
--- Task Finished ---
You: /quit
```

Related issue #965 🦕
# Description
Updated gemini setup. It is applicable to other models as well.


Example of `ai_learnings.md` entries:

```

## 2026-04-13 — Using extend() on a str return value

**Mistake**: Used `response_parts.extend(get_message_text(...))` and
`response_parts.extend(get_artifact_text(...))` where both functions
return `str`. `list.extend()` on a string iterates its characters,
producing `['H', 'e', 'l', 'l', 'o']` instead of `['Hello']`.

**Root cause**: Assumed the utility functions returned an iterable of
strings rather than a single string, and did not check their signatures
or run the tests before presenting the code.

**Rule**: Before calling `extend()`, verify the return type of the
expression. If it returns `str`, use `append()`. Run the tests after
any change to aggregation logic.

---

## 2026-04-13 — Assuming streaming event order without verifying across transports

**Mistake**: Added a strict check that the first streaming event must be
a `Task` or `Message`, raising a `RuntimeError` otherwise. Also used
`event.WhichOneof("event")` which fails because `StreamResponse` has no
oneof named "event" — its fields are independent message fields.
The REST transport sends a `status_update` as its first event, not a
`Task`, so the guard rejected valid responses.

**Root cause**: Assumed spec wording ("first event should be a Task")
held across all transport implementations without testing it. Did not
check the `StreamResponse` proto definition before calling `WhichOneof`.

**Rule**: Before adding ordering assumptions about streaming events,
verify the behaviour against every transport (JSONRPC, HTTP+JSON, GRPC).
Before calling `WhichOneof`, confirm the oneof name exists in the proto.

---

## 2026-04-13 — Assuming extras without checking dev dependencies

**Mistake**: Told the user that `http-server` and `grpc` extras needed
to be specified explicitly in the samples README prerequisites.

**Root cause**: Looked at the SDK's optional extras list and reasoned
from imports in the sample files, without checking whether the dev
dependency group already covered them. The dev group includes
`a2a-sdk[all]`, so a plain `uv sync` installs everything. Checking the
actual installed environment with one command would have revealed this
immediately.

**Rule**: Before writing installation instructions, verify what is
already provided by the project's dev dependencies (`uv sync` with no
flags). Do not recommend extra flags unless confirmed they are absent
from the dev group.

---

## 2026-04-13 — Proposing unverified code

**Mistake**: Proposed `_GRPC_ERROR = None` as a way to make `grpc`
optional in an `except` clause. `None` is not a valid exception type
in Python; the code would have crashed at runtime.

**Root cause**: The fix was reasoned about at a high level ("set it to
None when grpc is absent") without tracing through whether Python
actually accepts `None` in an `except` tuple. No verification step was
performed before presenting it to the user.

**Rule**: Before presenting any code change, trace through its
execution explicitly. For `except` clauses specifically: every element
in the tuple must be an exception class, never `None` or any other
non-exception value.

---

## 2026-04-14 — Race condition when reading state from DB in stream

**Mistake**: Used `active_task.get_task()` in `on_message_send_stream` to fetch the task state for the initial response. This caused a race condition where `get_task()` returned a task state that was ahead of the stream events, leading to test failures.

**Root cause**: Assumed `get_task()` would return the state corresponding to the event being processed, overlooking that the consumer loop runs independently and may have already processed subsequent events and updated the DB.

**Rule**: When processing a stream of events, do not rely on reading the current state from a shared store (like DB) to represent the state at the time of a specific event. Use state snapshots passed with the event if available.

```
…entCard inspection (#972)

## Description
Adds a `display_agent_card(card)` utility function to `a2a.utils` that
prints a
structured, human-readable summary of an `AgentCard` proto to stdout.
## Motivation
The current proto text format is complete but difficult to read at a
glance:
name: "Sample Agent"
supported_interfaces {
  url: "http://127.0.0.1:41241/a2a/jsonrpc"
  protocol_binding: "JSONRPC"
  protocol_version: "1.0"
}
...
At least four workarounds exist across `a2a-samples` for printing card
contents.
This provides a single, simple solution.
## Changes
- `src/a2a/utils/agent_card.py` — new file with
`display_agent_card(card: AgentCard) -> None`
- `src/a2a/utils/__init__.py` — exports `display_agent_card`
- `tests/utils/test_agent_card_display.py` — 5 unit tests including a
full golden test
- `samples/cli.py` — utilize the new display function
## Example output from `sample/cli.py`
```
uv run samples/cli.py 

Connecting to http://127.0.0.1:41241 (preferred transport: Any)

✓ Agent Card Found:
====================================================
                     AgentCard                      
====================================================
--- General ---
Name        : Sample Agent
Description : A sample agent to test the stream functionality.
Version     : 1.0.0
Provider    : A2A Samples (https://example.com)

--- Interfaces ---
  [0] 127.0.0.1:50051  (GRPC 1.0)
  [1] 127.0.0.1:50052  (GRPC 0.3)
  [2] http://127.0.0.1:41241/a2a/jsonrpc  (JSONRPC 1.0)
  [3] http://127.0.0.1:41241/a2a/jsonrpc  (JSONRPC 0.3)
  [4] http://127.0.0.1:41241/a2a/rest  (HTTP+JSON 1.0)
  [5] http://127.0.0.1:41241/a2a/rest  (HTTP+JSON 0.3)

--- Capabilities ---
Streaming           : True
Push notifications  : False
Extended agent card : False

--- I/O Modes ---
Input  : text
Output : text, task-status

--- Skills ---
----------------------------------------------------
  ID          : sample_agent
  Name        : Sample Agent
  Description : Say hi.
  Tags        : sample
  Example     : hi
====================================================
  Picked Transport: JsonRpcTransport
```
## Notes
- No breaking changes. Existing call sites are unaffected.
- Optional fields (`documentation_url`, `icon_url`, `provider`) are
shown only when set.
- Closes #961

Fixes #961  🦕
# Description

New version of itk
https://github.com/a2aproject/a2a-samples/releases/tag/itk-v.015-alpha
improves log readabiulity for debugging by spliting the logs of
individual tested agents into separate files if the `ITK_LOG_LEVEL`
environmental variable is set to "DEBUG"

This PR integrates the change into python's sdk CI and updates the
instruction on how to set debugging mode for tests

Thank you for opening a Pull Request!
Before submitting your PR, there are a few things you can do to make
sure it goes smoothly:

- [x] Follow the [`CONTRIBUTING`
Guide](https://github.com/a2aproject/a2a-python/blob/main/CONTRIBUTING.md).
- [x] Make your Pull Request title in the
<https://www.conventionalcommits.org/> specification.
- Important Prefixes for
[release-please](https://github.com/googleapis/release-please):
- `fix:` which represents bug fixes, and correlates to a
[SemVer](https://semver.org/) patch.
- `feat:` represents a new feature, and correlates to a SemVer minor.
- `feat!:`, or `fix!:`, `refactor!:`, etc., which represent a breaking
change (indicated by the `!`) and will result in a SemVer major.
- [x] Ensure the tests and linter pass (Run `bash scripts/format.sh`
from the repository root to format)
- [x] Appropriate docs were updated (if necessary)

Fixes #<issue_number_goes_here> 🦕

Co-authored-by: Krzysztof Dziedzic <dziedzick@google.com>
Co-authored-by: Ivan Shymko <ishymko@google.com>
# Description

Thank you for opening a Pull Request!
Before submitting your PR, there are a few things you can do to make
sure it goes smoothly:

- [ ] Follow the [`CONTRIBUTING`
Guide](https://github.com/a2aproject/a2a-python/blob/main/CONTRIBUTING.md).
- [ ] Make your Pull Request title in the
<https://www.conventionalcommits.org/> specification.
- Important Prefixes for
[release-please](https://github.com/googleapis/release-please):
- `fix:` which represents bug fixes, and correlates to a
[SemVer](https://semver.org/) patch.
- `feat:` represents a new feature, and correlates to a SemVer minor.
- `feat!:`, or `fix!:`, `refactor!:`, etc., which represent a breaking
change (indicated by the `!`) and will result in a SemVer major.
- [ ] Ensure the tests and linter pass (Run `bash scripts/format.sh`
from the repository root to format)
- [ ] Appropriate docs were updated (if necessary)

Fixes #<issue_number_goes_here> 🦕

Co-authored-by: Krzysztof Dziedzic <dziedzick@google.com>
# Description

Extracts developer-facing helper functions from a2a.utils into a
dedicated a2a.helpers package.

What changed
- New a2a.helpers package with two modules:
- proto_helpers.py — unified helpers for creating/inspecting Messages,
Artifacts, Tasks, Events, and StreamResponses
  - agent_card.py — moved from utils/agent_card.py
- Relocated internal functions to their actual consumers:
  - append_artifact_to_task -> server/tasks/task_manager.py
  - canonicalize_agent_card, _clean_empty -> utils/signing.py
- Removed unused helpers

Motivation
This is the first in a series of PRs to simplify the a2a.utils
structure. The goal is to stop mixing developer-facing convenience
helpers with internal SDK machinery.
# Description:
`docs/ai/ai_learnings.md` is a personal AI workflow log that should
not be shared in the repository. This PR:
- Removes `docs/ai/ai_learnings.md` from git tracking (file remains
  local, already listed in `.gitignore`)
- Updates `GEMINI.md` section 5 (Mistake Reflection Protocol) to
  include the file description, its local-only nature, and the entry
  format that was previously defined in the file itself
…ncept (#984)

1.0 spec uses `A2A-Extensions` instead of `X-A2A-Extensions`
header/metadata name. It also doesn't have "activation" concept - used
extensions are not propagated back via headers and should be put into
message.extensions or artifact.extensions instead.

1. Support both in for compat server.
2. Send `X-A2A-Extensions` in compat transports.
3. Remove "activation".
Fixes #869 🦕

---------

Co-authored-by: Ivan Shymko <ishymko@google.com>
# Description

Refactors internal helpers modules so that the helpers name is used
exclusively for the a2a.helpers package (customer-facing convenience
functions).
- Move a2a.client.helpers into a2a.client.card_resolver --
parse_agent_card and its backward-compat shims are implementation
details of card resolution
- Rename a2a.utils.helpers to a2a.utils.version_validator to reflect its
actual content
🤖 I have created a release *beep* *boop*
---


##
[1.0.0-alpha.2](v1.0.0-alpha.1...v1.0.0-alpha.2)
(2026-04-17)


### ⚠ BREAKING CHANGES

* clean helpers and utils folders structure
([#983](#983))
* Raise errors on invalid AgentExecutor behavior.
([#979](#979))
* extract developer helpers in helpers folder
([#978](#978))

### Features

* Raise errors on invalid AgentExecutor behavior.
([#979](#979))
([f4a0bcd](f4a0bcd))
* **utils:** add `display_agent_card()` utility for human-readable
AgentCard inspection
([#972](#972))
([3468180](3468180))


### Bug Fixes

* Don't generate empty metadata change events in VertexTaskStore
([#974](#974))
([b58b03e](b58b03e)),
closes [#802](#802)
* **extensions:** support both header names and remove "activation"
concept ([#984](#984))
([b8df210](b8df210))


### Documentation

* AgentExecutor interface documentation
([#976](#976))
([d667e4f](d667e4f))
* move `ai_learnings.md` to local-only and update `GEMINI.md`
([#982](#982))
([f6610fa](f6610fa))


### Code Refactoring

* clean helpers and utils folders structure
([#983](#983))
([c87e87c](c87e87c))
* extract developer helpers in helpers folder
([#978](#978))
([5f3ea29](5f3ea29))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
)

Existing extensions are kept, enables better modularity of service
parameters updates by (for instance) multiple interceptors.
🤖 I have created a release *beep* *boop*
---


##
[1.0.0-alpha.3](v1.0.0-alpha.2...v1.0.0-alpha.3)
(2026-04-17)


### Bug Fixes

* update `with_a2a_extensions` to append instead of overwriting
([#985](#985))
([e1d0e7a](e1d0e7a))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
`active_task.py` already contains agent executor behavior validation, do
not terminate the stream so that those errors can be raised, tests are
updated to cover invalid behavior conditions.
1. Fix gRPC setup.
1. Add E2E test with subprocess.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant updates to the A2A SDK, including a transition to Protobuf-based messaging, a new database migration CLI tool, and backward compatibility support for the v0.3 protocol. It also refactors the client transport layer to use interceptors and improves the overall architecture for task management. I have identified a critical issue in the database migration scripts where string literal defaults are not correctly quoted, which will cause SQL execution errors. Additionally, there are minor encapsulation concerns regarding private attribute access and URL construction that should be addressed to improve maintainability.

Comment thread itk/main.py
Comment thread src/a2a/server/events/event_queue_v2.py
Comment thread src/a2a/client/card_resolver.py
@ishymko ishymko marked this pull request as ready for review April 20, 2026 10:48
@ishymko ishymko requested review from a team and a2a-bot as code owners April 20, 2026 10:48
@ishymko ishymko merged commit 6d0080c into main Apr 20, 2026
30 of 34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.