Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: a2aproject/a2a-python
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.3.0
Choose a base ref
...
head repository: a2aproject/a2a-python
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.3.1
Choose a head ref
  • 20 commits
  • 50 files changed
  • 14 contributors

Commits on Aug 1, 2025

  1. Configuration menu
    Copy the full SHA
    4cff472 View commit details
    Browse the repository at this point in the history
  2. ci: Change release-please to GitHub Action (#374)

    - release-please GitHub App is being turned down on August 15, 2025
    holtskinner authored Aug 1, 2025
    Configuration menu
    Copy the full SHA
    760697f View commit details
    Browse the repository at this point in the history

Commits on Aug 4, 2025

  1. fix: relax protobuf dependency version requirement (#381)

    We want to use this in a project that requires `protobuf==6.31.1`.
    Version history indicates upgrading a2a-python to that version is not
    possible at the moment. Therefore, relax the required version to just be
    `>=5.29.5` (instead of `==`).
    
    This does print a warning when using a2a-python with a (major) newer
    version, but my tests show that it works just fine. Better to live with
    the warning than not being able to use a2a-python at all.
    
    This does not update the buf generation config as this would upgrade to
    newer proto requirements (and generate protos for newer versions).
    timn authored Aug 4, 2025
    Configuration menu
    Copy the full SHA
    0f55f55 View commit details
    Browse the repository at this point in the history
  2. fix: Use HasField for simple message retrieval for grpc transport (#380)

    Using `response.task` will reset the oneof field if the `msg` field was
    set. Properly check return value.
    
    ---------
    
    Co-authored-by: pstephengoogle <pstephen@google.com>
    timn and pstephengoogle authored Aug 4, 2025
    Configuration menu
    Copy the full SHA
    3032aa6 View commit details
    Browse the repository at this point in the history
  3. fix: openapi working in sub-app (#324)

    The `A2AFastAPIApplication` is very useful, but currently can not be
    used as a [Sub
    Application](https://fastapi.tiangolo.com/advanced/sub-applications/)
    without breaking the openapi specification.
    [Lifespan does not work for Sub
    Applications](https://fastapi.tiangolo.com/advanced/events/#sub-applications),
    which makes this otherwise useful integration work in existing larger
    FastAPI apps.
    
    This fix gets rid of the lifespan and instead enriches the openapi on
    the first call of the [openapi
    method](https://github.com/fastapi/fastapi/blob/0.116.1/fastapi/applications.py#L966).
    
    I tested it locally and everything works with sub-application.
    
    The following works after the fix with openapi components populated:
    ```python
    from fastapi import FastAPI
    from a2a.server.apps import A2AFastAPIApplication
    app = FastAPI()
    agent_app = A2AFastAPIApplication(...).build()
    app.mount("/a2a", agent_app)
    ```
    
    I am not adding `@override` although this overrides the `openapi`,
    because the pyright fails on it, see [the failed lint
    run](https://github.com/a2aproject/a2a-python/actions/runs/16370448989/job/46257297467?pr=324).
    
    ---------
    
    Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
    Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com>
    Co-authored-by: kthota-g <kcthota@google.com>
    4 people authored Aug 4, 2025
    Configuration menu
    Copy the full SHA
    dec4b48 View commit details
    Browse the repository at this point in the history

Commits on Aug 7, 2025

  1. Configuration menu
    Copy the full SHA
    b6796b9 View commit details
    Browse the repository at this point in the history
  2. fix: gracefully handle task exceptions in event consumer (#383)

    # Description
    
    This callback shouldn't result in exceptions being raised. From docs on
    `.exception()`:
    
    > The exception (or None if no exception was set) is returned only if
    the future is done. If the future has been cancelled, raises
    CancelledError. If the future isn't done yet, raises InvalidStateError.
    
    Currently, if a task has been cancelled, exceptions are thrown. E.g. the
    following error was observed when used with `google-adk`
    
    ```
    ERROR:asyncio:Exception in callback EventConsumer.agent_task_callback() at /app/python/.venv/lib/python3.13/site-packages/a2a/server/events/event_consumer.py:153
    handle: <Handle EventConsumer.agent_task_callback() at /app/python/.venv/lib/python3.13/site-packages/a2a/server/events/event_consumer.py:153>
    Traceback (most recent call last):
      File "/app/python/.venv/lib/python3.13/site-packages/anyio/streams/memory.py", line 111, in receive
        return self.receive_nowait()
               ~~~~~~~~~~~~~~~~~~~^^
      File "/app/python/.venv/lib/python3.13/site-packages/anyio/streams/memory.py", line 106, in receive_nowait
        raise WouldBlock
    anyio.WouldBlock
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/app/python/.local/share/uv/python/cpython-3.13.5-linux-x86_64-gnu/lib/python3.13/asyncio/events.py", line 89, in _run
        self._context.run(self._callback, *self._args)
        ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/app/python/.venv/lib/python3.13/site-packages/a2a/utils/telemetry.py", line 202, in sync_wrapper
        result = func(*args, **kwargs)
      File "/app/python/.venv/lib/python3.13/site-packages/a2a/server/events/event_consumer.py", line 163, in agent_task_callback
        if agent_task.exception() is not None:
           ~~~~~~~~~~~~~~~~~~~~^^
      File "/app/python/.venv/lib/python3.13/site-packages/a2a/utils/telemetry.py", line 162, in async_wrapper
        result = await func(*args, **kwargs)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/app/python/.venv/lib/python3.13/site-packages/a2a/server/request_handlers/default_request_handler.py", line 172, in _run_event_stream
        await self.agent_executor.execute(request, queue)
      File "/app/python/packages/kagent-adk/src/kagent_adk/_agent_executor.py", line 124, in execute
        await self._handle_request(context, event_queue, runner)
      File "/app/python/packages/kagent-adk/src/kagent_adk/_agent_executor.py", line 188, in _handle_request
        async for adk_event in runner.run_async(**run_args):
        ...<4 lines>...
                await event_queue.enqueue_event(a2a_event)
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/runners.py", line 233, in run_async
        async for event in self._exec_with_plugin(
        ...<2 lines>...
          yield event
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/runners.py", line 273, in _exec_with_plugin
        async for event in execute_fn(invocation_context):
        ...<6 lines>...
          yield (modified_event if modified_event else event)
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/runners.py", line 230, in execute
        async for event in ctx.agent.run_async(ctx):
          yield event
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/agents/base_agent.py", line 209, in run_async
        async for event in self._run_async_impl(ctx):
          yield event
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/agents/llm_agent.py", line 283, in _run_async_impl
        async for event in self._llm_flow.run_async(ctx):
          self.__maybe_save_output_to_state(event)
          yield event
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 290, in run_async
        async for event in self._run_one_step_async(invocation_context):
          last_event = event
          yield event
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 322, in _run_one_step_async
        async for event in self._postprocess_async(
        ...<5 lines>...
          yield event
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 407, in _postprocess_async
        async for event in self._postprocess_handle_function_calls_async(
        ...<2 lines>...
          yield event
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/flows/llm_flows/base_llm_flow.py", line 482, in _postprocess_handle_function_calls_async
        if function_response_event := await functions.handle_function_calls_async(
                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            invocation_context, function_call_event, llm_request.tools_dict
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        ):
        ^
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/flows/llm_flows/functions.py", line 179, in handle_function_calls_async
        function_response = await __call_tool_async(
                            ^^^^^^^^^^^^^^^^^^^^^^^^
            tool, args=function_args, tool_context=tool_context
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        )
        ^
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/flows/llm_flows/functions.py", line 474, in __call_tool_async
        return await tool.run_async(args=args, tool_context=tool_context)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/tools/base_authenticated_tool.py", line 93, in run_async
        return await self._run_async_impl(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
        ...<3 lines>...
        )
        ^
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/tools/mcp_tool/mcp_session_manager.py", line 128, in wrapper
        return await func(self, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/app/python/.venv/lib/python3.13/site-packages/google/adk/tools/mcp_tool/mcp_tool.py", line 133, in _run_async_impl
        response = await session.call_tool(self.name, arguments=args)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/app/python/.venv/lib/python3.13/site-packages/mcp/client/session.py", line 293, in call_tool
        result = await self.send_request(
                 ^^^^^^^^^^^^^^^^^^^^^^^^
        ...<12 lines>...
        )
        ^
      File "/app/python/.venv/lib/python3.13/site-packages/mcp/shared/session.py", line 272, in send_request
        response_or_error = await response_stream_reader.receive()
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/app/python/.venv/lib/python3.13/site-packages/anyio/streams/memory.py", line 119, in receive
        await receive_event.wait()
      File "/app/python/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 1774, in wait
        await self._event.wait()
      File "/app/python/.local/share/uv/python/cpython-3.13.5-linux-x86_64-gnu/lib/python3.13/asyncio/locks.py", line 213, in wait
        await fut
    asyncio.exceptions.CancelledError: Cancelled by cancel scope 72d19ee594f0
    ```
    onematchfox authored Aug 7, 2025
    Configuration menu
    Copy the full SHA
    2508a9b View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    fb7ee6f View commit details
    Browse the repository at this point in the history
  4. refactor!: Make the FastAPI and Starlette dependencies optional (#217)

    # Description
    
    This update makes Starlette and FastAPI libraries as optional
    dependencies. Users can run `uv add a2a-sdk[http-server]` to install
    these dependencies.
    
    ## Additional Checks
    
    - Verified that the "helloworld" agent sample works with this change.
    - Verified that a reasonable error message is printed when trying to use
    `A2AFastAPIApplication`.
    
    Release-As: 0.3.0
    
    ---------
    
    Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com>
    Co-authored-by: Holt Skinner <holtskinner@google.com>
    3 people authored Aug 7, 2025
    Configuration menu
    Copy the full SHA
    eb24654 View commit details
    Browse the repository at this point in the history

Commits on Aug 8, 2025

  1. ci: Add Conventional Commits GitHub Action (#391)

    Google GitHub App will be deprecated
    holtskinner authored Aug 8, 2025
    Configuration menu
    Copy the full SHA
    83b8091 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    1d8f92e View commit details
    Browse the repository at this point in the history

Commits on Aug 11, 2025

  1. test: Correctly run tests with the requested Python version (#393)

    The action "Test with Python 3.13" does not work as expected, all tests
    are run with Python 3.10.
    
    For exemple, [this
    run](https://github.com/a2aproject/a2a-python/actions/runs/16851324550/job/47738005154)
    shows:
    
    ```
    Test with Python 3.13
    ...
    Run uv run pytest --cov=a2a --cov-report term --cov-fail-under=88
    ============================= test session starts ==============================
    platform linux -- Python 3.10.18, pytest-8.4.1, pluggy-1.6.0
    ```
    
    I modified the script to set `python-version` on the "Install uv" step,
    this is the one that really creates the Python installation.
    Then I fixed the tests, they should work with all Pythons now.
    amauryfa authored Aug 11, 2025
    Configuration menu
    Copy the full SHA
    2ddf585 View commit details
    Browse the repository at this point in the history

Commits on Aug 12, 2025

  1. Configuration menu
    Copy the full SHA
    a96df5c View commit details
    Browse the repository at this point in the history
  2. fix: Add validation for transport types in ClientFactory (#396)

    ### Description
    
    This update introduces upfront validation for transport protocols within
    the `ClientFactory`. Previously, if an invalid or misspelled transport
    type was provided in the `ClientConfig`, it would be silently ignored.
    This could lead to confusing `ValueError('no compatible transports
    found.')` errors later on, making it difficult to debug
    misconfigurations.
    
    ### Changes
    
    * **`src/a2a/client/client_factory.py`**: Added a validation loop at the
    beginning of the `create` method to check all transport types provided
    in the `ClientConfig`.
    * **`tests/client/test_client_factory.py`**: Added a new unit test,
    `test_client_factory_invalid_transport_in_config`, to confirm that a
    `ValueError` is raised when an invalid transport string is used.
    pankaj-bind authored Aug 12, 2025
    Configuration menu
    Copy the full SHA
    2e8fbc4 View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    d7dd6ee View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    1aa4dd7 View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    2db7f81 View commit details
    Browse the repository at this point in the history

Commits on Aug 13, 2025

  1. feat: Add agent card as a route in rest adapter (#386)

    # 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: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
    Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com>
    Co-authored-by: Holt Skinner <holtskinner@google.com>
    4 people authored Aug 13, 2025
    Configuration menu
    Copy the full SHA
    ba93053 View commit details
    Browse the repository at this point in the history
  2. revert: "fix: Add validation for transport types in ClientFactory" (#…

    …402)
    
    Reverts #396
    
    This PR shouldn't have been merged as we don't want to limit the
    protocol to only JSON-RPC, gRPC, and REST Transports. (e.g. for
    proprietary transport protocols)
    
    Reported by @yarolegovich
    holtskinner authored Aug 13, 2025
    Configuration menu
    Copy the full SHA
    c4dac93 View commit details
    Browse the repository at this point in the history
  3. chore(main): release 0.3.1 (#382)

    🤖 I have created a release *beep* *boop*
    ---
    
    
    ##
    [0.3.1](v0.3.0...v0.3.1)
    (2025-08-13)
    
    
    ### Features
    
    * Add agent card as a route in rest adapter
    ([ba93053](ba93053))
    
    
    ### Bug Fixes
    
    * gracefully handle task exceptions in event consumer
    ([#383](#383))
    ([2508a9b](2508a9b))
    * openapi working in sub-app
    ([#324](#324))
    ([dec4b48](dec4b48))
    * Pass `message_length` param in `get_task()`
    ([#384](#384))
    ([b6796b9](b6796b9))
    * relax protobuf dependency version requirement
    ([#381](#381))
    ([0f55f55](0f55f55))
    * Use HasField for simple message retrieval for grpc transport
    ([#380](#380))
    ([3032aa6](3032aa6))
    
    ---
    This PR was generated with [Release
    Please](https://github.com/googleapis/release-please). See
    [documentation](https://github.com/googleapis/release-please#release-please).
    
    ---------
    
    Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com>
    a2a-bot and holtskinner authored Aug 13, 2025
    Configuration menu
    Copy the full SHA
    26f24be View commit details
    Browse the repository at this point in the history
Loading