Back to Adk Python

LlmAgent Single-Turn Mode

docs/guides/agents/llm_agent/single_turn.md

2.3.06.7 KB
Original Source

LlmAgent Single-Turn Mode

This guide explains the behavior of LlmAgent in single_turn mode, both when executed as a workflow node and when defined as a sub-agent in a multi-agent hierarchy. It covers default stateless execution, delegation mechanics, and how to configure history visibility.


Introduction

In ADK, mode="single_turn" is designed for isolated, stateless tasks where the agent only needs to process the immediate input without accumulating or referencing prior conversation history.

Depending on how the agent is deployed—either as a step in a Workflow or as a sub_agent of another LLM agent—its behavior and interaction patterns differ.


1. Single-Turn Mode as a Workflow Node

When building a Workflow graph, any LlmAgent added to the graph defaults to mode="single_turn" (unless explicitly configured otherwise).

Behavior

  • Stateless by Default: The node does not see previous conversation turns in the workflow session. Its history visibility (include_contents) automatically defaults to 'none'.
  • Isolated Execution: Each execution of the node is independent.

Example

python
from google.adk.agents import LlmAgent
from google.adk.workflow import Workflow, build_node

# Defaults to mode="single_turn" when run as a node
writer_agent = LlmAgent(
    name="writer",
    instruction="Write a short story about the input topic."
)

writer_node = build_node(writer_agent)

wf = Workflow(
    name="story_generator",
    edges=[
        ("START", writer_node),
        (writer_node, "END")
    ]
)

2. Single-Turn Mode as a Sub-Agent

You can define hierarchical agent structures by assigning agents to the sub_agents list of a parent LlmAgent.

Behavior

  • Exposed as a Tool: A single_turn sub-agent is not a transfer target. The parent agent cannot hand over control of the conversation to it. Instead, the framework automatically exposes the sub-agent to the parent as a Tool (function).
  • Functional Delegation: The parent agent calls the sub-agent like a function, passing arguments. The sub-agent executes, returns its output to the parent, and the parent continues the conversation.
  • Isolated Sub-Branch: When the parent calls the sub-agent tool, the framework executes the sub-agent in an isolated sub-branch (derived from the parent's branch, e.g., parent_branch.sub_agent@run_id).
  • Stateless by Default: Like the workflow node, a single_turn sub-agent defaults to include_contents="none" and only sees the inputs passed to it in the tool call.

Example

python
from google.adk.agents import LlmAgent

# Define a specialized single-turn sub-agent
translator_agent = LlmAgent(
    name="translator",
    instruction="Translate the input text to Spanish.",
    mode="single_turn"  # Must be explicit if not auto-wrapped in workflow
)

# Define the parent agent and assign the sub-agent
bilingual_writer = LlmAgent(
    name="bilingual_writer",
    instruction="Write a poem about the topic, then use the translator tool to translate it.",
    sub_agents=[translator_agent] # Exposes 'translator' as a tool to bilingual_writer
)

How Context Isolation Works

ADK manages history visibility using branches and the include_contents configuration:

  1. Branch Hierarchy: When a sub-agent runs, it executes in a sub-branch (e.g., main.translator@1).
    • A sub-branch is allowed to read events from its parent branch (one-way visibility).
    • The parent branch cannot read events from the sub-branch (protecting the parent from sub-agent internal reasoning chatter).
  2. History Filtering:
    • include_contents="none" (Default): The agent bypasses history loading entirely. It only sees the immediate input (the workflow node input or the tool call arguments).
    • include_contents="default": The agent loads conversation history. Because of the branch hierarchy, a sub-agent with this setting can see the parent agent's conversation history leading up to the tool call.

Configuration Options

ParameterTypeDefaultDescription
modeLiteral['single_turn', 'task', 'chat']'single_turn' (when run as node)The execution mode. single_turn isolates execution; task supports delegation; chat preserves full history.
include_contentsLiteral['default', 'none']'none' (for single_turn if unset)Controls history visibility. For single_turn mode, it defaults to 'none' (stateless), but can be explicitly set to 'default' to make the agent context-aware.

Advanced Applications: Context-Aware Execution

If you want a single-turn agent (node or sub-agent) to have access to the conversation history, you must explicitly set include_contents="default".

Context-Aware Sub-Agent Example

In this setup, the verifier sub-agent needs to see the history of the conversation to verify the parent's draft against previous user constraints:

python
verifier_agent = LlmAgent(
    name="verifier",
    instruction="Verify that the draft meets all constraints discussed in the chat.",
    mode="single_turn",
    include_contents="default"  # Allows the sub-agent to see the parent's conversation history
)

editor_agent = LlmAgent(
    name="editor",
    instruction="Discuss the draft with the user and use verifier to check constraints.",
    sub_agents=[verifier_agent]
)

Limitations

  • Difference from Standalone Behavior: A standalone LlmAgent defaults to include_contents="default". When used in a workflow or as a sub-agent, it defaults to include_contents="none".
  • No Direct Transfer: You cannot use transfer_to_agent to target a single_turn agent. They must be invoked via tool calls.