Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions docs/agents/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ details on what you must install and configure before you can run agents with
the Agent Config files.

!!! note
The Agent Config feature currently only supports Gemini models. For more
information about additional; functional restrictions, see
[Known limitations](#known-limitations).
The `model:` key of an Agent Config takes a Gemini model name. To use
another model, construct a `BaseLlm` instance in Python and reference it
from the `model_code:` key. For more information about additional;
functional restrictions, see [Known limitations](#known-limitations).

To set up ADK for use with Agent Config:

Expand Down Expand Up @@ -148,6 +149,10 @@ For more information about the ADK command line options, see the

You can also bypass the CLI and dynamically load and execute a configuration-based agent directly in your code. The utility loads the configuration and instantiates the proper agent class (such as `LlmAgent`) transparently as a `BaseAgent` subclass.

!!! note
In Python, `config_agent_utils.from_config` is deprecated: calling it emits
a `DeprecationWarning`, and it will be removed in a future version.

=== "Python"

```python
Expand Down Expand Up @@ -275,8 +280,15 @@ deployment guides.
The Agent Config feature is experimental and includes the following
limitations:

- **Model support:** Only Gemini models are currently supported.
Integration with third-party models is in progress.
- **Model support:** The `model:` key only accepts a Gemini model name. To use
another model, such as `LiteLlm`, construct it in Python and reference it
from the `model_code:` key, which takes a mapping whose `name:` sub-key is
the fully qualified name of the `BaseLlm` instance:

model_code:
name: my_library.clients.my_litellm

The `model:` and `model_code:` keys cannot both be set.
- **Programming language:** The Agent Config feature currently supports
Python and Java code for tools and other functionality requiring programming code.
- **ADK Tool support:** The following ADK tools are supported by the Agent
Expand Down
33 changes: 27 additions & 6 deletions docs/agents/custom-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ The core of any custom agent is the method where you define its unique asynchron
* **Signature:** `async def _run_async_impl(self, ctx: InvocationContext) -> AsyncGenerator[Event, None]:`
* **Asynchronous Generator:** It must be an `async def` function and return an `AsyncGenerator`. This allows it to `yield` events produced by sub-agents or its own logic back to the runner.
* **`ctx` (InvocationContext):** Provides access to crucial runtime information, most importantly `ctx.session.state`, which is the primary way to share data between steps orchestrated by your custom agent.
* **Live (audio/video) runs:** The `_run_async_impl` method only covers text-based runs. To support `run_live()`, also override `_run_live_impl`, which has the same signature. Without that override, live runs raise `NotImplementedError`.

=== "TypeScript"

Expand Down Expand Up @@ -246,7 +247,7 @@ The core of any custom agent is the method where you define its unique asynchron

Typically, a custom agent orchestrates other agents (like `LlmAgent`, `LoopAgent`, etc.).

* **Initialization:** You usually pass instances of these sub-agents into your custom agent's constructor and store them as instance fields/attributes (e.g., `this.story_generator = story_generator_instance` or `self.story_generator = story_generator_instance`). This makes them accessible within the custom agent's core asynchronous execution logic (such as: `_run_async_impl` method).
* **Initialization:** You usually pass instances of these sub-agents into your custom agent's constructor and store them as instance fields/attributes (e.g., `this.story_generator = story_generator_instance` or `self.story_generator = story_generator_instance`). This makes them accessible within the custom agent's core asynchronous execution logic (such as: `_run_async_impl` method). In Python, `BaseAgent` is a Pydantic model configured with `extra='forbid'`, so declare each sub-agent you keep as an annotated class-level field (e.g., `story_generator: LlmAgent`) and pass it to `super().__init__(...)`. Assigning an undeclared attribute in `__init__` raises a `ValueError`.
* **Sub Agents List:** When initializing the `BaseAgent` using it's `super()` constructor, you should pass a `sub agents` list. This list tells the ADK framework about the agents that are part of this custom agent's immediate hierarchy. It's important for framework features like lifecycle management, introspection, and potentially future routing capabilities, even if your core execution logic (`_run_async_impl`) calls the agents directly via `self.xxx_agent`. Include the agents that your custom logic directly invokes at the top level.
* **State:** As mentioned, `ctx.session.state` is the standard way sub-agents (especially `LlmAgent`s using `output key`) communicate results back to the orchestrator and how the orchestrator passes necessary inputs down.

Expand Down Expand Up @@ -276,12 +277,25 @@ The foundation for structuring multi-agent systems is the parent-child relations

```python
# Conceptual Example: Defining Hierarchy
from typing import AsyncGenerator

from google.adk.agents import LlmAgent, BaseAgent
from google.adk.agents.invocation_context import InvocationContext
from google.adk.events import Event


# A custom non-LLM agent must implement _run_async_impl; instantiating
# BaseAgent directly raises NotImplementedError when it runs.
class TaskExecutor(BaseAgent):
async def _run_async_impl(
self, ctx: InvocationContext
) -> AsyncGenerator[Event, None]:
yield Event(author=self.name)


# Define individual agents
greeter = LlmAgent(name="Greeter", model="gemini-flash-latest")
task_doer = BaseAgent(name="TaskExecutor") # Custom non-LLM agent
task_doer = TaskExecutor(name="TaskExecutor") # Custom non-LLM agent


# Create parent agent and assign children via sub_agents
Expand Down Expand Up @@ -393,6 +407,12 @@ The foundation for structuring multi-agent systems is the parent-child relations

ADK includes specialized agents derived from `BaseAgent` that don't perform tasks themselves but orchestrate the execution flow of their `sub_agents`.

!!! note "Deprecated in Python"

In Python, `SequentialAgent`, `ParallelAgent`, and `LoopAgent` are
deprecated in favor of `Workflow`: constructing one emits a
`DeprecationWarning`, and the classes will be removed in a future release.

* **[`SequentialAgent`](workflow-agents/sequential-agents.md):** Executes its `sub_agents` one after another in the order they are listed.
* **Context:** Passes the *same* [`InvocationContext`](../runtime/index.md) sequentially, allowing agents to easily pass results via shared state.

Expand Down Expand Up @@ -662,7 +682,7 @@ Agents within a system often need to exchange data or trigger actions in one ano

The most fundamental way for agents operating within the same invocation (and thus sharing the same [`Session`](/sessions/session/) object via the `InvocationContext`) to communicate passively.

* **Mechanism:** One agent (or its tool/callback) writes a value (`context.state['data_key'] = processed_data`), and a subsequent agent reads it (`data = context.state.get('data_key')`). State changes are tracked via [`CallbackContext`](../callbacks/index.md).
* **Mechanism:** One agent (or its tool/callback) writes a value (`context.state['data_key'] = processed_data`), and a subsequent agent reads it (`data = context.state.get('data_key')`). In Python, [`CallbackContext`](../callbacks/index.md) and `ToolContext` are the same delta-aware context class, and every write to `context.state` is recorded as a `state_delta` on the event the agent emits.
* **Convenience:** The `output_key` property on [`LlmAgent`](llm-agents.md) automatically saves the agent's final response text (or structured output) to the specified state key.
* **Nature:** Asynchronous, passive communication. Ideal for pipelines orchestrated by `SequentialAgent` or passing data across `LoopAgent` iterations.
* **See Also:** [State Management](../sessions/state.md)
Expand Down Expand Up @@ -866,8 +886,9 @@ Allows an [`LlmAgent`](llm-agents.md) to treat another `BaseAgent` instance as a
```python
# Conceptual Setup: Agent as a Tool
from google.adk.agents import LlmAgent, BaseAgent
from google.adk.events import Event
from google.adk.tools import agent_tool
from pydantic import BaseModel
from google.genai import types


# Define a target agent (could be LlmAgent or custom BaseAgent)
Expand All @@ -879,7 +900,7 @@ Allows an [`LlmAgent`](llm-agents.md) to treat another `BaseAgent` instance as a
prompt = ctx.session.state.get("image_prompt", "default prompt")
# ... generate image bytes ...
image_bytes = b"..."
yield Event(author=self.name, content=types.Content(parts=[types.Part.from_bytes(image_bytes, "image/png")]))
yield Event(author=self.name, content=types.Content(parts=[types.Part.from_bytes(data=image_bytes, mime_type="image/png")]))


image_agent = ImageGeneratorAgent()
Expand Down Expand Up @@ -1154,7 +1175,7 @@ These are standard `LlmAgent` definitions, responsible for specific tasks. Their
=== "Python"

```python
GEMINI_2_FLASH = "gemini-flash-latest" # Define model constant
GEMINI_2_FLASH = "gemini-2.0-flash" # Define model constant
--8<-- "examples/python/snippets/agents/custom-agent/storyflow_agent.py:llmagents"
```

Expand Down
Loading
Loading