Skip to content

Commit 2c75293

Browse files
DeanChensjcopybara-github
authored andcommitted
feat: Skip running a workflow agent if it has no sub-agents
PiperOrigin-RevId: 811528166
1 parent b2b80e7 commit 2c75293

File tree

6 files changed

+54
-0
lines changed

6 files changed

+54
-0
lines changed

src/google/adk/agents/loop_agent.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ class LoopAgent(BaseAgent):
6666
async def _run_async_impl(
6767
self, ctx: InvocationContext
6868
) -> AsyncGenerator[Event, None]:
69+
if not self.sub_agents:
70+
return
71+
6972
times_looped = 0
7073
while not self.max_iterations or times_looped < self.max_iterations:
7174
for sub_agent in self.sub_agents:

src/google/adk/agents/parallel_agent.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ class ParallelAgent(BaseAgent):
175175
async def _run_async_impl(
176176
self, ctx: InvocationContext
177177
) -> AsyncGenerator[Event, None]:
178+
if not self.sub_agents:
179+
return
180+
178181
agent_runs = [
179182
sub_agent.run_async(
180183
_create_branch_ctx_for_sub_agent(self, sub_agent, ctx)

src/google/adk/agents/sequential_agent.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ class SequentialAgent(BaseAgent):
5151
async def _run_async_impl(
5252
self, ctx: InvocationContext
5353
) -> AsyncGenerator[Event, None]:
54+
# Skip if there is no sub-agent.
55+
if not self.sub_agents:
56+
return
57+
5458
for sub_agent in self.sub_agents:
5559
pause_invocation = False
5660

@@ -80,6 +84,9 @@ async def _run_live_impl(
8084
Args:
8185
ctx: The invocation context of the agent.
8286
"""
87+
if not self.sub_agents:
88+
return
89+
8390
# There is no way to know if it's using live during init phase so we have to init it here
8491
for sub_agent in self.sub_agents:
8592
# add tool

tests/unittests/agents/test_loop_agent.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,20 @@ async def test_run_async(request: pytest.FixtureRequest):
114114
assert events[1].content.parts[0].text == f'Hello, async {agent.name}!'
115115

116116

117+
@pytest.mark.asyncio
118+
async def test_run_async_skip_if_no_sub_agent(request: pytest.FixtureRequest):
119+
loop_agent = LoopAgent(
120+
name=f'{request.function.__name__}_test_loop_agent',
121+
max_iterations=2,
122+
sub_agents=[],
123+
)
124+
parent_ctx = await _create_parent_invocation_context(
125+
request.function.__name__, loop_agent
126+
)
127+
events = [e async for e in loop_agent.run_async(parent_ctx)]
128+
assert not events
129+
130+
117131
@pytest.mark.asyncio
118132
async def test_run_async_with_escalate_action(request: pytest.FixtureRequest):
119133
non_escalating_agent = _TestingAgent(

tests/unittests/agents/test_parallel_agent.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,19 @@ async def test_generating_one_event_per_agent_at_once(
184184
# Asserts on event are done in _TestingAgentWithMultipleEvents.
185185

186186

187+
@pytest.mark.asyncio
188+
async def test_run_async_skip_if_no_sub_agent(request: pytest.FixtureRequest):
189+
parallel_agent = ParallelAgent(
190+
name=f'{request.function.__name__}_test_parallel_agent',
191+
sub_agents=[],
192+
)
193+
parent_ctx = await _create_parent_invocation_context(
194+
request.function.__name__, parallel_agent
195+
)
196+
events = [e async for e in parallel_agent.run_async(parent_ctx)]
197+
assert not events
198+
199+
187200
class _TestingAgentWithException(_TestingAgent):
188201
"""Mock agent for testing."""
189202

tests/unittests/agents/test_sequential_agent.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,20 @@ async def test_run_async(request: pytest.FixtureRequest):
9191
assert events[1].content.parts[0].text == f'Hello, async {agent_2.name}!'
9292

9393

94+
@pytest.mark.asyncio
95+
async def test_run_async_skip_if_no_sub_agent(request: pytest.FixtureRequest):
96+
sequential_agent = SequentialAgent(
97+
name=f'{request.function.__name__}_test_agent',
98+
sub_agents=[],
99+
)
100+
parent_ctx = await _create_parent_invocation_context(
101+
request.function.__name__, sequential_agent
102+
)
103+
events = [e async for e in sequential_agent.run_async(parent_ctx)]
104+
105+
assert not events
106+
107+
94108
@pytest.mark.asyncio
95109
async def test_run_live(request: pytest.FixtureRequest):
96110
agent_1 = _TestingAgent(name=f'{request.function.__name__}_test_agent_1')

0 commit comments

Comments
 (0)