From 3eccd4b1e3c7388f14e1e7191dce0efe7a011a20 Mon Sep 17 00:00:00 2001 From: Ed Snible Date: Wed, 1 Jul 2026 11:01:39 -0400 Subject: [PATCH 1/8] Upgrade git_issue_agent dependencies Signed-off-by: Ed Snible --- a2a/git_issue_agent/a2a_agent.py | 56 +++++++++------------ a2a/git_issue_agent/pyproject.toml | 2 +- a2a/git_issue_agent/uv.lock | 79 ++++++++++++++++++++++++++++-- 3 files changed, 99 insertions(+), 38 deletions(-) diff --git a/a2a/git_issue_agent/a2a_agent.py b/a2a/git_issue_agent/a2a_agent.py index 7c35edab..fdcd1865 100644 --- a/a2a/git_issue_agent/a2a_agent.py +++ b/a2a/git_issue_agent/a2a_agent.py @@ -13,22 +13,22 @@ from a2a.server.agent_execution import AgentExecutor, RequestContext -from a2a.server.apps import A2AStarletteApplication from a2a.server.events.event_queue import EventQueue from a2a.server.request_handlers import DefaultRequestHandler +from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes from a2a.server.tasks import InMemoryTaskStore, TaskUpdater +from a2a.helpers import new_task_from_user_message, new_text_part from a2a.types import ( AgentCapabilities, AgentCard, + AgentInterface, AgentSkill, TaskState, - TextPart, SecurityScheme, HTTPAuthSecurityScheme, ) -from a2a.utils import new_agent_text_message, new_task -from starlette.routing import Route +from starlette.applications import Starlette from git_issue_agent.config import settings, Settings from git_issue_agent.event import Event @@ -51,20 +51,21 @@ def get_agent_card(host: str, port: int): "Show all issues assigned to me across any repository", ], ) + # Allow env var AGENT_ENDPOINT to override the URL in the agent card + url = os.getenv("AGENT_ENDPOINT", f"http://{host}:{port}").rstrip("/") + "/" return AgentCard( name="Github issue agent", description="Answer queries about Github issues", - # Allow env var AGENT_ENDPOINT to override the URL in the agent card - url=os.getenv("AGENT_ENDPOINT", f"http://{host}:{port}").rstrip("/") + "/", + supported_interfaces=[AgentInterface(url=url, protocol_binding="JSONRPC")], version="1.0.0", default_input_modes=["text"], default_output_modes=["text"], capabilities=capabilities, skills=[skill], - securitySchemes={ + security_schemes={ "Bearer": SecurityScheme( - root=HTTPAuthSecurityScheme( - type="http", scheme="bearer", bearerFormat="JWT", description="OAuth 2.0 JWT token" + http_auth_security_scheme=HTTPAuthSecurityScheme( + scheme="bearer", bearer_format="JWT", description="OAuth 2.0 JWT token" ) ) }, @@ -99,17 +100,13 @@ async def emit_event(self, message: str, final: bool = False) -> None: logger.info("Emitting event %s", message) if final: - parts = [TextPart(text=message)] + parts = [new_text_part(message)] await self.task_updater.add_artifact(parts) await self.task_updater.complete() else: await self.task_updater.update_status( - TaskState.working, - new_agent_text_message( - message, - self.task_updater.context_id, - self.task_updater.task_id, - ), + TaskState.TASK_STATE_WORKING, + self.task_updater.new_agent_message([new_text_part(message)]), ) @@ -153,7 +150,7 @@ async def execute(self, context: RequestContext, event_queue: EventQueue): user_input = [context.get_user_input()] task = context.current_task if not task: - task = new_task(context.message) + task = new_task_from_user_message(context.message) await event_queue.enqueue_event(task) task_updater = TaskUpdater(event_queue, task.id, task.context_id) event_emitter = A2AEvent(task_updater) @@ -216,24 +213,17 @@ def run(): request_handler = DefaultRequestHandler( agent_executor=GithubExecutor(), task_store=InMemoryTaskStore(), - ) - - server = A2AStarletteApplication( agent_card=agent_card, - http_handler=request_handler, ) - app = server.build() # this returns a Starlette app - - # Add the new agent-card.json path alongside the legacy agent.json path - app.routes.insert( - 0, - Route( - "/.well-known/agent-card.json", - server._handle_get_agent_card, - methods=["GET"], - name="agent_card_new", - ), - ) + # a2a-sdk 1.x replaced A2AStarletteApplication with route factories that we + # assemble into a Starlette app ourselves. + routes = create_jsonrpc_routes(request_handler, rpc_url="/") + # Serve the current well-known path (/.well-known/agent-card.json) plus the + # legacy /.well-known/agent.json path for backward compatibility. + routes += create_agent_card_routes(agent_card) + routes += create_agent_card_routes(agent_card, card_url="/.well-known/agent.json") + + app = Starlette(routes=routes) uvicorn.run(app, host="0.0.0.0", port=settings.SERVICE_PORT) diff --git a/a2a/git_issue_agent/pyproject.toml b/a2a/git_issue_agent/pyproject.toml index a07323d5..5904d8fe 100644 --- a/a2a/git_issue_agent/pyproject.toml +++ b/a2a/git_issue_agent/pyproject.toml @@ -5,7 +5,7 @@ requires-python = ">=3.11,<3.13" description = "Git issue Agent module" dependencies = [ "python-dotenv>=1.2.2", - "a2a-sdk>=0.2.16", + "a2a-sdk>=1.1.0,<2", # We use 1.6.1 instead of the latest because # crewai requires openai>=2.30.0 # but litellm requires openai==2.24.0 diff --git a/a2a/git_issue_agent/uv.lock b/a2a/git_issue_agent/uv.lock index f114fbb9..b51d3e15 100644 --- a/a2a/git_issue_agent/uv.lock +++ b/a2a/git_issue_agent/uv.lock @@ -8,18 +8,22 @@ resolution-markers = [ [[package]] name = "a2a-sdk" -version = "0.3.6" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "culsans" }, { name = "google-api-core" }, + { name = "googleapis-common-protos" }, { name = "httpx" }, { name = "httpx-sse" }, + { name = "json-rpc" }, + { name = "packaging" }, { name = "protobuf" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/c1/ffe3d9aa51288703dbe68afb0b146601562f1232458c9f6da02c1e63b78c/a2a_sdk-0.3.6.tar.gz", hash = "sha256:d5d1b8de940435b1df9b58e95c3a375a8e53a650b0307a3cf90865b1dec69968", size = 222989, upload-time = "2025-09-17T17:17:36.418Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/7e/8ac10bbf8b15b16574355f39b17dbdf617a282c27b41c7ff2116e30336df/a2a_sdk-1.1.0.tar.gz", hash = "sha256:e8102dad1b36709dbdc3d19319e38e6dfa3b3a79c30416030eb2d482576be204", size = 375726, upload-time = "2026-05-29T09:34:43.015Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/84/13/b8901dd49017eac755d599d6751fb3f8346808846d4b79612401145aade7/a2a_sdk-0.3.6-py3-none-any.whl", hash = "sha256:f006c9aee2a2f9b235eb884273e572b7b09e1220d00f5789432a156fcd9dfe4c", size = 137620, upload-time = "2025-09-17T17:17:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ea/3a5b160cfd51c67759b08748051094d9365ceff18127633d0021950c9860/a2a_sdk-1.1.0-py3-none-any.whl", hash = "sha256:d7f5846caf18033d8bf3108b11ec827dd8dd32f867c98848ede0e39474be93be", size = 241886, upload-time = "2026-05-29T09:34:41.484Z" }, ] [[package]] @@ -82,6 +86,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/1a/d92e3325134ebfff6f4069f270d3aac770d63320bd1fcd0eca023e74d9a8/aiohttp-3.13.4-cp312-cp312-win_amd64.whl", hash = "sha256:6148c9ae97a3e8bff9a1fc9c757fa164116f86c100468339730e717590a3fb77", size = 461285, upload-time = "2026-03-28T17:16:42.713Z" }, ] +[[package]] +name = "aiologic" +version = "0.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sniffio" }, + { name = "typing-extensions" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/7a/d51f2fde1e8ae8a83431f8e97b7a71e9358cdb1d4d2ce6be387fa44d68de/aiologic-0.17.1.tar.gz", hash = "sha256:2e1b93b9e88ced318c2a63ad7b382688f40cbfe40e3d42258d49dc9c5aea179d", size = 252354, upload-time = "2026-06-27T20:41:33.25Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/d3/2d310b1b839014034dba0cba685e492df8a5c7ad32c19cab7e979eed6554/aiologic-0.17.1-py3-none-any.whl", hash = "sha256:c66b319830fedb7ca3d2b2125fa6f5b653f89418c2a27ea76f259ec5f00943c0", size = 161331, upload-time = "2026-06-27T20:41:31.877Z" }, +] + [[package]] name = "aiosignal" version = "1.4.0" @@ -484,6 +502,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a2/ca/7e8365deec19afb2b2c7be7c1c0aa8f99633b54e90c570999acda93260fc/cryptography-48.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:db63bf618e5dea46c07de12e900fe1cdd2541e6dc9dbae772a70b7d4d4765f6a", size = 3739536, upload-time = "2026-05-04T22:59:29.61Z" }, ] +[[package]] +name = "culsans" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiologic" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/e3/49afa1bc180e0d28008ec6bcdf82a4072d1c7a41032b5b759b60814ca4b0/culsans-0.11.0.tar.gz", hash = "sha256:0b43d0d05dce6106293d114c86e3fb4bfc63088cfe8ff08ed3fe36891447fe33", size = 107546, upload-time = "2025-12-31T23:15:38.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/5d/9fb19fb38f6d6120422064279ea5532e22b84aa2be8831d49607194feda3/culsans-0.11.0-py3-none-any.whl", hash = "sha256:278d118f63fc75b9db11b664b436a1b83cc30d9577127848ba41420e66eb5a47", size = 21811, upload-time = "2025-12-31T23:15:37.189Z" }, +] + [[package]] name = "defusedxml" version = "0.7.1" @@ -676,7 +707,7 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "a2a-sdk", specifier = ">=0.2.16" }, + { name = "a2a-sdk", specifier = ">=1.1.0,<2" }, { name = "crewai", extras = ["litellm"], specifier = ">=1.6.1" }, { name = "crewai-tools", extras = ["mcp"], specifier = ">=1.6.1" }, { name = "cryptography", specifier = ">=48.0.0,<49" }, @@ -971,6 +1002,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/aa/43/ac6691c7b5aa7191c964a04ae926d2bb06d9297dba1f2287df5b85cb3715/json_repair-0.25.2-py3-none-any.whl", hash = "sha256:51d67295c3184b6c41a3572689661c6128cef6cfc9fb04db63130709adfc5bf0", size = 12740, upload-time = "2024-06-27T16:26:13.823Z" }, ] +[[package]] +name = "json-rpc" +version = "1.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/9e/59f4a5b7855ced7346ebf40a2e9a8942863f644378d956f68bcef2c88b90/json-rpc-1.15.0.tar.gz", hash = "sha256:e6441d56c1dcd54241c937d0a2dcd193bdf0bdc539b5316524713f554b7f85b9", size = 28854, upload-time = "2023-06-11T09:45:49.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/9e/820c4b086ad01ba7d77369fb8b11470a01fac9b4977f02e18659cf378b6b/json_rpc-1.15.0-py2.py3-none-any.whl", hash = "sha256:4a4668bbbe7116feb4abbd0f54e64a4adcf4b8f648f19ffa0848ad0f6606a9bf", size = 39450, upload-time = "2023-06-11T09:45:47.136Z" }, +] + [[package]] name = "json5" version = "0.14.0" @@ -2673,6 +2713,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598, upload-time = "2026-01-10T09:23:45.395Z" }, ] +[[package]] +name = "wrapt" +version = "2.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/a4/282c8e64300a59fc834518a54bf0afabb4ff9218b5fa76958b450459a844/wrapt-2.2.2.tar.gz", hash = "sha256:0788e321027c999bf221b667bd4a54aaefd1a36283749a860ac3eb77daed0302", size = 129068, upload-time = "2026-06-20T23:49:44.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/15/0c2d55168707465abfc41f33c0b23d792a5fa9b65c26983606940900a120/wrapt-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f1a2ff355ece6a111ca7a20dc86df6659c9205d3fcee674ca34f2a2854fd4e73", size = 80782, upload-time = "2026-06-20T23:47:44.367Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b5/5c0b093eb48f8a062ef6267d3cb36e9bb1b88440181f6545a383c60efdf8/wrapt-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55b9a899e6fff5444f229d30aa6e9ac92d2216d9d60f33c771b5d76a760d5f8e", size = 81678, upload-time = "2026-06-20T23:47:45.857Z" }, + { url = "https://files.pythonhosted.org/packages/34/f3/de70937472dd3e8a4e6811192f9c6075efdffd4a2cd9b4596bf160f89668/wrapt-2.2.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a2d78c363f97d8bd718ee40432c66395685e9e98528ccaa423c3355d1715a26d", size = 159671, upload-time = "2026-06-20T23:47:47.345Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ec/40aed2330e7f02ecf74386ffcfef9ccb7108c6a430f15b6a252b663b1bed/wrapt-2.2.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d619e1eed9bd4f6ed9f24cd61971aa086fa86505289628d464bcf8a2c2e3f328", size = 160785, upload-time = "2026-06-20T23:47:48.759Z" }, + { url = "https://files.pythonhosted.org/packages/45/04/aa5309beed5344b00220ae6b3b24055852192656194c27947bee1736306a/wrapt-2.2.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:518b0c5e323511ec56a38894802ddd5e1222626484e68efe63f201854ad788e5", size = 153699, upload-time = "2026-06-20T23:47:50.177Z" }, + { url = "https://files.pythonhosted.org/packages/01/df/2def7e99d1fe87eea413f95f671924cdddcb08823b1ffd212748dfa6d062/wrapt-2.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4bccea5cdecffa9dd70e343741f0e41e0a16619313d04b72f78bb525162ebcd0", size = 159695, upload-time = "2026-06-20T23:47:51.602Z" }, + { url = "https://files.pythonhosted.org/packages/c7/f6/a906d01a2ce12157bad2404957b3e2140da354b8a70b2fa48bbf282871c0/wrapt-2.2.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:209112cafd963710a05d199aae431d79a28bc76eb8e6d1bbbb8ad24340722cae", size = 152813, upload-time = "2026-06-20T23:47:53.03Z" }, + { url = "https://files.pythonhosted.org/packages/02/49/bc0086292d239575b4c08f4cf8a4079fa58abbad58ec23abf84833a283ed/wrapt-2.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5a5290e4bf2f332fc29ce72ffb9a2fff678aaac047e2e9f5f7165cd7792e099", size = 158809, upload-time = "2026-06-20T23:47:54.391Z" }, + { url = "https://files.pythonhosted.org/packages/55/83/8fbd034de1f3e907edaa18786d5dd8f6932874edee0826c7cecb5cab03a1/wrapt-2.2.2-cp311-cp311-win32.whl", hash = "sha256:5499236ad1dc116012e2a5dd943f3f31af12fce452128e2bbcbd55a7d3d4d14c", size = 77414, upload-time = "2026-06-20T23:47:55.882Z" }, + { url = "https://files.pythonhosted.org/packages/7e/9c/23695baa331c6de4e874c3d78b8e0bed92e1d2a274e665b29858f6841672/wrapt-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:8636809939152be6ae20a6cef0fed9fe60f411b47847d0426a826884b469e971", size = 80368, upload-time = "2026-06-20T23:47:57.237Z" }, + { url = "https://files.pythonhosted.org/packages/08/49/40cefc342bf89b234a4490d741290fce781774b831aefb39c25471da96c9/wrapt-2.2.2-cp311-cp311-win_arm64.whl", hash = "sha256:5d0a142f7af07caeb5e5da87493162a7b8efa19ba919e550a746f7446e13fb30", size = 79489, upload-time = "2026-06-20T23:47:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/2a/85/180b40628b23772692a0c76e8030114e1c0ae068470ed531919f0a5f2a4a/wrapt-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8417fd3c674d3c8023d080292d29301531a12daf8bd938dd419710dd2f464f2b", size = 81484, upload-time = "2026-06-20T23:47:59.924Z" }, + { url = "https://files.pythonhosted.org/packages/94/f2/21c90f2a16689702e2aaff45795b11018dff2c9b1242bac10d225483f676/wrapt-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e7070c7472582e31af3dfc2622b2381a0df7435110a9388ed8db5ffbce67efb", size = 82151, upload-time = "2026-06-20T23:48:01.303Z" }, + { url = "https://files.pythonhosted.org/packages/5f/b3/7e6e9fcf4fe7e1b69a49fe6cc5a44e8224bab6283c5233c97e132f14908e/wrapt-2.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2e096c9d39a59b35b63c9aacfbbbec2088ff51ff1fc31051acc60a07f42f273a", size = 169828, upload-time = "2026-06-20T23:48:02.719Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/894f132d857ed5a9904d937baf368badcbe5ea9e436e2f1930fe21c9f1f0/wrapt-2.2.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d1a6050405bf334be33bf66296f113563622972a34900ae6fa60fd283a1a900", size = 171544, upload-time = "2026-06-20T23:48:04.266Z" }, + { url = "https://files.pythonhosted.org/packages/29/de/3c833e03725b477e9ea34028224dd21a48781830101e4e036f77e8b6b102/wrapt-2.2.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10adb01371408c6de504a6658b9886480f1a4919a83752748a387a504a21df79", size = 160663, upload-time = "2026-06-20T23:48:05.708Z" }, + { url = "https://files.pythonhosted.org/packages/33/be/27edce350b24e3054d9d047f65f16d4c4d4c1f3f31c4278a1f8a95c723c8/wrapt-2.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3442eee2a5798f9b451f1b2cd7518ce8b7e28a2a364696c414460a0e295c012a", size = 169387, upload-time = "2026-06-20T23:48:07.243Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c4/9fd9679af8bf38e146652c7f47b6b352c3e5795b4ad1c0b7f94e15ac2aa7/wrapt-2.2.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6c99012a22f735a85eed7c4b86a3e99c30fdd57d9e115b2b45f796264b58d0bf", size = 158849, upload-time = "2026-06-20T23:48:08.91Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c2/aa6c0c2206803068c6859dabe01f8c84c43744da93d4c67b8946d21655ee/wrapt-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b686cfc008776a3952d6213cb296ed7f45d782a8453936406faa89eac0835ab", size = 168147, upload-time = "2026-06-20T23:48:10.374Z" }, + { url = "https://files.pythonhosted.org/packages/42/63/3eb25da41049d20ae18fcab2dd8b056e02387c4bfa626cbdfb7c3b872e4f/wrapt-2.2.2-cp312-cp312-win32.whl", hash = "sha256:ef2cce266b5b0b07e19fa82e59673b81142b7a3607c8ed1254113d048ed668da", size = 77734, upload-time = "2026-06-20T23:48:11.769Z" }, + { url = "https://files.pythonhosted.org/packages/da/09/0390e008a305360948fa9ce69507d041ac12cb2ee5d28e34467e2ee79391/wrapt-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:abf8c20a2d72ee69e16328b3c91342c446e723bfe48bfcc4dded3b9722ac027f", size = 80585, upload-time = "2026-06-20T23:48:13.117Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b3/84c445c66969f2d3457276b183a48c91097d59bbef9af6c075366b0f8c36/wrapt-2.2.2-cp312-cp312-win_arm64.whl", hash = "sha256:c6c64c5d02578bc4c4bca4f0aef1504de933c1d5b4ac2710b9131111459506c8", size = 79553, upload-time = "2026-06-20T23:48:14.5Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d2/6317eb6d4554855bbf12d61857774af34747bf88a42c19bf306de67e2fa3/wrapt-2.2.2-py3-none-any.whl", hash = "sha256:5bad217350f19ce99ca5b5e71d406765ea86fe541628426772b657375ee1c048", size = 61460, upload-time = "2026-06-20T23:49:42.966Z" }, +] + [[package]] name = "yarl" version = "1.20.1" From bda614b448e801694abb530a7cec2e54106d01c3 Mon Sep 17 00:00:00 2001 From: Ed Snible Date: Wed, 1 Jul 2026 11:01:51 -0400 Subject: [PATCH 2/8] Upgrade weather_service dependencies Signed-off-by: Ed Snible --- a2a/weather_service/pyproject.toml | 2 +- .../src/weather_service/agent.py | 58 ++++++++----------- a2a/weather_service/uv.lock | 48 +++++++++++++-- 3 files changed, 70 insertions(+), 38 deletions(-) diff --git a/a2a/weather_service/pyproject.toml b/a2a/weather_service/pyproject.toml index 54fb99a2..70f6d1e6 100644 --- a/a2a/weather_service/pyproject.toml +++ b/a2a/weather_service/pyproject.toml @@ -9,7 +9,7 @@ readme = "README.md" license = { text = "Apache" } requires-python = ">=3.11" dependencies = [ - "a2a-sdk>=0.3.26", + "a2a-sdk>=1.1.0,<2", "langgraph>=1.2.2", "langchain-core>=1.4.0", "langchain-community>=0.4.2", diff --git a/a2a/weather_service/src/weather_service/agent.py b/a2a/weather_service/src/weather_service/agent.py index a989ce04..07dfe27e 100644 --- a/a2a/weather_service/src/weather_service/agent.py +++ b/a2a/weather_service/src/weather_service/agent.py @@ -4,17 +4,17 @@ from textwrap import dedent import uvicorn -from langchain_core.messages import HumanMessage -from starlette.middleware.base import BaseHTTPMiddleware -from starlette.routing import Route - +from a2a.helpers import new_task_from_user_message, new_text_part from a2a.server.agent_execution import AgentExecutor, RequestContext -from a2a.server.apps import A2AStarletteApplication from a2a.server.events.event_queue import EventQueue from a2a.server.request_handlers import DefaultRequestHandler +from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes from a2a.server.tasks import InMemoryTaskStore, TaskUpdater -from a2a.types import AgentCapabilities, AgentCard, AgentSkill, TaskState, TextPart -from a2a.utils import new_agent_text_message, new_task +from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill, TaskState +from langchain_core.messages import HumanMessage +from starlette.applications import Starlette +from starlette.middleware.base import BaseHTTPMiddleware + from weather_service.configuration import Configuration from weather_service.graph import get_graph, get_mcpclient from weather_service.observability import ( @@ -82,7 +82,12 @@ def get_agent_card(host: str, port: int): """, ), # Allow env var AGENT_ENDPOINT to override the URL in the agent card - url=os.getenv("AGENT_ENDPOINT", f"http://{host}:{port}").rstrip("/") + "/", + supported_interfaces=[ + AgentInterface( + url=os.getenv("AGENT_ENDPOINT", f"http://{host}:{port}").rstrip("/") + "/", + protocol_binding="JSONRPC", + ) + ], version="1.0.0", default_input_modes=["text"], default_output_modes=["text"], @@ -106,7 +111,7 @@ async def emit_event(self, message: str, final: bool = False, failed: bool = Fal logger.info("Emitting event %s", message) if final or failed: - parts = [TextPart(text=message)] + parts = [new_text_part(message)] await self.task_updater.add_artifact(parts) if final: await self.task_updater.complete() @@ -114,12 +119,8 @@ async def emit_event(self, message: str, final: bool = False, failed: bool = Fal await self.task_updater.failed() else: await self.task_updater.update_status( - TaskState.working, - new_agent_text_message( - message, - self.task_updater.context_id, - self.task_updater.task_id, - ), + TaskState.TASK_STATE_WORKING, + self.task_updater.new_agent_message([new_text_part(message)]), ) @@ -136,7 +137,7 @@ async def execute(self, context: RequestContext, event_queue: EventQueue): # Setup Event Emitter task = context.current_task if not task: - task = new_task(context.message) # type: ignore + task = new_task_from_user_message(context.message) # type: ignore await event_queue.enqueue_event(task) task_updater = TaskUpdater(event_queue, task.id, task.context_id) event_emitter = A2AEvent(task_updater) @@ -243,28 +244,19 @@ def run(): request_handler = DefaultRequestHandler( agent_executor=WeatherExecutor(), task_store=InMemoryTaskStore(), - ) - - server = A2AStarletteApplication( agent_card=agent_card, - http_handler=request_handler, ) - # Build the Starlette app - app = server.build() - - # Add the new agent-card.json path alongside the legacy agent.json path - app.routes.insert( - 0, - Route( - "/.well-known/agent-card.json", - server._handle_get_agent_card, - methods=["GET"], - name="agent_card_new", - ), - ) + # a2a-sdk 1.x replaced A2AStarletteApplication with route factories that we + # assemble into a Starlette app ourselves. + routes = create_jsonrpc_routes(request_handler, rpc_url="/") + # Serve the current well-known path (/.well-known/agent-card.json) plus the + # legacy /.well-known/agent.json path for backward compatibility. + routes += create_agent_card_routes(agent_card) + routes += create_agent_card_routes(agent_card, card_url="/.well-known/agent.json") # Add tracing middleware - creates root span with MLflow/GenAI attributes + app = Starlette(routes=routes) app.add_middleware(BaseHTTPMiddleware, dispatch=create_tracing_middleware()) uvicorn.run(app, host=host, port=port) diff --git a/a2a/weather_service/uv.lock b/a2a/weather_service/uv.lock index ea0d0366..7c7af2cc 100644 --- a/a2a/weather_service/uv.lock +++ b/a2a/weather_service/uv.lock @@ -11,18 +11,22 @@ resolution-markers = [ [[package]] name = "a2a-sdk" -version = "0.3.26" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "culsans", marker = "python_full_version < '3.13'" }, { name = "google-api-core" }, + { name = "googleapis-common-protos" }, { name = "httpx" }, { name = "httpx-sse" }, + { name = "json-rpc" }, + { name = "packaging" }, { name = "protobuf" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/be/97/a6840e01795b182ce751ca165430d46459927cde9bfab838087cbb24aef7/a2a_sdk-0.3.26.tar.gz", hash = "sha256:44068e2d037afbb07ab899267439e9bc7eaa7ac2af94f1e8b239933c993ad52d", size = 274598, upload-time = "2026-04-09T15:21:13.902Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/7e/8ac10bbf8b15b16574355f39b17dbdf617a282c27b41c7ff2116e30336df/a2a_sdk-1.1.0.tar.gz", hash = "sha256:e8102dad1b36709dbdc3d19319e38e6dfa3b3a79c30416030eb2d482576be204", size = 375726, upload-time = "2026-05-29T09:34:43.015Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dd/d5/51f4ee1bf3b736add42a542d3c8a3fd3fa85f3d36c17972127defc46c26f/a2a_sdk-0.3.26-py3-none-any.whl", hash = "sha256:754e0573f6d33b225c1d8d51f640efa69cbbed7bdfb06ce9c3540ea9f58d4a91", size = 151016, upload-time = "2026-04-09T15:21:12.35Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ea/3a5b160cfd51c67759b08748051094d9365ceff18127633d0021950c9860/a2a_sdk-1.1.0-py3-none-any.whl", hash = "sha256:d7f5846caf18033d8bf3108b11ec827dd8dd32f867c98848ede0e39474be93be", size = 241886, upload-time = "2026-05-29T09:34:41.484Z" }, ] [[package]] @@ -161,6 +165,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/11/7f83fcba9ee05d4c54d61b3f8104da0d43a59adac44dd28effc0c9a10422/aiohttp-3.14.0-cp314-cp314t-win_arm64.whl", hash = "sha256:7a3fc4358e65826c515350f199c210de747cf669998211b1ee6c2e46de364b24", size = 467399, upload-time = "2026-06-01T19:40:59.993Z" }, ] +[[package]] +name = "aiologic" +version = "0.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sniffio", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "wrapt", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/7a/d51f2fde1e8ae8a83431f8e97b7a71e9358cdb1d4d2ce6be387fa44d68de/aiologic-0.17.1.tar.gz", hash = "sha256:2e1b93b9e88ced318c2a63ad7b382688f40cbfe40e3d42258d49dc9c5aea179d", size = 252354, upload-time = "2026-06-27T20:41:33.25Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/d3/2d310b1b839014034dba0cba685e492df8a5c7ad32c19cab7e979eed6554/aiologic-0.17.1-py3-none-any.whl", hash = "sha256:c66b319830fedb7ca3d2b2125fa6f5b653f89418c2a27ea76f259ec5f00943c0", size = 161331, upload-time = "2026-06-27T20:41:31.877Z" }, +] + [[package]] name = "aiosignal" version = "1.4.0" @@ -545,6 +563,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a2/ca/7e8365deec19afb2b2c7be7c1c0aa8f99633b54e90c570999acda93260fc/cryptography-48.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:db63bf618e5dea46c07de12e900fe1cdd2541e6dc9dbae772a70b7d4d4765f6a", size = 3739536, upload-time = "2026-05-04T22:59:29.61Z" }, ] +[[package]] +name = "culsans" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiologic", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/e3/49afa1bc180e0d28008ec6bcdf82a4072d1c7a41032b5b759b60814ca4b0/culsans-0.11.0.tar.gz", hash = "sha256:0b43d0d05dce6106293d114c86e3fb4bfc63088cfe8ff08ed3fe36891447fe33", size = 107546, upload-time = "2025-12-31T23:15:38.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/5d/9fb19fb38f6d6120422064279ea5532e22b84aa2be8831d49607194feda3/culsans-0.11.0-py3-none-any.whl", hash = "sha256:278d118f63fc75b9db11b664b436a1b83cc30d9577127848ba41420e66eb5a47", size = 21811, upload-time = "2025-12-31T23:15:37.189Z" }, +] + [[package]] name = "cycler" version = "0.12.1" @@ -1225,6 +1256,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, ] +[[package]] +name = "json-rpc" +version = "1.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/9e/59f4a5b7855ced7346ebf40a2e9a8942863f644378d956f68bcef2c88b90/json-rpc-1.15.0.tar.gz", hash = "sha256:e6441d56c1dcd54241c937d0a2dcd193bdf0bdc539b5316524713f554b7f85b9", size = 28854, upload-time = "2023-06-11T09:45:49.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/9e/820c4b086ad01ba7d77369fb8b11470a01fac9b4977f02e18659cf378b6b/json_rpc-1.15.0-py2.py3-none-any.whl", hash = "sha256:4a4668bbbe7116feb4abbd0f54e64a4adcf4b8f648f19ffa0848ad0f6606a9bf", size = 39450, upload-time = "2023-06-11T09:45:47.136Z" }, +] + [[package]] name = "jsonpatch" version = "1.33" @@ -3635,7 +3675,7 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "a2a-sdk", specifier = ">=0.3.26" }, + { name = "a2a-sdk", specifier = ">=1.1.0,<2" }, { name = "aiohttp", specifier = ">=3.14.0" }, { name = "cryptography", specifier = ">=48.0.0,<49" }, { name = "gitpython", specifier = ">=3.1.47" }, From fdc5594fd716fbd1912a9ceb2eea173177b12fe1 Mon Sep 17 00:00:00 2001 From: Ed Snible Date: Wed, 1 Jul 2026 11:15:05 -0400 Subject: [PATCH 3/8] Upgrade generic_agent dependencies Signed-off-by: Ed Snible --- a2a/generic_agent/pyproject.toml | 2 +- a2a/generic_agent/src/generic_agent/agent.py | 56 +++++++++----------- a2a/generic_agent/uv.lock | 48 +++++++++++++++-- 3 files changed, 70 insertions(+), 36 deletions(-) diff --git a/a2a/generic_agent/pyproject.toml b/a2a/generic_agent/pyproject.toml index aab49ceb..aff0aabf 100644 --- a/a2a/generic_agent/pyproject.toml +++ b/a2a/generic_agent/pyproject.toml @@ -4,7 +4,7 @@ version = "0.0.1" description = "Simple ollama-based Langgraph agent with MCP tool calling." requires-python = ">=3.11" dependencies = [ - "a2a-sdk>=0.2.16", + "a2a-sdk>=1.1.0,<2", "langgraph>=1.2.2", "langchain-core>=1.4.0", "langchain-community>=0.4.2", diff --git a/a2a/generic_agent/src/generic_agent/agent.py b/a2a/generic_agent/src/generic_agent/agent.py index c66d41d7..f990a219 100644 --- a/a2a/generic_agent/src/generic_agent/agent.py +++ b/a2a/generic_agent/src/generic_agent/agent.py @@ -3,17 +3,17 @@ from textwrap import dedent import uvicorn -from langchain_core.messages import HumanMessage -from openinference.instrumentation.langchain import LangChainInstrumentor -from starlette.routing import Route - +from a2a.helpers import new_task_from_user_message, new_text_part from a2a.server.agent_execution import AgentExecutor, RequestContext -from a2a.server.apps import A2AStarletteApplication from a2a.server.events.event_queue import EventQueue from a2a.server.request_handlers import DefaultRequestHandler +from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes from a2a.server.tasks import InMemoryTaskStore, TaskUpdater -from a2a.types import AgentCapabilities, AgentCard, AgentSkill, TaskState, TextPart -from a2a.utils import new_agent_text_message, new_task +from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill, TaskState +from langchain_core.messages import HumanMessage +from openinference.instrumentation.langchain import LangChainInstrumentor +from starlette.applications import Starlette + from generic_agent.config import Configuration from generic_agent.graph import get_graph, get_mcp_server_names, get_mcpclient, get_skill_folder_paths @@ -64,7 +64,12 @@ def get_agent_card(host: str, port: int) -> AgentCard: """, ), # Allow env var AGENT_ENDPOINT to override the URL in the agent card - url=os.getenv("AGENT_ENDPOINT", f"http://{host}:{port}").rstrip("/") + "/", + supported_interfaces=[ + AgentInterface( + url=os.getenv("AGENT_ENDPOINT", f"http://{host}:{port}").rstrip("/") + "/", + protocol_binding="JSONRPC", + ) + ], version=config.AGENT_VERSION, default_input_modes=["text"], default_output_modes=["text"], @@ -99,7 +104,7 @@ async def emit_event(self, message: str, final: bool = False, failed: bool = Fal logger.info("Emitting event %s", message) if final or failed: - parts = [TextPart(text=message)] + parts = [new_text_part(message)] await self.task_updater.add_artifact(parts) if final: await self.task_updater.complete() @@ -107,12 +112,8 @@ async def emit_event(self, message: str, final: bool = False, failed: bool = Fal await self.task_updater.failed() else: await self.task_updater.update_status( - TaskState.working, - new_agent_text_message( - message, - self.task_updater.context_id, - self.task_updater.task_id, - ), + TaskState.TASK_STATE_WORKING, + self.task_updater.new_agent_message([new_text_part(message)]), ) @@ -129,7 +130,7 @@ async def execute(self, context: RequestContext, event_queue: EventQueue): # Setup Event Emitter task = context.current_task if not task: - task = new_task(context.message) # type: ignore + task = new_task_from_user_message(context.message) # type: ignore await event_queue.enqueue_event(task) task_updater = TaskUpdater(event_queue, task.id, task.context_id) event_emitter = A2AEvent(task_updater) @@ -211,24 +212,17 @@ def run(): request_handler = DefaultRequestHandler( agent_executor=GenericExecutor(), task_store=InMemoryTaskStore(), - ) - - server = A2AStarletteApplication( agent_card=agent_card, - http_handler=request_handler, ) - app = server.build() + # a2a-sdk 1.x replaced A2AStarletteApplication with route factories that we + # assemble into a Starlette app ourselves. + routes = create_jsonrpc_routes(request_handler, rpc_url="/") + # Serve the current well-known path (/.well-known/agent-card.json) plus the + # legacy /.well-known/agent.json path for backward compatibility. + routes += create_agent_card_routes(agent_card) + routes += create_agent_card_routes(agent_card, card_url="/.well-known/agent.json") - # Add the new agent-card.json path alongside the legacy agent.json path - app.routes.insert( - 0, - Route( - "/.well-known/agent-card.json", - server._handle_get_agent_card, - methods=["GET"], - name="agent_card_new", - ), - ) + app = Starlette(routes=routes) uvicorn.run(app, host=host, port=port) diff --git a/a2a/generic_agent/uv.lock b/a2a/generic_agent/uv.lock index 9e5ca197..20eee122 100644 --- a/a2a/generic_agent/uv.lock +++ b/a2a/generic_agent/uv.lock @@ -9,18 +9,22 @@ resolution-markers = [ [[package]] name = "a2a-sdk" -version = "0.3.10" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "culsans", marker = "python_full_version < '3.13'" }, { name = "google-api-core" }, + { name = "googleapis-common-protos" }, { name = "httpx" }, { name = "httpx-sse" }, + { name = "json-rpc" }, + { name = "packaging" }, { name = "protobuf" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/de/5a/3634ce054a8985c0d2ca0cb2ed1c8c8fdcd67456ddb6496895483c17fee0/a2a_sdk-0.3.10.tar.gz", hash = "sha256:f2df01935fb589c6ebaf8581aede4fe059a30a72cd38e775035337c78f8b2cca", size = 225974, upload-time = "2025-10-21T20:40:38.423Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/7e/8ac10bbf8b15b16574355f39b17dbdf617a282c27b41c7ff2116e30336df/a2a_sdk-1.1.0.tar.gz", hash = "sha256:e8102dad1b36709dbdc3d19319e38e6dfa3b3a79c30416030eb2d482576be204", size = 375726, upload-time = "2026-05-29T09:34:43.015Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/9b/82df9530ed77d30831c49ffffc827222961422d444c0d684101e945ee214/a2a_sdk-0.3.10-py3-none-any.whl", hash = "sha256:b216ccc5ccfd00dcfa42f0f2dc709bc7ba057550717a34b0b1b34a99a76749cf", size = 140291, upload-time = "2025-10-21T20:40:36.929Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ea/3a5b160cfd51c67759b08748051094d9365ceff18127633d0021950c9860/a2a_sdk-1.1.0-py3-none-any.whl", hash = "sha256:d7f5846caf18033d8bf3108b11ec827dd8dd32f867c98848ede0e39474be93be", size = 241886, upload-time = "2026-05-29T09:34:41.484Z" }, ] [[package]] @@ -159,6 +163,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/11/7f83fcba9ee05d4c54d61b3f8104da0d43a59adac44dd28effc0c9a10422/aiohttp-3.14.0-cp314-cp314t-win_arm64.whl", hash = "sha256:7a3fc4358e65826c515350f199c210de747cf669998211b1ee6c2e46de364b24", size = 467399, upload-time = "2026-06-01T19:40:59.993Z" }, ] +[[package]] +name = "aiologic" +version = "0.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sniffio", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "wrapt", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/7a/d51f2fde1e8ae8a83431f8e97b7a71e9358cdb1d4d2ce6be387fa44d68de/aiologic-0.17.1.tar.gz", hash = "sha256:2e1b93b9e88ced318c2a63ad7b382688f40cbfe40e3d42258d49dc9c5aea179d", size = 252354, upload-time = "2026-06-27T20:41:33.25Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/d3/2d310b1b839014034dba0cba685e492df8a5c7ad32c19cab7e979eed6554/aiologic-0.17.1-py3-none-any.whl", hash = "sha256:c66b319830fedb7ca3d2b2125fa6f5b653f89418c2a27ea76f259ec5f00943c0", size = 161331, upload-time = "2026-06-27T20:41:31.877Z" }, +] + [[package]] name = "aiosignal" version = "1.4.0" @@ -445,6 +463,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a2/ca/7e8365deec19afb2b2c7be7c1c0aa8f99633b54e90c570999acda93260fc/cryptography-48.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:db63bf618e5dea46c07de12e900fe1cdd2541e6dc9dbae772a70b7d4d4765f6a", size = 3739536, upload-time = "2026-05-04T22:59:29.61Z" }, ] +[[package]] +name = "culsans" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiologic", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/e3/49afa1bc180e0d28008ec6bcdf82a4072d1c7a41032b5b759b60814ca4b0/culsans-0.11.0.tar.gz", hash = "sha256:0b43d0d05dce6106293d114c86e3fb4bfc63088cfe8ff08ed3fe36891447fe33", size = 107546, upload-time = "2025-12-31T23:15:38.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/5d/9fb19fb38f6d6120422064279ea5532e22b84aa2be8831d49607194feda3/culsans-0.11.0-py3-none-any.whl", hash = "sha256:278d118f63fc75b9db11b664b436a1b83cc30d9577127848ba41420e66eb5a47", size = 21811, upload-time = "2025-12-31T23:15:37.189Z" }, +] + [[package]] name = "deprecation" version = "2.1.0" @@ -600,7 +631,7 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "a2a-sdk", specifier = ">=0.2.16" }, + { name = "a2a-sdk", specifier = ">=1.1.0,<2" }, { name = "aiohttp", specifier = ">=3.14.0" }, { name = "cryptography", specifier = ">=48.0.0,<49" }, { name = "langchain-community", specifier = ">=0.4.2" }, @@ -901,6 +932,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d9/71/71408b02c6133153336d29fa3ba53000f1e1a3f78bb2fc2d1a1865d2e743/jiter-0.11.1-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18c77aaa9117510d5bdc6a946baf21b1f0cfa58ef04d31c8d016f206f2118960", size = 343697, upload-time = "2025-10-17T11:31:13.773Z" }, ] +[[package]] +name = "json-rpc" +version = "1.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/9e/59f4a5b7855ced7346ebf40a2e9a8942863f644378d956f68bcef2c88b90/json-rpc-1.15.0.tar.gz", hash = "sha256:e6441d56c1dcd54241c937d0a2dcd193bdf0bdc539b5316524713f554b7f85b9", size = 28854, upload-time = "2023-06-11T09:45:49.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/9e/820c4b086ad01ba7d77369fb8b11470a01fac9b4977f02e18659cf378b6b/json_rpc-1.15.0-py2.py3-none-any.whl", hash = "sha256:4a4668bbbe7116feb4abbd0f54e64a4adcf4b8f648f19ffa0848ad0f6606a9bf", size = 39450, upload-time = "2023-06-11T09:45:47.136Z" }, +] + [[package]] name = "jsonpatch" version = "1.33" From 58ad0ac601bc66d45176c7eebe44014b4225bb38 Mon Sep 17 00:00:00 2001 From: Ed Snible Date: Wed, 1 Jul 2026 11:32:05 -0400 Subject: [PATCH 4/8] Upgrade simple_generalist dependencies Signed-off-by: Ed Snible --- a2a/simple_generalist/pyproject.toml | 2 +- .../simple_generalist/a2a_server/server.py | 41 +++++---- a2a/simple_generalist/uv.lock | 83 +++++++++++++------ 3 files changed, 80 insertions(+), 46 deletions(-) diff --git a/a2a/simple_generalist/pyproject.toml b/a2a/simple_generalist/pyproject.toml index 687bab40..3498664a 100644 --- a/a2a/simple_generalist/pyproject.toml +++ b/a2a/simple_generalist/pyproject.toml @@ -5,7 +5,7 @@ requires-python = ">=3.12,<3.13" description = "A generalist AG2 agent exposed via A2A, powered by MCP tools" dependencies = [ "python-dotenv>=1.2.2", - "a2a-sdk[http-server]>=0.3.22", + "a2a-sdk[http-server]>=1.1.0,<2", "ag2[openai,mcp,tracing]>=0.13.2", "httpx>=0.28.1", "pydantic>=2.13.4", diff --git a/a2a/simple_generalist/src/simple_generalist/a2a_server/server.py b/a2a/simple_generalist/src/simple_generalist/a2a_server/server.py index 7a287696..512cbe8f 100644 --- a/a2a/simple_generalist/src/simple_generalist/a2a_server/server.py +++ b/a2a/simple_generalist/src/simple_generalist/a2a_server/server.py @@ -4,19 +4,20 @@ import traceback from typing import Any from a2a.server.agent_execution import AgentExecutor, RequestContext -from a2a.server.apps import A2AStarletteApplication from a2a.server.events.event_queue import EventQueue from a2a.server.request_handlers import DefaultRequestHandler +from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes from a2a.server.tasks import InMemoryTaskStore, TaskUpdater from a2a.types import ( AgentCapabilities, AgentCard, + AgentInterface, AgentSkill, - Part, TaskState, - TextPart, ) -from a2a.utils import new_agent_text_message, new_task +from a2a.helpers import new_task_from_user_message, new_text_part + +from starlette.applications import Starlette from autogen.mcp.mcp_client import create_toolkit, Toolkit from mcp import ClientSession @@ -69,7 +70,7 @@ def get_agent_card(settings: Settings) -> AgentCard: return AgentCard( name="Simple Generalist Agent", description="A generalist AG2 agent exposed via A2A, powered by MCP tools", - url=agent_url, + supported_interfaces=[AgentInterface(url=agent_url, protocol_binding="JSONRPC")], version="0.1.0", default_input_modes=["text"], default_output_modes=["text"], @@ -125,7 +126,7 @@ async def execute(self, context: RequestContext, event_queue: EventQueue): # Get or create task task = context.current_task if not task: - task = new_task(context.message) # type: ignore + task = new_task_from_user_message(context.message) # type: ignore await event_queue.enqueue_event(task) # Create task updater for progress events @@ -138,24 +139,20 @@ async def event_callback(message: str, final: bool = False): if final: # Final message with artifact - parts = [Part(root=TextPart(text=message))] + parts = [new_text_part(message)] await task_updater.add_artifact(parts) await task_updater.complete() else: # Progress update await task_updater.update_status( - TaskState.working, - new_agent_text_message( - message, - task_updater.context_id, - task_updater.task_id, - ), + TaskState.TASK_STATE_WORKING, + task_updater.new_agent_message([new_text_part(message)]), ) async def error_callback(message: str): """Send error event and mark task as failed.""" logger.info(f"Error event: {message}") - parts = [Part(root=TextPart(text=message))] + parts = [new_text_part(message)] await task_updater.add_artifact(parts) await task_updater.failed() @@ -234,16 +231,18 @@ def create_app(settings: Settings) -> Any: request_handler = DefaultRequestHandler( agent_executor=SimpleGeneralistExecutor(settings), task_store=InMemoryTaskStore(), - ) - - # Create A2A server - server = A2AStarletteApplication( agent_card=agent_card, - http_handler=request_handler, ) - # Build and return the app - app = server.build() + # a2a-sdk 1.x replaced A2AStarletteApplication with route factories that we + # assemble into a Starlette app ourselves. + routes = create_jsonrpc_routes(request_handler, rpc_url="/") + # Serve the current well-known path (/.well-known/agent-card.json) plus the + # legacy /.well-known/agent.json path for backward compatibility. + routes += create_agent_card_routes(agent_card) + routes += create_agent_card_routes(agent_card, card_url="/.well-known/agent.json") + + app = Starlette(routes=routes) logger.info("A2A server application created") return app diff --git a/a2a/simple_generalist/uv.lock b/a2a/simple_generalist/uv.lock index 749bb5ed..0d266481 100644 --- a/a2a/simple_generalist/uv.lock +++ b/a2a/simple_generalist/uv.lock @@ -4,23 +4,26 @@ requires-python = "==3.12.*" [[package]] name = "a2a-sdk" -version = "0.3.22" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "culsans" }, { name = "google-api-core" }, + { name = "googleapis-common-protos" }, { name = "httpx" }, { name = "httpx-sse" }, + { name = "json-rpc" }, + { name = "packaging" }, { name = "protobuf" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/92/a3/76f2d94a32a1b0dc760432d893a09ec5ed31de5ad51b1ef0f9d199ceb260/a2a_sdk-0.3.22.tar.gz", hash = "sha256:77a5694bfc4f26679c11b70c7f1062522206d430b34bc1215cfbb1eba67b7e7d", size = 231535, upload-time = "2025-12-16T18:39:21.19Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/7e/8ac10bbf8b15b16574355f39b17dbdf617a282c27b41c7ff2116e30336df/a2a_sdk-1.1.0.tar.gz", hash = "sha256:e8102dad1b36709dbdc3d19319e38e6dfa3b3a79c30416030eb2d482576be204", size = 375726, upload-time = "2026-05-29T09:34:43.015Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/e8/f4e39fd1cf0b3c4537b974637143f3ebfe1158dad7232d9eef15666a81ba/a2a_sdk-0.3.22-py3-none-any.whl", hash = "sha256:b98701135bb90b0ff85d35f31533b6b7a299bf810658c1c65f3814a6c15ea385", size = 144347, upload-time = "2025-12-16T18:39:19.218Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ea/3a5b160cfd51c67759b08748051094d9365ceff18127633d0021950c9860/a2a_sdk-1.1.0-py3-none-any.whl", hash = "sha256:d7f5846caf18033d8bf3108b11ec827dd8dd32f867c98848ede0e39474be93be", size = 241886, upload-time = "2026-05-29T09:34:41.484Z" }, ] [package.optional-dependencies] http-server = [ - { name = "fastapi" }, { name = "sse-starlette" }, { name = "starlette" }, ] @@ -58,12 +61,17 @@ tracing = [ ] [[package]] -name = "annotated-doc" -version = "0.0.4" +name = "aiologic" +version = "0.17.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +dependencies = [ + { name = "sniffio" }, + { name = "typing-extensions" }, + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/7a/d51f2fde1e8ae8a83431f8e97b7a71e9358cdb1d4d2ce6be387fa44d68de/aiologic-0.17.1.tar.gz", hash = "sha256:2e1b93b9e88ced318c2a63ad7b382688f40cbfe40e3d42258d49dc9c5aea179d", size = 252354, upload-time = "2026-06-27T20:41:33.25Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d3/2d310b1b839014034dba0cba685e492df8a5c7ad32c19cab7e979eed6554/aiologic-0.17.1-py3-none-any.whl", hash = "sha256:c66b319830fedb7ca3d2b2125fa6f5b653f89418c2a27ea76f259ec5f00943c0", size = 161331, upload-time = "2026-06-27T20:41:31.877Z" }, ] [[package]] @@ -214,6 +222,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3a/6a/bd2e7caa2facffedf172a45c1a02e551e6d7d4828658c9a245516a598d94/cryptography-46.0.4-cp38-abi3-win_amd64.whl", hash = "sha256:fa0900b9ef9c49728887d1576fd8d9e7e3ea872fa9b25ef9b64888adc434e976", size = 3466633, upload-time = "2026-01-28T00:24:21.851Z" }, ] +[[package]] +name = "culsans" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiologic" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d9/e3/49afa1bc180e0d28008ec6bcdf82a4072d1c7a41032b5b759b60814ca4b0/culsans-0.11.0.tar.gz", hash = "sha256:0b43d0d05dce6106293d114c86e3fb4bfc63088cfe8ff08ed3fe36891447fe33", size = 107546, upload-time = "2025-12-31T23:15:38.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/5d/9fb19fb38f6d6120422064279ea5532e22b84aa2be8831d49607194feda3/culsans-0.11.0-py3-none-any.whl", hash = "sha256:278d118f63fc75b9db11b664b436a1b83cc30d9577127848ba41420e66eb5a47", size = 21811, upload-time = "2025-12-31T23:15:37.189Z" }, +] + [[package]] name = "distro" version = "1.9.0" @@ -241,21 +262,6 @@ pydantic = [ { name = "pydantic" }, ] -[[package]] -name = "fastapi" -version = "0.128.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "annotated-doc" }, - { name = "pydantic" }, - { name = "starlette" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f6/59/28bde150415783ff084334e3de106eb7461a57864cf69f343950ad5a5ddd/fastapi-0.128.1.tar.gz", hash = "sha256:ce5be4fa26d4ce6f54debcc873d1fb8e0e248f5c48d7502ba6c61457ab2dc766", size = 374260, upload-time = "2026-02-04T17:35:10.542Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/08/3953db1979ea131c68279b997c6465080118b407f0800445b843f8e164b3/fastapi-0.128.1-py3-none-any.whl", hash = "sha256:ee82146bbf91ea5bbf2bb8629e4c6e056c4fbd997ea6068501b11b15260b50fb", size = 103810, upload-time = "2026-02-04T17:35:08.02Z" }, -] - [[package]] name = "google-api-core" version = "2.29.0" @@ -408,6 +414,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/67/8a/a342b2f0251f3dac4ca17618265d93bf244a2a4d089126e81e4c1056ac50/jiter-0.13.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb00b6d26db67a05fe3e12c76edc75f32077fb51deed13822dc648fa373bc19", size = 343768, upload-time = "2026-02-02T12:37:55.055Z" }, ] +[[package]] +name = "json-rpc" +version = "1.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/9e/59f4a5b7855ced7346ebf40a2e9a8942863f644378d956f68bcef2c88b90/json-rpc-1.15.0.tar.gz", hash = "sha256:e6441d56c1dcd54241c937d0a2dcd193bdf0bdc539b5316524713f554b7f85b9", size = 28854, upload-time = "2023-06-11T09:45:49.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/9e/820c4b086ad01ba7d77369fb8b11470a01fac9b4977f02e18659cf378b6b/json_rpc-1.15.0-py2.py3-none-any.whl", hash = "sha256:4a4668bbbe7116feb4abbd0f54e64a4adcf4b8f648f19ffa0848ad0f6606a9bf", size = 39450, upload-time = "2023-06-11T09:45:47.136Z" }, +] + [[package]] name = "jsonschema" version = "4.26.0" @@ -923,7 +938,7 @@ dev = [ [package.metadata] requires-dist = [ - { name = "a2a-sdk", extras = ["http-server"], specifier = ">=0.3.22" }, + { name = "a2a-sdk", extras = ["http-server"], specifier = ">=1.1.0,<2" }, { name = "ag2", extras = ["openai", "mcp", "tracing"], specifier = ">=0.13.2" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "opentelemetry-exporter-otlp-proto-http", specifier = ">=1.42.1" }, @@ -1055,3 +1070,23 @@ sdist = { url = "https://files.pythonhosted.org/packages/c4/1f/fa18009dea8469069 wheels = [ { url = "https://files.pythonhosted.org/packages/88/fa/e1388bbcf24ef3274f45c0c1c7b501fd14971037c1b6ee23610553307497/uvicorn-0.49.0-py3-none-any.whl", hash = "sha256:ba3d14c3ee7e41c6c654c46c9eb489d33213cdd30aa1696eab1374337c13f68f", size = 71376, upload-time = "2026-06-03T22:01:29.037Z" }, ] + +[[package]] +name = "wrapt" +version = "2.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/a4/282c8e64300a59fc834518a54bf0afabb4ff9218b5fa76958b450459a844/wrapt-2.2.2.tar.gz", hash = "sha256:0788e321027c999bf221b667bd4a54aaefd1a36283749a860ac3eb77daed0302", size = 129068, upload-time = "2026-06-20T23:49:44.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/85/180b40628b23772692a0c76e8030114e1c0ae068470ed531919f0a5f2a4a/wrapt-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8417fd3c674d3c8023d080292d29301531a12daf8bd938dd419710dd2f464f2b", size = 81484, upload-time = "2026-06-20T23:47:59.924Z" }, + { url = "https://files.pythonhosted.org/packages/94/f2/21c90f2a16689702e2aaff45795b11018dff2c9b1242bac10d225483f676/wrapt-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e7070c7472582e31af3dfc2622b2381a0df7435110a9388ed8db5ffbce67efb", size = 82151, upload-time = "2026-06-20T23:48:01.303Z" }, + { url = "https://files.pythonhosted.org/packages/5f/b3/7e6e9fcf4fe7e1b69a49fe6cc5a44e8224bab6283c5233c97e132f14908e/wrapt-2.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2e096c9d39a59b35b63c9aacfbbbec2088ff51ff1fc31051acc60a07f42f273a", size = 169828, upload-time = "2026-06-20T23:48:02.719Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/894f132d857ed5a9904d937baf368badcbe5ea9e436e2f1930fe21c9f1f0/wrapt-2.2.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d1a6050405bf334be33bf66296f113563622972a34900ae6fa60fd283a1a900", size = 171544, upload-time = "2026-06-20T23:48:04.266Z" }, + { url = "https://files.pythonhosted.org/packages/29/de/3c833e03725b477e9ea34028224dd21a48781830101e4e036f77e8b6b102/wrapt-2.2.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10adb01371408c6de504a6658b9886480f1a4919a83752748a387a504a21df79", size = 160663, upload-time = "2026-06-20T23:48:05.708Z" }, + { url = "https://files.pythonhosted.org/packages/33/be/27edce350b24e3054d9d047f65f16d4c4d4c1f3f31c4278a1f8a95c723c8/wrapt-2.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3442eee2a5798f9b451f1b2cd7518ce8b7e28a2a364696c414460a0e295c012a", size = 169387, upload-time = "2026-06-20T23:48:07.243Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c4/9fd9679af8bf38e146652c7f47b6b352c3e5795b4ad1c0b7f94e15ac2aa7/wrapt-2.2.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6c99012a22f735a85eed7c4b86a3e99c30fdd57d9e115b2b45f796264b58d0bf", size = 158849, upload-time = "2026-06-20T23:48:08.91Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c2/aa6c0c2206803068c6859dabe01f8c84c43744da93d4c67b8946d21655ee/wrapt-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b686cfc008776a3952d6213cb296ed7f45d782a8453936406faa89eac0835ab", size = 168147, upload-time = "2026-06-20T23:48:10.374Z" }, + { url = "https://files.pythonhosted.org/packages/42/63/3eb25da41049d20ae18fcab2dd8b056e02387c4bfa626cbdfb7c3b872e4f/wrapt-2.2.2-cp312-cp312-win32.whl", hash = "sha256:ef2cce266b5b0b07e19fa82e59673b81142b7a3607c8ed1254113d048ed668da", size = 77734, upload-time = "2026-06-20T23:48:11.769Z" }, + { url = "https://files.pythonhosted.org/packages/da/09/0390e008a305360948fa9ce69507d041ac12cb2ee5d28e34467e2ee79391/wrapt-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:abf8c20a2d72ee69e16328b3c91342c446e723bfe48bfcc4dded3b9722ac027f", size = 80585, upload-time = "2026-06-20T23:48:13.117Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b3/84c445c66969f2d3457276b183a48c91097d59bbef9af6c075366b0f8c36/wrapt-2.2.2-cp312-cp312-win_arm64.whl", hash = "sha256:c6c64c5d02578bc4c4bca4f0aef1504de933c1d5b4ac2710b9131111459506c8", size = 79553, upload-time = "2026-06-20T23:48:14.5Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d2/6317eb6d4554855bbf12d61857774af34747bf88a42c19bf306de67e2fa3/wrapt-2.2.2-py3-none-any.whl", hash = "sha256:5bad217350f19ce99ca5b5e71d406765ea86fe541628426772b657375ee1c048", size = 61460, upload-time = "2026-06-20T23:49:42.966Z" }, +] From f416380dcf7953f8a46e283390066ac7575615a6 Mon Sep 17 00:00:00 2001 From: Ed Snible Date: Wed, 1 Jul 2026 11:47:55 -0400 Subject: [PATCH 5/8] Upgrade claude_agent dependencies Signed-off-by: Ed Snible --- a2a/claude_agent/pyproject.toml | 4 +- a2a/claude_agent/src/claude_agent/agent.py | 32 +++-- a2a/claude_agent/src/claude_agent/events.py | 12 +- a2a/claude_agent/tests/test_agent.py | 3 +- a2a/claude_agent/uv.lock | 136 +++++++++++++++++--- 5 files changed, 148 insertions(+), 39 deletions(-) diff --git a/a2a/claude_agent/pyproject.toml b/a2a/claude_agent/pyproject.toml index f075b5df..223b684c 100644 --- a/a2a/claude_agent/pyproject.toml +++ b/a2a/claude_agent/pyproject.toml @@ -6,8 +6,8 @@ readme = "README.md" license = { text = "Apache" } requires-python = ">=3.11" dependencies = [ - # http-server extra pulls in the Starlette/SSE stack that A2AStarletteApplication needs. - "a2a-sdk[http-server]==0.3.26", + # http-server extra pulls in the Starlette/SSE stack the route factories need. + "a2a-sdk[http-server]>=1.1.0,<2", "pydantic-settings>=2.14.1", "uvicorn>=0.30", "starlette>=0.49.1", # Indirect; prevents CVE-2025-62727 diff --git a/a2a/claude_agent/src/claude_agent/agent.py b/a2a/claude_agent/src/claude_agent/agent.py index 8adb3fd9..910ecb5f 100644 --- a/a2a/claude_agent/src/claude_agent/agent.py +++ b/a2a/claude_agent/src/claude_agent/agent.py @@ -4,14 +4,15 @@ from textwrap import dedent import uvicorn - +from a2a.helpers import new_task_from_user_message from a2a.server.agent_execution import AgentExecutor, RequestContext -from a2a.server.apps import A2AStarletteApplication from a2a.server.events.event_queue import EventQueue from a2a.server.request_handlers import DefaultRequestHandler +from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes from a2a.server.tasks import InMemoryTaskStore, TaskUpdater -from a2a.types import AgentCapabilities, AgentCard, AgentSkill -from a2a.utils import new_task +from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill +from starlette.applications import Starlette + from claude_agent.configuration import Configuration from claude_agent.events import StreamTranslator from claude_agent.runner import run_turn @@ -46,7 +47,12 @@ def get_agent_card(host: str, port: int) -> AgentCard: - **prompt** (string) – the instruction or question for Claude. """ ), - url=os.getenv("AGENT_ENDPOINT", f"http://{host}:{port}").rstrip("/") + "/", + supported_interfaces=[ + AgentInterface( + url=os.getenv("AGENT_ENDPOINT", f"http://{host}:{port}").rstrip("/") + "/", + protocol_binding="JSONRPC", + ) + ], version="1.0.0", default_input_modes=["text"], default_output_modes=["text"], @@ -71,7 +77,7 @@ def __init__( async def execute(self, context: RequestContext, event_queue: EventQueue) -> None: task = context.current_task if not task: - task = new_task(context.message) # type: ignore + task = new_task_from_user_message(context.message) # type: ignore await event_queue.enqueue_event(task) task_updater = TaskUpdater(event_queue, task.id, task.context_id) translator = StreamTranslator(task_updater) @@ -118,11 +124,15 @@ def run() -> None: request_handler = DefaultRequestHandler( agent_executor=ClaudeAgentExecutor(config, registry, semaphore), task_store=InMemoryTaskStore(), + agent_card=agent_card, ) - server = A2AStarletteApplication(agent_card=agent_card, http_handler=request_handler) - # build() serves the agent card at /.well-known/agent-card.json natively - # (a2a-sdk's default AGENT_CARD_WELL_KNOWN_PATH), plus the legacy - # /.well-known/agent.json for back-compat — no custom route needed. - app = server.build() + # a2a-sdk 1.x replaced A2AStarletteApplication with route factories that we + # assemble into a Starlette app ourselves. Serve the current well-known path + # (/.well-known/agent-card.json) plus the legacy /.well-known/agent.json for + # back-compat. + routes = create_jsonrpc_routes(request_handler, rpc_url="/") + routes += create_agent_card_routes(agent_card) + routes += create_agent_card_routes(agent_card, card_url="/.well-known/agent.json") + app = Starlette(routes=routes) uvicorn.run(app, host=config.host, port=config.port) diff --git a/a2a/claude_agent/src/claude_agent/events.py b/a2a/claude_agent/src/claude_agent/events.py index 46cdbd71..4726d100 100644 --- a/a2a/claude_agent/src/claude_agent/events.py +++ b/a2a/claude_agent/src/claude_agent/events.py @@ -1,8 +1,8 @@ import json import logging -from a2a.types import TaskState, TextPart -from a2a.utils import new_agent_text_message +from a2a.helpers import new_text_part +from a2a.types import TaskState logger = logging.getLogger(__name__) @@ -33,8 +33,8 @@ async def _working(self, text: str) -> None: if not text.strip(): return await self._tu.update_status( - TaskState.working, - new_agent_text_message(text, self._tu.context_id, self._tu.task_id), + TaskState.TASK_STATE_WORKING, + self._tu.new_agent_message([new_text_part(text)]), ) async def handle(self, event: dict) -> None: @@ -70,8 +70,8 @@ async def finish(self) -> None: """Emit the terminal A2A state based on what was accumulated.""" if self.errored or self.final_text is None: reason = self.error_reason or "Claude produced no result" - await self._tu.add_artifact([TextPart(text=f"Error: {reason}")]) + await self._tu.add_artifact([new_text_part(f"Error: {reason}")]) await self._tu.failed() else: - await self._tu.add_artifact([TextPart(text=self.final_text)]) + await self._tu.add_artifact([new_text_part(self.final_text)]) await self._tu.complete() diff --git a/a2a/claude_agent/tests/test_agent.py b/a2a/claude_agent/tests/test_agent.py index 79e15f3c..8d5b7907 100644 --- a/a2a/claude_agent/tests/test_agent.py +++ b/a2a/claude_agent/tests/test_agent.py @@ -10,7 +10,8 @@ def test_agent_card_has_streaming_and_url(): card = get_agent_card("0.0.0.0", 8000) assert card.capabilities.streaming is True - assert card.url.endswith("/") + # a2a-sdk 1.x moved the URL from AgentCard.url into supported_interfaces. + assert card.supported_interfaces[0].url.endswith("/") assert card.skills # at least one skill advertised diff --git a/a2a/claude_agent/uv.lock b/a2a/claude_agent/uv.lock index faaced18..8979fe40 100644 --- a/a2a/claude_agent/uv.lock +++ b/a2a/claude_agent/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.11" resolution-markers = [ "python_full_version >= '3.13'", @@ -8,34 +8,42 @@ resolution-markers = [ [[package]] name = "a2a-sdk" -version = "0.3.26" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "culsans", marker = "python_full_version < '3.13'" }, { name = "google-api-core" }, + { name = "googleapis-common-protos" }, { name = "httpx" }, { name = "httpx-sse" }, + { name = "json-rpc" }, + { name = "packaging" }, { name = "protobuf" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/be/97/a6840e01795b182ce751ca165430d46459927cde9bfab838087cbb24aef7/a2a_sdk-0.3.26.tar.gz", hash = "sha256:44068e2d037afbb07ab899267439e9bc7eaa7ac2af94f1e8b239933c993ad52d", size = 274598, upload-time = "2026-04-09T15:21:13.902Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/7e/8ac10bbf8b15b16574355f39b17dbdf617a282c27b41c7ff2116e30336df/a2a_sdk-1.1.0.tar.gz", hash = "sha256:e8102dad1b36709dbdc3d19319e38e6dfa3b3a79c30416030eb2d482576be204", size = 375726, upload-time = "2026-05-29T09:34:43.015Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dd/d5/51f4ee1bf3b736add42a542d3c8a3fd3fa85f3d36c17972127defc46c26f/a2a_sdk-0.3.26-py3-none-any.whl", hash = "sha256:754e0573f6d33b225c1d8d51f640efa69cbbed7bdfb06ce9c3540ea9f58d4a91", size = 151016, upload-time = "2026-04-09T15:21:12.35Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ea/3a5b160cfd51c67759b08748051094d9365ceff18127633d0021950c9860/a2a_sdk-1.1.0-py3-none-any.whl", hash = "sha256:d7f5846caf18033d8bf3108b11ec827dd8dd32f867c98848ede0e39474be93be", size = 241886, upload-time = "2026-05-29T09:34:41.484Z" }, ] [package.optional-dependencies] http-server = [ - { name = "fastapi" }, { name = "sse-starlette" }, { name = "starlette" }, ] [[package]] -name = "annotated-doc" -version = "0.0.4" +name = "aiologic" +version = "0.17.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" } +dependencies = [ + { name = "sniffio", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "wrapt", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/7a/d51f2fde1e8ae8a83431f8e97b7a71e9358cdb1d4d2ce6be387fa44d68de/aiologic-0.17.1.tar.gz", hash = "sha256:2e1b93b9e88ced318c2a63ad7b382688f40cbfe40e3d42258d49dc9c5aea179d", size = 252354, upload-time = "2026-06-27T20:41:33.25Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d3/2d310b1b839014034dba0cba685e492df8a5c7ad32c19cab7e979eed6554/aiologic-0.17.1-py3-none-any.whl", hash = "sha256:c66b319830fedb7ca3d2b2125fa6f5b653f89418c2a27ea76f259ec5f00943c0", size = 161331, upload-time = "2026-06-27T20:41:31.877Z" }, ] [[package]] @@ -247,7 +255,7 @@ dev = [ [package.metadata] requires-dist = [ - { name = "a2a-sdk", extras = ["http-server"], specifier = "==0.3.26" }, + { name = "a2a-sdk", extras = ["http-server"], specifier = ">=1.1.0,<2" }, { name = "pydantic-settings", specifier = ">=2.14.1" }, { name = "starlette", specifier = ">=0.49.1" }, { name = "uvicorn", specifier = ">=0.30" }, @@ -340,19 +348,16 @@ wheels = [ ] [[package]] -name = "fastapi" -version = "0.136.3" +name = "culsans" +version = "0.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "annotated-doc" }, - { name = "pydantic" }, - { name = "starlette" }, - { name = "typing-extensions" }, - { name = "typing-inspection" }, + { name = "aiologic", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/81/2d/ff8d91d7b564d464629a0fd50a4489c97fcb836ac230bf3a7269232a9b1f/fastapi-0.136.3.tar.gz", hash = "sha256:e487fae93ad408e6f47641ee4dfe389864fd7bec92e547ea8498fc13f43e83ab", size = 396410, upload-time = "2026-05-23T18:53:15.192Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/e3/49afa1bc180e0d28008ec6bcdf82a4072d1c7a41032b5b759b60814ca4b0/culsans-0.11.0.tar.gz", hash = "sha256:0b43d0d05dce6106293d114c86e3fb4bfc63088cfe8ff08ed3fe36891447fe33", size = 107546, upload-time = "2025-12-31T23:15:38.196Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/82/45359b62a067409bd929ae8a56b8ed13e5a8c8a61194b3c236920999ab83/fastapi-0.136.3-py3-none-any.whl", hash = "sha256:3d2a69bdf04b7e9f3afa292c3bc7a98816bbfafa10bc9b45f3f3700d2f761620", size = 117481, upload-time = "2026-05-23T18:53:16.924Z" }, + { url = "https://files.pythonhosted.org/packages/e0/5d/9fb19fb38f6d6120422064279ea5532e22b84aa2be8831d49607194feda3/culsans-0.11.0-py3-none-any.whl", hash = "sha256:278d118f63fc75b9db11b664b436a1b83cc30d9577127848ba41420e66eb5a47", size = 21811, upload-time = "2025-12-31T23:15:37.189Z" }, ] [[package]] @@ -460,6 +465,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] +[[package]] +name = "json-rpc" +version = "1.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/9e/59f4a5b7855ced7346ebf40a2e9a8942863f644378d956f68bcef2c88b90/json-rpc-1.15.0.tar.gz", hash = "sha256:e6441d56c1dcd54241c937d0a2dcd193bdf0bdc539b5316524713f554b7f85b9", size = 28854, upload-time = "2023-06-11T09:45:49.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/9e/820c4b086ad01ba7d77369fb8b11470a01fac9b4977f02e18659cf378b6b/json_rpc-1.15.0-py2.py3-none-any.whl", hash = "sha256:4a4668bbbe7116feb4abbd0f54e64a4adcf4b8f648f19ffa0848ad0f6606a9bf", size = 39450, upload-time = "2023-06-11T09:45:47.136Z" }, +] + [[package]] name = "packaging" version = "26.2" @@ -728,6 +742,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, ] +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + [[package]] name = "sse-starlette" version = "3.4.4" @@ -796,3 +819,78 @@ sdist = { url = "https://files.pythonhosted.org/packages/e6/bf/f6544ba992ddb9a60 wheels = [ { url = "https://files.pythonhosted.org/packages/01/be/72532be3da7acc5fdfbccdb95215cd04f995a0886532a5b423f929cda4cc/uvicorn-0.48.0-py3-none-any.whl", hash = "sha256:48097851328b87ec36117d3d575234519eb58c2b22d79666e9bbc6c49a761dad", size = 71410, upload-time = "2026-05-24T12:08:40.258Z" }, ] + +[[package]] +name = "wrapt" +version = "2.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/a4/282c8e64300a59fc834518a54bf0afabb4ff9218b5fa76958b450459a844/wrapt-2.2.2.tar.gz", hash = "sha256:0788e321027c999bf221b667bd4a54aaefd1a36283749a860ac3eb77daed0302", size = 129068, upload-time = "2026-06-20T23:49:44.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/15/0c2d55168707465abfc41f33c0b23d792a5fa9b65c26983606940900a120/wrapt-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f1a2ff355ece6a111ca7a20dc86df6659c9205d3fcee674ca34f2a2854fd4e73", size = 80782, upload-time = "2026-06-20T23:47:44.367Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b5/5c0b093eb48f8a062ef6267d3cb36e9bb1b88440181f6545a383c60efdf8/wrapt-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55b9a899e6fff5444f229d30aa6e9ac92d2216d9d60f33c771b5d76a760d5f8e", size = 81678, upload-time = "2026-06-20T23:47:45.857Z" }, + { url = "https://files.pythonhosted.org/packages/34/f3/de70937472dd3e8a4e6811192f9c6075efdffd4a2cd9b4596bf160f89668/wrapt-2.2.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a2d78c363f97d8bd718ee40432c66395685e9e98528ccaa423c3355d1715a26d", size = 159671, upload-time = "2026-06-20T23:47:47.345Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ec/40aed2330e7f02ecf74386ffcfef9ccb7108c6a430f15b6a252b663b1bed/wrapt-2.2.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d619e1eed9bd4f6ed9f24cd61971aa086fa86505289628d464bcf8a2c2e3f328", size = 160785, upload-time = "2026-06-20T23:47:48.759Z" }, + { url = "https://files.pythonhosted.org/packages/45/04/aa5309beed5344b00220ae6b3b24055852192656194c27947bee1736306a/wrapt-2.2.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:518b0c5e323511ec56a38894802ddd5e1222626484e68efe63f201854ad788e5", size = 153699, upload-time = "2026-06-20T23:47:50.177Z" }, + { url = "https://files.pythonhosted.org/packages/01/df/2def7e99d1fe87eea413f95f671924cdddcb08823b1ffd212748dfa6d062/wrapt-2.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4bccea5cdecffa9dd70e343741f0e41e0a16619313d04b72f78bb525162ebcd0", size = 159695, upload-time = "2026-06-20T23:47:51.602Z" }, + { url = "https://files.pythonhosted.org/packages/c7/f6/a906d01a2ce12157bad2404957b3e2140da354b8a70b2fa48bbf282871c0/wrapt-2.2.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:209112cafd963710a05d199aae431d79a28bc76eb8e6d1bbbb8ad24340722cae", size = 152813, upload-time = "2026-06-20T23:47:53.03Z" }, + { url = "https://files.pythonhosted.org/packages/02/49/bc0086292d239575b4c08f4cf8a4079fa58abbad58ec23abf84833a283ed/wrapt-2.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5a5290e4bf2f332fc29ce72ffb9a2fff678aaac047e2e9f5f7165cd7792e099", size = 158809, upload-time = "2026-06-20T23:47:54.391Z" }, + { url = "https://files.pythonhosted.org/packages/55/83/8fbd034de1f3e907edaa18786d5dd8f6932874edee0826c7cecb5cab03a1/wrapt-2.2.2-cp311-cp311-win32.whl", hash = "sha256:5499236ad1dc116012e2a5dd943f3f31af12fce452128e2bbcbd55a7d3d4d14c", size = 77414, upload-time = "2026-06-20T23:47:55.882Z" }, + { url = "https://files.pythonhosted.org/packages/7e/9c/23695baa331c6de4e874c3d78b8e0bed92e1d2a274e665b29858f6841672/wrapt-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:8636809939152be6ae20a6cef0fed9fe60f411b47847d0426a826884b469e971", size = 80368, upload-time = "2026-06-20T23:47:57.237Z" }, + { url = "https://files.pythonhosted.org/packages/08/49/40cefc342bf89b234a4490d741290fce781774b831aefb39c25471da96c9/wrapt-2.2.2-cp311-cp311-win_arm64.whl", hash = "sha256:5d0a142f7af07caeb5e5da87493162a7b8efa19ba919e550a746f7446e13fb30", size = 79489, upload-time = "2026-06-20T23:47:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/2a/85/180b40628b23772692a0c76e8030114e1c0ae068470ed531919f0a5f2a4a/wrapt-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8417fd3c674d3c8023d080292d29301531a12daf8bd938dd419710dd2f464f2b", size = 81484, upload-time = "2026-06-20T23:47:59.924Z" }, + { url = "https://files.pythonhosted.org/packages/94/f2/21c90f2a16689702e2aaff45795b11018dff2c9b1242bac10d225483f676/wrapt-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e7070c7472582e31af3dfc2622b2381a0df7435110a9388ed8db5ffbce67efb", size = 82151, upload-time = "2026-06-20T23:48:01.303Z" }, + { url = "https://files.pythonhosted.org/packages/5f/b3/7e6e9fcf4fe7e1b69a49fe6cc5a44e8224bab6283c5233c97e132f14908e/wrapt-2.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2e096c9d39a59b35b63c9aacfbbbec2088ff51ff1fc31051acc60a07f42f273a", size = 169828, upload-time = "2026-06-20T23:48:02.719Z" }, + { url = "https://files.pythonhosted.org/packages/0b/43/894f132d857ed5a9904d937baf368badcbe5ea9e436e2f1930fe21c9f1f0/wrapt-2.2.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d1a6050405bf334be33bf66296f113563622972a34900ae6fa60fd283a1a900", size = 171544, upload-time = "2026-06-20T23:48:04.266Z" }, + { url = "https://files.pythonhosted.org/packages/29/de/3c833e03725b477e9ea34028224dd21a48781830101e4e036f77e8b6b102/wrapt-2.2.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10adb01371408c6de504a6658b9886480f1a4919a83752748a387a504a21df79", size = 160663, upload-time = "2026-06-20T23:48:05.708Z" }, + { url = "https://files.pythonhosted.org/packages/33/be/27edce350b24e3054d9d047f65f16d4c4d4c1f3f31c4278a1f8a95c723c8/wrapt-2.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3442eee2a5798f9b451f1b2cd7518ce8b7e28a2a364696c414460a0e295c012a", size = 169387, upload-time = "2026-06-20T23:48:07.243Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c4/9fd9679af8bf38e146652c7f47b6b352c3e5795b4ad1c0b7f94e15ac2aa7/wrapt-2.2.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6c99012a22f735a85eed7c4b86a3e99c30fdd57d9e115b2b45f796264b58d0bf", size = 158849, upload-time = "2026-06-20T23:48:08.91Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c2/aa6c0c2206803068c6859dabe01f8c84c43744da93d4c67b8946d21655ee/wrapt-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b686cfc008776a3952d6213cb296ed7f45d782a8453936406faa89eac0835ab", size = 168147, upload-time = "2026-06-20T23:48:10.374Z" }, + { url = "https://files.pythonhosted.org/packages/42/63/3eb25da41049d20ae18fcab2dd8b056e02387c4bfa626cbdfb7c3b872e4f/wrapt-2.2.2-cp312-cp312-win32.whl", hash = "sha256:ef2cce266b5b0b07e19fa82e59673b81142b7a3607c8ed1254113d048ed668da", size = 77734, upload-time = "2026-06-20T23:48:11.769Z" }, + { url = "https://files.pythonhosted.org/packages/da/09/0390e008a305360948fa9ce69507d041ac12cb2ee5d28e34467e2ee79391/wrapt-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:abf8c20a2d72ee69e16328b3c91342c446e723bfe48bfcc4dded3b9722ac027f", size = 80585, upload-time = "2026-06-20T23:48:13.117Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b3/84c445c66969f2d3457276b183a48c91097d59bbef9af6c075366b0f8c36/wrapt-2.2.2-cp312-cp312-win_arm64.whl", hash = "sha256:c6c64c5d02578bc4c4bca4f0aef1504de933c1d5b4ac2710b9131111459506c8", size = 79553, upload-time = "2026-06-20T23:48:14.5Z" }, + { url = "https://files.pythonhosted.org/packages/43/fc/f32f4b22c6511173c11d9e541ab4e7d8467a0f1b3455acaf784115d31ff8/wrapt-2.2.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9e8b648270c613720a202d9a45ebabc33261b22c3a839b115ac5bce8c0bb0d69", size = 81296, upload-time = "2026-06-20T23:48:15.881Z" }, + { url = "https://files.pythonhosted.org/packages/72/06/4d117d5d77a9344776c0248b24dae3d3dd2f58e5f765fa08cf887072e719/wrapt-2.2.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6fb7e94e8fe3e4c3067bb1653a91cce7c5e83acc119fdd41501b1bf74654617", size = 81841, upload-time = "2026-06-20T23:48:17.262Z" }, + { url = "https://files.pythonhosted.org/packages/15/ff/63ad96f98eb58a742b1a20d80f21da88924405910149950b912368150468/wrapt-2.2.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb18fc51e813df0d9c98049e3bf2298a5495a648602040e21fa3c7329371159e", size = 167882, upload-time = "2026-06-20T23:48:18.764Z" }, + { url = "https://files.pythonhosted.org/packages/20/1f/8bb62d8933df7acf3247194e6e9fc68edf9d2fa203252c89c94b319dd472/wrapt-2.2.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94b00b00f806eb3ef2abe9049ed45994a81ee9284884d96e6b8314927c6cea3d", size = 167411, upload-time = "2026-06-20T23:48:20.315Z" }, + { url = "https://files.pythonhosted.org/packages/17/09/8789dcb09ee1de715727db7521aabbb68ffa68dfade3a49468440cfced49/wrapt-2.2.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:62415fd095bc590b842b6d092f2b5d9ccbaeb7e0b28535c03dcea2718b48636b", size = 158607, upload-time = "2026-06-20T23:48:21.728Z" }, + { url = "https://files.pythonhosted.org/packages/9c/20/66e02562d53ee67d841f175e38e3c993c2d78a3e104c576cad61c028b43c/wrapt-2.2.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a41e758d80dc0ab8c210f641ac892009d356cf1f955d97db544c8dd317b4d14c", size = 166367, upload-time = "2026-06-20T23:48:23.177Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a3/832ac4e41222fb263b3042d42c2f08d305db7d0f0c9b1d3a271a9eede8f6/wrapt-2.2.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b84cd4058001c9727b0e9980b7a9e66325b5ca748b1b578e822cade1bc6b304f", size = 157176, upload-time = "2026-06-20T23:48:24.711Z" }, + { url = "https://files.pythonhosted.org/packages/b7/01/1bd5e4d2df9c0178989ac8da9186543465388588ee2ef153e2591accebef/wrapt-2.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:26fc73a1b15e0946d2942b9a4426d162b51676338327dc067ccd8d2d76385f94", size = 167025, upload-time = "2026-06-20T23:48:26.118Z" }, + { url = "https://files.pythonhosted.org/packages/1c/69/583ed25291ab53e1ec117135fb1c33425e2f46d2bc8f29c17f7a94cf4274/wrapt-2.2.2-cp313-cp313-win32.whl", hash = "sha256:3c4095803491f6ef72128914c28ec05bbad9758433bb35f6715a3e9c8e46fb2d", size = 77605, upload-time = "2026-06-20T23:48:27.643Z" }, + { url = "https://files.pythonhosted.org/packages/29/68/e69fc6d06e1523c68e0d00f95c9aed1158ce9908ee41603f7f2eae3d5db6/wrapt-2.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:2cb07f414fab25dbe6b5c7398e1491423a5c81a6209533639969a6c928d474a4", size = 80508, upload-time = "2026-06-20T23:48:29.013Z" }, + { url = "https://files.pythonhosted.org/packages/55/21/fe7a393d9e5dc0923bed8f5d857e9dcff210f1fa0888c02cc8f3ffaa55aa/wrapt-2.2.2-cp313-cp313-win_arm64.whl", hash = "sha256:1fc7691f070220215cccb2a20836b9adbaecb8ff22ad47abe63de5f110994fac", size = 79565, upload-time = "2026-06-20T23:48:30.429Z" }, + { url = "https://files.pythonhosted.org/packages/b6/e5/c120d13bf5091164f68c3c1657e84f16f57e71d978421b626393ac5bd7eb/wrapt-2.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ec8f83949028366531383603139403cac7a826e4011955813cdd640017845ce5", size = 83264, upload-time = "2026-06-20T23:48:31.807Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b0/d4a1eb97e0e286625bdf21bc7f702637f9607787ffbbdb5ec14d50c79dbf/wrapt-2.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4b481fb0c40d9fd90a5809911208da700987d373a20a4709dc9e3944af7a6bec", size = 83791, upload-time = "2026-06-20T23:48:33.482Z" }, + { url = "https://files.pythonhosted.org/packages/18/1e/f060df47755e87b57684cee7bfc1362b204df55fac96ffebc0631b697b79/wrapt-2.2.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0065a3b657cec06813b4241d2462ccec287f6863103d7445b725fb3a889736f9", size = 203399, upload-time = "2026-06-20T23:48:34.97Z" }, + { url = "https://files.pythonhosted.org/packages/c4/de/2316a757a1abb6453700b79d83e532146dcef2611348282d4d8889792161/wrapt-2.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:30f7424af5c5c345b7f26490e097f74a2ef45b3d08b664dc33571aee3bd3b56c", size = 210461, upload-time = "2026-06-20T23:48:36.569Z" }, + { url = "https://files.pythonhosted.org/packages/ed/29/d1160785ae18ca2495a6d82a21154103d74f656c9fd457fb35f6b11b965a/wrapt-2.2.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:07fdcb012821859168641acf68afad61ef9783cf37100af85f152550e9677194", size = 195313, upload-time = "2026-06-20T23:48:38.175Z" }, + { url = "https://files.pythonhosted.org/packages/f5/2d/7caa9598ae61a9cf0989cc501739cbeeb7d650ab3193cca1407b9af0c6ab/wrapt-2.2.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f90038ab58fafb584801ca62d72384d7d5225d93c76f7b773c22fae545bd8066", size = 206116, upload-time = "2026-06-20T23:48:39.804Z" }, + { url = "https://files.pythonhosted.org/packages/ac/02/281ea1088b8650d865f311b35cf86fd21df89128e2909714f1161e01c9d0/wrapt-2.2.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:c5d7825491bfa2d08b97e9557768987952c7b9ae687d06c3320b40a37ccb7f20", size = 192668, upload-time = "2026-06-20T23:48:41.346Z" }, + { url = "https://files.pythonhosted.org/packages/be/7d/976e2d5b4b5c5babda40974edd54d0a5585cb60132ed86b46f4b80239b16/wrapt-2.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0ad520e6daa9bbf136f14de735474dbec7dcc0891f718e1d274ce8dc92e645af", size = 198891, upload-time = "2026-06-20T23:48:43.056Z" }, + { url = "https://files.pythonhosted.org/packages/59/b7/e47651797c097f75a37e2ce86dcf04048ff576f3a674f7c558df7b5e9622/wrapt-2.2.2-cp313-cp313t-win32.whl", hash = "sha256:25904acb9475f46c24fe0423dbc8fda8cc5fbc282ab3dc6e72e919748c53f4e9", size = 78537, upload-time = "2026-06-20T23:48:44.509Z" }, + { url = "https://files.pythonhosted.org/packages/d1/6f/9fa5d59fb06d890defb5a8f727ce6a14d2932c8760153f96956628559fee/wrapt-2.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:305d4c247d61c4115794a169141823c62f719525ddb90b23aa332741c77d2c28", size = 82005, upload-time = "2026-06-20T23:48:46.391Z" }, + { url = "https://files.pythonhosted.org/packages/15/80/4c7bd9873d1f9f7d138d93556b500469dbe24f42710b877519c2b9eb380d/wrapt-2.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c20279cd1a29800815d7b2d6338b60a6c6e78263f9d6e62e0eda251ba9cae2d0", size = 80762, upload-time = "2026-06-20T23:48:47.964Z" }, + { url = "https://files.pythonhosted.org/packages/24/05/7fd9c3f83b2c74cbfc572a0b88aa37431e04bd8aed70d2c0efd3464206de/wrapt-2.2.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:0e64826f920c42d9d9f87e8cc09ffae66c51ede12d59061a5a426deb9aa71745", size = 81341, upload-time = "2026-06-20T23:48:49.39Z" }, + { url = "https://files.pythonhosted.org/packages/4b/68/1bfa43100dd90d4ef74a05897b86275cf57e1313ca14aae2545bc9f872c9/wrapt-2.2.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dcaa5e1451bd8751d7bd1568dfa3321c78092a52a7ecb5d1a0f18a5791e1fd00", size = 81921, upload-time = "2026-06-20T23:48:50.986Z" }, + { url = "https://files.pythonhosted.org/packages/74/eb/df7b7f0b631dbbc750f39be27d8b55f65777d8ac86da80e12be41a644c4b/wrapt-2.2.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0abfd648dac9ac9c5b3aa9b523d27f1789046640b58dcd5652a720ddb325e1fc", size = 167713, upload-time = "2026-06-20T23:48:52.598Z" }, + { url = "https://files.pythonhosted.org/packages/4d/9a/d1bd36f6d088c8e652a9383cabbd49af30b8c576302a7eccddbab6963e3f/wrapt-2.2.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f4bfd8d1eb438153eff8b8cfe87f032ba65731e1ce06138b5090f745a33f6f95", size = 166779, upload-time = "2026-06-20T23:48:54.33Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ae/24ffacd4187fac2740a1972093929e836dea092d42c87d728cd98fee11a6/wrapt-2.2.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c427c9d06d859848a69f0d928fe28b5c33a941b2265d10a0e1f15cd244f1ee33", size = 158407, upload-time = "2026-06-20T23:48:55.944Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ed/974427668249a356051e8d67d47fa54ef6c777f0fcf3bae9d292c047d4b6/wrapt-2.2.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4250b43d1a129d947e083c4dc6baf333c9bb34edd26f912d5b0457841fc858ab", size = 166594, upload-time = "2026-06-20T23:48:57.617Z" }, + { url = "https://files.pythonhosted.org/packages/fb/5f/e1d7c6e4523f78db2fbd7826babd0348da1d5e0834c4f918b9ab5757dfae/wrapt-2.2.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:173e5bb5ca350a6e0abab60b7ec7cdd7992a814cb14b4de670a28f067f105663", size = 157068, upload-time = "2026-06-20T23:48:59.171Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c1/7ebd1027f00700c0b0233b20aceef2b4784294ed64971424c4a78e069e34/wrapt-2.2.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:aa14b01804bce36c6d63d7b6a4f55df390f29f8648cc13a1f40b166f4d54680d", size = 166470, upload-time = "2026-06-20T23:49:00.737Z" }, + { url = "https://files.pythonhosted.org/packages/99/eb/974e471a6a978b8180186b8a9dc5ae3361ce269a967190b709b8ce17abfb/wrapt-2.2.2-cp314-cp314-win32.whl", hash = "sha256:58f9f8d637c9a6e245c6ef5b109b67ec187d2faed23d1405656b51d96e0a5b56", size = 78062, upload-time = "2026-06-20T23:49:02.327Z" }, + { url = "https://files.pythonhosted.org/packages/49/ec/e1281156cdc7a66693838ad7a0865ad641c74abd337a957d668b575aaffb/wrapt-2.2.2-cp314-cp314-win_amd64.whl", hash = "sha256:385cb1866f20479e83299af585375bfa0a4b0c6c9907a981483ea782ea8ae406", size = 80832, upload-time = "2026-06-20T23:49:03.837Z" }, + { url = "https://files.pythonhosted.org/packages/45/7d/1b6b5ddd94005a2dac97a4490c9838f3154977850d633abcb65b30089437/wrapt-2.2.2-cp314-cp314-win_arm64.whl", hash = "sha256:8ffbeaea6771a6eba6e6eeb09767864995726bc8240bb54baf88a9bb1db34d5c", size = 80029, upload-time = "2026-06-20T23:49:05.237Z" }, + { url = "https://files.pythonhosted.org/packages/b0/33/9ebcf8aafe91c601127cbd93708c16aa8f688f34a10bf004046803ecdc4f/wrapt-2.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:09f811d43f6f33ec7515f0be76b159569f4057ab54d3e079c3204dddb90afa2a", size = 83357, upload-time = "2026-06-20T23:49:06.632Z" }, + { url = "https://files.pythonhosted.org/packages/39/38/ec45b635153327b52e52732a0ea980e5f00b7efba65f9e018828f1e69daa/wrapt-2.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a795d3c06e5fbf9ea2f13196180b77aeab1b4685917256ee0d014cc163d90063", size = 83794, upload-time = "2026-06-20T23:49:08.098Z" }, + { url = "https://files.pythonhosted.org/packages/4e/ea/1a89e6d3b7a83c3affe5c09cde77792c947e63e4bc85ad84cd5bb9abb0d8/wrapt-2.2.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:45c2f2768e790c9f8db90f239ef23a2af8e7570f25a35619ef902df4a738447f", size = 203362, upload-time = "2026-06-20T23:49:09.811Z" }, + { url = "https://files.pythonhosted.org/packages/19/d8/3b58763d9863b5a73771c0d97110f9595d248db454009e07e1535ee905a4/wrapt-2.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bbf00ee0cb55ec24e2b0995a71942b85b21a066db8f3f46e1dbfdb9433ffba81", size = 210449, upload-time = "2026-06-20T23:49:11.521Z" }, + { url = "https://files.pythonhosted.org/packages/2d/6f/17fd9e053103d8be148d20d5d7505facc72d5fe1f9127973904ceaed79cf/wrapt-2.2.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2252f77663651b89255895f58cc6ac08fcb206d4371813e5af61bb62d4f7689c", size = 195349, upload-time = "2026-06-20T23:49:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/ef/04/d0d1ccaaa12cb7dccf28a23f0279a608ba498f71e81d949d5ed54bcfd5c1/wrapt-2.2.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2cd7181ab1c31192ff5219269830744b5a62020b3a6d433588c4f1c95b8f8bff", size = 206099, upload-time = "2026-06-20T23:49:15.051Z" }, + { url = "https://files.pythonhosted.org/packages/44/b3/e8aa07b619890a2aa6cde1931b1887abb08820721b564a5f80b7ca3f3aa0/wrapt-2.2.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6fe35fd51b74867d8b80174c277bd6bbf6a73e443f908129dc531c4b688a20d5", size = 192728, upload-time = "2026-06-20T23:49:16.854Z" }, + { url = "https://files.pythonhosted.org/packages/b7/f0/1819fb50f0d3c9bd758d8a83b56f1b470dee8b5b8eac8702b7c137cea9d4/wrapt-2.2.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:11d95fc2fbad3163596c39d440e6f21ca9fccece74b56e30a37ac2fca786a07c", size = 198842, upload-time = "2026-06-20T23:49:18.504Z" }, + { url = "https://files.pythonhosted.org/packages/67/7c/e88313f16a99930b899ef970d91c281544a470749a359decad994483bbda/wrapt-2.2.2-cp314-cp314t-win32.whl", hash = "sha256:d8a15813215f33fa83667bfc978b300e35669ea8bb424e970a1426bcb7bc6cca", size = 79059, upload-time = "2026-06-20T23:49:20.107Z" }, + { url = "https://files.pythonhosted.org/packages/a0/4f/ac12fda57a55068a094ec42851fb0a40e8489d8941863d517452de62e507/wrapt-2.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:d09db0f7e8357060d3c38fc22a018aba683a796bf184360fd1a58f6fc180dc77", size = 82462, upload-time = "2026-06-20T23:49:21.631Z" }, + { url = "https://files.pythonhosted.org/packages/48/a7/df732dac86d9b2027c56bd163dbc883e037b16c3469614752e148d219c61/wrapt-2.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:f32fe639c39561ccc187bcae17e9271be0eb45f1c2952510d2f29b33ab577347", size = 81182, upload-time = "2026-06-20T23:49:23.199Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d2/6317eb6d4554855bbf12d61857774af34747bf88a42c19bf306de67e2fa3/wrapt-2.2.2-py3-none-any.whl", hash = "sha256:5bad217350f19ce99ca5b5e71d406765ea86fe541628426772b657375ee1c048", size = 61460, upload-time = "2026-06-20T23:49:42.966Z" }, +] From ea03cf017a5ab6689fae6b1141505a2902f31c18 Mon Sep 17 00:00:00 2001 From: Ed Snible Date: Wed, 1 Jul 2026 12:54:14 -0400 Subject: [PATCH 6/8] Format imports according to Ruff 0.11.4, which this repo uses Signed-off-by: Ed Snible --- a2a/claude_agent/src/claude_agent/agent.py | 4 ++-- a2a/generic_agent/src/generic_agent/agent.py | 8 ++++---- a2a/weather_service/src/weather_service/agent.py | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/a2a/claude_agent/src/claude_agent/agent.py b/a2a/claude_agent/src/claude_agent/agent.py index 910ecb5f..f7fe8b6f 100644 --- a/a2a/claude_agent/src/claude_agent/agent.py +++ b/a2a/claude_agent/src/claude_agent/agent.py @@ -4,6 +4,8 @@ from textwrap import dedent import uvicorn +from starlette.applications import Starlette + from a2a.helpers import new_task_from_user_message from a2a.server.agent_execution import AgentExecutor, RequestContext from a2a.server.events.event_queue import EventQueue @@ -11,8 +13,6 @@ from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes from a2a.server.tasks import InMemoryTaskStore, TaskUpdater from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill -from starlette.applications import Starlette - from claude_agent.configuration import Configuration from claude_agent.events import StreamTranslator from claude_agent.runner import run_turn diff --git a/a2a/generic_agent/src/generic_agent/agent.py b/a2a/generic_agent/src/generic_agent/agent.py index f990a219..bb778036 100644 --- a/a2a/generic_agent/src/generic_agent/agent.py +++ b/a2a/generic_agent/src/generic_agent/agent.py @@ -3,6 +3,10 @@ from textwrap import dedent import uvicorn +from langchain_core.messages import HumanMessage +from openinference.instrumentation.langchain import LangChainInstrumentor +from starlette.applications import Starlette + from a2a.helpers import new_task_from_user_message, new_text_part from a2a.server.agent_execution import AgentExecutor, RequestContext from a2a.server.events.event_queue import EventQueue @@ -10,10 +14,6 @@ from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes from a2a.server.tasks import InMemoryTaskStore, TaskUpdater from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill, TaskState -from langchain_core.messages import HumanMessage -from openinference.instrumentation.langchain import LangChainInstrumentor -from starlette.applications import Starlette - from generic_agent.config import Configuration from generic_agent.graph import get_graph, get_mcp_server_names, get_mcpclient, get_skill_folder_paths diff --git a/a2a/weather_service/src/weather_service/agent.py b/a2a/weather_service/src/weather_service/agent.py index 07dfe27e..3ceaa833 100644 --- a/a2a/weather_service/src/weather_service/agent.py +++ b/a2a/weather_service/src/weather_service/agent.py @@ -4,6 +4,10 @@ from textwrap import dedent import uvicorn +from langchain_core.messages import HumanMessage +from starlette.applications import Starlette +from starlette.middleware.base import BaseHTTPMiddleware + from a2a.helpers import new_task_from_user_message, new_text_part from a2a.server.agent_execution import AgentExecutor, RequestContext from a2a.server.events.event_queue import EventQueue @@ -11,10 +15,6 @@ from a2a.server.routes import create_agent_card_routes, create_jsonrpc_routes from a2a.server.tasks import InMemoryTaskStore, TaskUpdater from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill, TaskState -from langchain_core.messages import HumanMessage -from starlette.applications import Starlette -from starlette.middleware.base import BaseHTTPMiddleware - from weather_service.configuration import Configuration from weather_service.graph import get_graph, get_mcpclient from weather_service.observability import ( From 20aacf55e28a895a8218a773573fbdb94be28555 Mon Sep 17 00:00:00 2001 From: Ed Snible Date: Wed, 1 Jul 2026 13:10:05 -0400 Subject: [PATCH 7/8] Starlette import changes for tests Signed-off-by: Ed Snible --- tests/a2a/test_weather_secret_redaction.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/a2a/test_weather_secret_redaction.py b/tests/a2a/test_weather_secret_redaction.py index 9c519698..458efbf5 100644 --- a/tests/a2a/test_weather_secret_redaction.py +++ b/tests/a2a/test_weather_secret_redaction.py @@ -36,16 +36,19 @@ def _load_module(name: str, path: pathlib.Path): "langchain_core", "langchain_core.messages", "starlette", + "starlette.applications", "starlette.middleware", "starlette.middleware.base", "starlette.routing", "a2a", + "a2a.helpers", "a2a.server", "a2a.server.agent_execution", "a2a.server.apps", "a2a.server.events", "a2a.server.events.event_queue", "a2a.server.request_handlers", + "a2a.server.routes", "a2a.server.tasks", "a2a.types", "a2a.utils", From 87be0d5a8b3f4365c1131919a48a34528caf30cb Mon Sep 17 00:00:00 2001 From: Ed Snible Date: Wed, 1 Jul 2026 13:27:49 -0400 Subject: [PATCH 8/8] Allow A2A 0.3 clients Signed-off-by: Ed Snible --- a2a/claude_agent/src/claude_agent/agent.py | 3 ++- a2a/generic_agent/src/generic_agent/agent.py | 3 ++- a2a/git_issue_agent/a2a_agent.py | 3 ++- .../src/simple_generalist/a2a_server/server.py | 3 ++- a2a/weather_service/src/weather_service/agent.py | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/a2a/claude_agent/src/claude_agent/agent.py b/a2a/claude_agent/src/claude_agent/agent.py index f7fe8b6f..372d5870 100644 --- a/a2a/claude_agent/src/claude_agent/agent.py +++ b/a2a/claude_agent/src/claude_agent/agent.py @@ -130,7 +130,8 @@ def run() -> None: # assemble into a Starlette app ourselves. Serve the current well-known path # (/.well-known/agent-card.json) plus the legacy /.well-known/agent.json for # back-compat. - routes = create_jsonrpc_routes(request_handler, rpc_url="/") + # enable_v0_3_compat is needed because Kagenti uses A2A 0.3 client libraries + routes = create_jsonrpc_routes(request_handler, rpc_url="/", enable_v0_3_compat=True) routes += create_agent_card_routes(agent_card) routes += create_agent_card_routes(agent_card, card_url="/.well-known/agent.json") app = Starlette(routes=routes) diff --git a/a2a/generic_agent/src/generic_agent/agent.py b/a2a/generic_agent/src/generic_agent/agent.py index bb778036..56ba6348 100644 --- a/a2a/generic_agent/src/generic_agent/agent.py +++ b/a2a/generic_agent/src/generic_agent/agent.py @@ -217,7 +217,8 @@ def run(): # a2a-sdk 1.x replaced A2AStarletteApplication with route factories that we # assemble into a Starlette app ourselves. - routes = create_jsonrpc_routes(request_handler, rpc_url="/") + # enable_v0_3_compat is needed because Kagenti uses A2A 0.3 client libraries + routes = create_jsonrpc_routes(request_handler, rpc_url="/", enable_v0_3_compat=True) # Serve the current well-known path (/.well-known/agent-card.json) plus the # legacy /.well-known/agent.json path for backward compatibility. routes += create_agent_card_routes(agent_card) diff --git a/a2a/git_issue_agent/a2a_agent.py b/a2a/git_issue_agent/a2a_agent.py index fdcd1865..1cbb2761 100644 --- a/a2a/git_issue_agent/a2a_agent.py +++ b/a2a/git_issue_agent/a2a_agent.py @@ -218,7 +218,8 @@ def run(): # a2a-sdk 1.x replaced A2AStarletteApplication with route factories that we # assemble into a Starlette app ourselves. - routes = create_jsonrpc_routes(request_handler, rpc_url="/") + # enable_v0_3_compat is needed because Kagenti uses A2A 0.3 client libraries + routes = create_jsonrpc_routes(request_handler, rpc_url="/", enable_v0_3_compat=True) # Serve the current well-known path (/.well-known/agent-card.json) plus the # legacy /.well-known/agent.json path for backward compatibility. routes += create_agent_card_routes(agent_card) diff --git a/a2a/simple_generalist/src/simple_generalist/a2a_server/server.py b/a2a/simple_generalist/src/simple_generalist/a2a_server/server.py index 512cbe8f..46751a76 100644 --- a/a2a/simple_generalist/src/simple_generalist/a2a_server/server.py +++ b/a2a/simple_generalist/src/simple_generalist/a2a_server/server.py @@ -236,7 +236,8 @@ def create_app(settings: Settings) -> Any: # a2a-sdk 1.x replaced A2AStarletteApplication with route factories that we # assemble into a Starlette app ourselves. - routes = create_jsonrpc_routes(request_handler, rpc_url="/") + # enable_v0_3_compat is needed because Kagenti uses A2A 0.3 client libraries + routes = create_jsonrpc_routes(request_handler, rpc_url="/", enable_v0_3_compat=True) # Serve the current well-known path (/.well-known/agent-card.json) plus the # legacy /.well-known/agent.json path for backward compatibility. routes += create_agent_card_routes(agent_card) diff --git a/a2a/weather_service/src/weather_service/agent.py b/a2a/weather_service/src/weather_service/agent.py index 3ceaa833..0ae51099 100644 --- a/a2a/weather_service/src/weather_service/agent.py +++ b/a2a/weather_service/src/weather_service/agent.py @@ -249,7 +249,8 @@ def run(): # a2a-sdk 1.x replaced A2AStarletteApplication with route factories that we # assemble into a Starlette app ourselves. - routes = create_jsonrpc_routes(request_handler, rpc_url="/") + # enable_v0_3_compat is needed because Kagenti uses A2A 0.3 client libraries + routes = create_jsonrpc_routes(request_handler, rpc_url="/", enable_v0_3_compat=True) # Serve the current well-known path (/.well-known/agent-card.json) plus the # legacy /.well-known/agent.json path for backward compatibility. routes += create_agent_card_routes(agent_card)