fix(a2a): Support to_a2a(Workflow) and reject non-agent root nodes#5710
Closed
sokoliva wants to merge 1 commit into
Closed
fix(a2a): Support to_a2a(Workflow) and reject non-agent root nodes#5710sokoliva wants to merge 1 commit into
sokoliva wants to merge 1 commit into
Conversation
haranrk
approved these changes
May 29, 2026
b3eac05 to
f3f5019
Compare
copybara-service Bot
pushed a commit
that referenced
this pull request
Jun 2, 2026
### Link to Issue - Related: #5487 **Problem:** `to_a2a(workflow)` fails because `AgentCardBuilder` requires field `sub_agents` which `Workflow` does not have. **Solution:** - Make `to_a2a()` and `AgentCardBuilder` accept `Workflow` (the v2 graph orchestrator) as a root, not just `BaseAgent`. Previously crashed with`RuntimeError: 'Workflow' object has no attribute 'sub_agents'`. - Tighten the public type contract to `BaseAgent | Workflow` and reject other `BaseNode` subtypes (e.g. `FunctionNode`, `JoinNode`) at call time with `TypeError`. They previously produced a degenerate "custom agent" card silently. ### Testing Plan **tests/unittests/a2a/utils/test_agent_card_builder.py** — 9 new tests: - test_get_agent_type_workflow — returns 'graph_workflow' for the new v2 Workflow. - test_get_agent_skill_name_workflow — returns 'workflow' for Workflow. - test_init_rejects_function_node — AgentCardBuilder(agent=FunctionNode(...)) raises TypeError (regression coverage for the runtime guard). - test_init_rejects_arbitrary_object — AgentCardBuilder(agent="...") raises TypeError. - test_build_succeeds_for_llm_agent — regression coverage that the original BaseAgent path still works after the type narrowing. - test_build_succeeds_for_workflow_with_llm_agent_node — exact OP repro shape, end-to-end through build(). - test_build_succeeds_for_workflow_with_output_schema_node — covers the output_schema shape mentioned in the issue. - test_build_succeeds_for_empty_workflow — degenerate but valid case (no edges). - test_get_workflow_description_workflow_with_nodes — verifies graph nodes appear in the description string. - test_get_workflow_description_empty_workflow — returns None when no nodes. **tests/unittests/a2a/utils/test_agent_to_a2a.py** — 2 new tests, 1 rewritten: - test_to_a2a_succeeds_for_workflow (new) — end-to-end through the actual Starlette lifespan (the exact code path that crashed in the OP's repro). - test_to_a2a_rejects_function_node (new) — to_a2a(FunctionNode(...)) raises TypeError at call time. - test_to_a2a_rejects_non_agent_non_workflow (rewrote existing test_to_a2a_with_invalid_agent_type) — now asserts TypeError raised eagerly at to_a2a() call time instead of AttributeError raised lazily during request handling. This is a deliberate behavior change, not a regression: the old test encoded buggy lazy-failure UX where misuse only surfaced when a client hit the endpoint. **Unit Tests:** - [x] I have added or updated unit tests for my change. - [x] All unit tests pass locally. _Please include a summary of passed `pytest` results._ ran `uv run pytest tests/unittests` `6275 passed, 14 skipped, 25 xfailed, 10 xpassed, 2532 warnings ` ### Checklist - [x] I have read the [CONTRIBUTING.md](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) document. - [x] I have performed a self-review of my own code. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have added tests that prove my fix is effective or that my feature works. - [x] New and existing unit tests pass locally with my changes. - [x] I have manually tested my changes end-to-end. - [x] Any dependent changes have been merged and published in downstream modules. Merge #5710 Change-Id: I2330b2f3036cfd99c89b5d5c492f1c46c275974f
Collaborator
copybara-service Bot
pushed a commit
that referenced
this pull request
Jun 8, 2026
Port of GitHub PR: #5710 Problem: to_a2a(workflow) fails because AgentCardBuilder requires field sub_agents which Workflow does not have. Solution: - Make to_a2a() and AgentCardBuilder accept Workflow (the v2 graph orchestrator) as a root, not just BaseAgent. Previously crashed with RuntimeError: 'Workflow' object has no attribute 'sub_agents'. - Tighten the public type contract to BaseAgent | Workflow and reject other BaseNode subtypes (e.g. FunctionNode, JoinNode) at call time with TypeError. They previously produced a degenerate "custom agent" card silently. Ported tests to test_agent_card_builder.py and test_agent_to_a2a.py. Co-authored-by: Yifan Wang <wanyif@google.com> PiperOrigin-RevId: 927500389
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Link to Issue
Problem:
to_a2a(workflow)fails becauseAgentCardBuilderrequires fieldsub_agentswhichWorkflowdoes not have.Solution:
to_a2a()andAgentCardBuilderacceptWorkflow(the v2 graph orchestrator) as a root, not justBaseAgent. Previously crashed withRuntimeError: 'Workflow' object has no attribute 'sub_agents'.BaseAgent | Workflowand reject otherBaseNodesubtypes (e.g.FunctionNode,JoinNode) at call time withTypeError. They previously produced a degenerate "custom agent" card silently.Testing Plan
tests/unittests/a2a/utils/test_agent_card_builder.py — 9 new tests:
tests/unittests/a2a/utils/test_agent_to_a2a.py — 2 new tests, 1 rewritten:
Unit Tests:
Please include a summary of passed
pytestresults.ran
uv run pytest tests/unittests6275 passed, 14 skipped, 25 xfailed, 10 xpassed, 2532 warningsChecklist