Skip to content

events is mixing while running single_turn agent as parallel聽#5961

Description

@maxx1958

馃敶 Required Information

Please ensure all items in this section are completed to allow for efficient
triaging. Requests without complete information may be rejected / deprioritized.
If an item is not applicable to you - please mark it as N/A

Describe the Bug:
When "single_turn" agents are executed in parallel, the context gets mixed.
Single_turn_Agent1("order 1")
Single_turn_Agent1("order 2")
Single_turn_Agent1 got
context = [
"order 1",
"order 2",
]

Single_turn_Agent2 also got
context = [
"order 1",
"order 2",
]

Steps to Reproduce:
Please provide a numbered list of steps to reproduce the behavior:

  1. Install '...'
  2. Run '....'
  3. Open '....'
  4. Provide error or stacktrace
    root_agent(
    sub_agents = [ Single_turn_Agent1 , Single_turn_Agent2 ]
    )

Asking questions that are called simultaneously

Expected Behavior:
A clear and concise description of what you expected to happen.

Single_turn_Agent1("order 1")
Single_turn_Agent1("order 2")
Single_turn_Agent1 got
context = [
"order 1",
]

Single_turn_Agent2 also got
context = [
"order 2",
]

Observed Behavior:
What actually happened? Include error messages or crash stack traces here.

Environment Details:

  • ADK Library Version (pip show google-adk):
    Version: 2.1.0

  • Desktop OS:** [e.g., macOS, Linux, Windows] : linux

  • Python Version (python -V):
    Python 3.12.3

Model Information:

  • Are you using LiteLLM: Yes
  • Which model is being used: (e.g., gemini-2.5-pro)
    bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0

馃煛 Optional Information

Providing this information greatly speeds up the resolution process.

Regression:
Did this work in a previous version of ADK? If so, which one?

Logs:
Please attach relevant logs. Wrap them in code blocks (```) or attach a
text file.

// Paste logs here

Screenshots / Video:
If applicable, add screenshots or screen recordings to help explain
your problem.

Additional Context:
Add any other context about the problem here.

@OverRide
async def run_async(
self,
*,
args: dict[str, Any],
tool_context: ToolContext,
) -> Any:
input_schema = _get_input_schema(self.agent)
if input_schema:
try:
node_input = input_schema.model_validate(args)
except Exception as e:
return f'Error validating input: {e}'
else:
node_input = args.get('request')
print(f"# name:{self.agent.name}, node_input:{node_input}")
print(f"# name:{self.agent.name}, tool_context:{tool_context.session.events}")
try:
return await tool_context.run_node(
self.agent, node_input=node_input, use_sub_branch=True
)
except Exception as e:
return f'Error running sub-agent: {e}'

Minimal Reproduction Code:
Please provide a code snippet or a link to a Gist/repo that isolates the issue.

// Code snippet here

How often has this issue occurred?:

  • Always (100%)

Activity

  1. added
    core[Component] This issue is related to the core interface and implementation
    on Jun 4, 2026
  2. added theissue type on Jun 4, 2026
  3. maxx1958 commented on Jun 4, 2026

    @maxx1958
    Author

    _SingleTurnAgentTool name:battery, node_input:get device list with battery issue

    content=Content(
    parts=[
    Part(
    text="I'll help you retrieve information about devices with security issues and battery issues."
    ),
    Part(
    function_call=FunctionCall(
    args={
    'request': 'get device list with security issues'
    },
    id='tooluse_z4B4h5OaNfK6vg7YayK12x',
    name='security'
    )
    ),
    Part(
    function_call=FunctionCall(
    args={
    'request': 'get device list with battery issues'
    },
    id='tooluse_IJXmFZ01iOnO3BLydn8wWA',
    name='battery'
    )
    ),
    ],
    role='model'
    ...
    Event(model_version=None, content=Content(
    parts=[
    Part(
    text='get device list with security issues'
    ),
    ],
    role='user'
    )
    ...
    Event(model_version=None, content=Content(
    parts=[
    Part(
    text='get device list with battery issues'
    ),
    ],

    _SingleTurnAgentTool name:security, node_input:get device list with security vulnerabilities and security issues

    content=Content(
    parts=[
    Part(
    text="I'll help you retrieve information about devices with security issues and battery issues."
    ),
    Part(
    function_call=FunctionCall(
    args={
    'request': 'get device list with security issues'
    },
    id='tooluse_z4B4h5OaNfK6vg7YayK12x',
    name='security'
    )
    ),
    Part(
    function_call=FunctionCall(
    args={
    'request': 'get device list with battery issues'
    },
    id='tooluse_IJXmFZ01iOnO3BLydn8wWA',
    name='battery'
    )
    ),
    ],
    role='model'
    ...
    Event(model_version=None, content=Content(
    parts=[
    Part(
    text='get device list with security issues'
    ),
    ],
    role='user'
    )
    ...
    Event(model_version=None, content=Content(
    parts=[
    Part(
    text='get device list with battery issues'
    ),
    ],

  4. llalitkumarrr commented on Jun 4, 2026

    @llalitkumarrr
    Collaborator

    Hello @maxx1958 ,

    Could you please try parallel worker sample and check if you observe similar behavior here as well? Kindly try this and share your observations with us.

    Also we observed that you are using Litellm with Gemini models, we highly recommend using Gemini model class with gemini models.

  5. added
    request clarification[Status] The maintainer need clarification or more information from the author
    on Jun 4, 2026
  6. maxx1958 commented on Jun 4, 2026

    @maxx1958
    Author

    @llalitkumarrr
    This is an issue that occurs in the agent's mode=single_turn, not the graph workflow.

  7. maxx1958 commented on Jun 5, 2026

    @maxx1958
    Author

    I discovered that the "_get_current_turn_contents" function saves the last conversation.

    When two requests occur simultaneously,

    tool_call single_turn_agent1 order1

    tool_call single_turn_agent2 order2

    is executed as the parent agent's llm output,
    which generates
    Event("order1"),

    Event("order2"),

    and these events are stored as follows.

    In the code above, ,

    Event("order2"), is unconditionally retrieved,

    and Single_turn_agent1 also attempts to execute order2.

  8. maxx1958 commented on Jun 5, 2026

    @maxx1958
    Author
    
    def _get_current_turn_contents(
        current_branch: Optional[str],
        events: list[Event],
        agent_name: str = '',
        *,
        preserve_function_call_ids: bool = False,
        is_single_turn: bool = False,
        isolation_scope: Optional[str] = None,
        user_content: Optional[types.Content] = None,
    ) -> list[types.Content]:
      """Get contents for the current turn only (no conversation history).
    
      When include_contents='none', we want to include:
      - The current user input
      - Tool calls and responses from the current turn
      But exclude conversation history from previous turns.
    
      In multi-agent scenarios, the "current turn" for an agent starts from an
      actual user or from another agent.
    
      Args:
        current_branch: The current branch of the agent.
        events: A list of all session events.
        agent_name: The name of the agent.
        preserve_function_call_ids: Whether to preserve function call ids.
    
      Returns:
        A list of contents for the current turn only, preserving context needed
        for proper tool execution while excluding conversation history.
      """
      # Find the latest event that starts the current turn and process from there
      for i in range(len(events) - 1, -1, -1):               <=========== here
        event = events[i]
        if _should_include_event_in_context(
            current_branch, event, isolation_scope=isolation_scope
        ) and (event.author == 'user' or _is_other_agent_reply(agent_name, event)):          <===== here
          return _get_contents(
              current_branch,
              events[i:],
              agent_name,
              preserve_function_call_ids=preserve_function_call_ids,
              isolation_scope=isolation_scope,
              is_single_turn=is_single_turn,
              user_content=user_content,
          )
    
      return []
    
  9. added
    workflow[Component] This issue is related to ADKworkflow
    on Jun 7, 2026
  10. llalitkumarrr commented on Jun 23, 2026

    @llalitkumarrr
    Collaborator

    Hello @maxx1958 ,

    Could you please share a minimal reproducible code to help analyze this issue in more detail?

  11. adk-bot commented on Jul 1, 2026

    @adk-bot
    Collaborator

    This issue has been automatically marked as stale because it has not had recent activity for 7 days after a maintainer requested clarification. It will be closed if no further activity occurs within 7 days.

  12. added
    stale[Status] Issues which have been marked inactive since there is no user response
    on Jul 1, 2026
  13. adk-bot commented on Jul 9, 2026

    @adk-bot
    Collaborator

    This has been automatically closed because it has been marked as stale for over 7 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

core[Component] This issue is related to the core interface and implementationrequest clarification[Status] The maintainer need clarification or more information from the authorstale[Status] Issues which have been marked inactive since there is no user responseworkflow[Component] This issue is related to ADKworkflow

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions