Skip to content

Commit f39d75b

Browse files
google-genai-botcopybara-github
authored andcommitted
fix(adk): propagate isolation_scope to prevent history filtering loops
PiperOrigin-RevId: 933314484
1 parent 69ecf07 commit f39d75b

4 files changed

Lines changed: 67 additions & 0 deletions

File tree

src/google/adk/agents/context.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ def get_invocation_context(self) -> InvocationContext:
403403
ctx_with_proxy = ctx.model_copy(
404404
update={
405405
'session': self.session,
406+
'isolation_scope': self.isolation_scope,
406407
}
407408
)
408409
return ctx_with_proxy

src/google/adk/workflow/_llm_agent_wrapper.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,14 @@ def prepare_llm_agent_context(agent: Any, ctx: Context) -> Context:
207207

208208
ic = ctx._invocation_context.model_copy()
209209
ic._event_queue = ctx._invocation_context._event_queue
210+
ic.isolation_scope = ctx.isolation_scope
210211
agent_ctx = Context(
211212
invocation_context=ic,
212213
node_path=ctx.node_path,
213214
run_id=ctx.run_id,
214215
resume_inputs=ctx.resume_inputs,
215216
)
217+
agent_ctx.isolation_scope = ctx.isolation_scope
216218

217219
ic.session = ic.session.model_copy(deep=False)
218220
return agent_ctx

tests/unittests/agents/test_context.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,3 +647,29 @@ def test_derive_scheduler_with_parent_no_scheduler(self):
647647

648648
scheduler = _derive_scheduler(mock_parent)
649649
assert isinstance(scheduler, DynamicNodeScheduler)
650+
651+
652+
class TestContextGetInvocationContext:
653+
"""Test get_invocation_context method in Context."""
654+
655+
def test_get_invocation_context_propagates_isolation_scope(
656+
self, mock_invocation_context
657+
):
658+
"""Test that get_invocation_context propagates isolation_scope to the copy."""
659+
context = Context(mock_invocation_context)
660+
context.isolation_scope = "test-isolation-scope"
661+
662+
# Mock model_copy to return a mock copy
663+
mock_copy = MagicMock()
664+
mock_invocation_context.model_copy.return_value = mock_copy
665+
666+
result = context.get_invocation_context()
667+
668+
# Verify model_copy was called with correct update dict
669+
mock_invocation_context.model_copy.assert_called_once_with(
670+
update={
671+
"session": context.session,
672+
"isolation_scope": "test-isolation-scope",
673+
}
674+
)
675+
assert result is mock_copy

tests/unittests/workflow/test_llm_agent_as_node.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,44 @@ async def fake_run(invocation_context):
500500
assert captured_branches[0] is None
501501

502502

503+
@pytest.mark.asyncio
504+
async def test_single_turn_propagates_isolation_scope(
505+
request: pytest.FixtureRequest,
506+
):
507+
"""Single-turn workflow node propagates isolation_scope to the agent."""
508+
agent = _make_agent(mode='single_turn')
509+
wrapper = build_node(agent)
510+
captured_isolation_scopes = []
511+
512+
async def fake_run_async(invocation_context):
513+
captured_isolation_scopes.append(invocation_context.isolation_scope)
514+
yield Event(
515+
invocation_id='inv',
516+
author=wrapper.name,
517+
content=types.Content(parts=[types.Part(text='ok')]),
518+
)
519+
520+
object.__setattr__(wrapper, 'run_async', fake_run_async)
521+
522+
# Use the helper to create a real InvocationContext
523+
ic = await create_parent_invocation_context(
524+
request.function.__name__, wrapper
525+
)
526+
527+
# Create the parent context with isolation_scope
528+
ctx = Context(invocation_context=ic)
529+
ctx.isolation_scope = 'test-scope-123'
530+
531+
# Run the node
532+
events = [
533+
event async for event in wrapper._run_impl(ctx=ctx, node_input='hi')
534+
]
535+
536+
assert len(events) == 1
537+
assert events[0].content.parts[0].text == 'ok'
538+
assert captured_isolation_scopes == ['test-scope-123']
539+
540+
503541
@pytest.mark.xfail(
504542
strict=True,
505543
reason=(

0 commit comments

Comments
 (0)