Skip to content

Commit cbd1837

Browse files
committed
fix(cli): remove shadowing local json import breaking A2A setup
1 parent 78d1957 commit cbd1837

2 files changed

Lines changed: 76 additions & 1 deletion

File tree

src/google/adk/cli/fast_api.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,6 @@ async def _get_a2a_runner_async() -> Runner:
756756
)
757757

758758
import inspect
759-
import json
760759

761760
from google.adk.agents import Agent
762761
import google.auth

tests/unittests/cli/test_fast_api.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,6 +2041,82 @@ def test_openapi_json_schema_accessible(test_app):
20412041
logger.info("OpenAPI /openapi.json endpoint is accessible")
20422042

20432043

2044+
def test_a2a_setup_reaches_application_build(
2045+
mock_session_service,
2046+
mock_artifact_service,
2047+
mock_memory_service,
2048+
mock_agent_loader,
2049+
mock_eval_sets_manager,
2050+
mock_eval_set_results_manager,
2051+
temp_agents_dir_with_a2a,
2052+
monkeypatch,
2053+
):
2054+
"""Regression test for the A2A setup silently failing.
2055+
2056+
A function-local ``import json`` made ``json`` a local for the whole
2057+
``get_fast_api_app`` function, so the earlier ``json.load(agent.json)`` in
2058+
the A2A loop raised ``UnboundLocalError``. The surrounding ``except`` swallowed
2059+
it, so no A2A routes were ever mounted. This asserts the loop gets past the
2060+
``json.load`` call and actually builds the A2A application.
2061+
"""
2062+
with (
2063+
patch("signal.signal", return_value=None),
2064+
patch(
2065+
"google.adk.cli.fast_api.create_session_service_from_options",
2066+
return_value=mock_session_service,
2067+
),
2068+
patch(
2069+
"google.adk.cli.fast_api.create_artifact_service_from_options",
2070+
return_value=mock_artifact_service,
2071+
),
2072+
patch(
2073+
"google.adk.cli.fast_api.create_memory_service_from_options",
2074+
return_value=mock_memory_service,
2075+
),
2076+
patch(
2077+
"google.adk.cli.fast_api.AgentLoader",
2078+
return_value=mock_agent_loader,
2079+
),
2080+
patch(
2081+
"google.adk.cli.fast_api.LocalEvalSetsManager",
2082+
return_value=mock_eval_sets_manager,
2083+
),
2084+
patch(
2085+
"google.adk.cli.fast_api.LocalEvalSetResultsManager",
2086+
return_value=mock_eval_set_results_manager,
2087+
),
2088+
patch(
2089+
"google.adk.cli.fast_api._create_task_store_from_options",
2090+
return_value=MagicMock(),
2091+
),
2092+
patch("google.adk.a2a.executor.a2a_agent_executor.A2aAgentExecutor"),
2093+
patch("a2a.server.request_handlers.DefaultRequestHandler"),
2094+
patch("a2a.types.AgentCard", return_value=MagicMock()),
2095+
patch("a2a.server.apps.A2AStarletteApplication") as mock_a2a_app,
2096+
):
2097+
mock_app_instance = MagicMock()
2098+
mock_app_instance.routes.return_value = []
2099+
mock_a2a_app.return_value = mock_app_instance
2100+
2101+
monkeypatch.chdir(temp_agents_dir_with_a2a)
2102+
2103+
get_fast_api_app(
2104+
agents_dir=".",
2105+
web=True,
2106+
session_service_uri="",
2107+
artifact_service_uri="",
2108+
memory_service_uri="",
2109+
allow_origins=["*"],
2110+
a2a=True,
2111+
host="127.0.0.1",
2112+
port=8000,
2113+
)
2114+
2115+
# If json.load raised UnboundLocalError, execution never reaches the
2116+
# A2AStarletteApplication construction and this mock is never called.
2117+
assert mock_a2a_app.called
2118+
2119+
20442120
def test_a2a_agent_discovery(test_app_with_a2a):
20452121
"""Test that A2A agents are properly discovered and configured."""
20462122
# This test mainly verifies that the A2A setup doesn't break the app

0 commit comments

Comments
 (0)