agent_tool.go
Overview
The agent_tool.go file defines the Agent Tool, a specialized tool implementation that enables an AI agent to invoke another agent as a sub-agent within a compositional workflow. This facilitates hierarchical agent delegation, allowing complex AI workflows by composing multiple agents with distinct capabilities.
The core function of this tool is to wrap a sub-agent and expose it as a callable tool with a well-defined interface, including input/output schemas. When invoked, it creates a new session context for the sub-agent, runs it via an internal runner, and returns the sub-agent's output. This file is part of the broader Agent Tools and Tooling System for modular tool-based agent extensibility.
Types and Structures
agentTool struct
type agentTool struct {
agent agent.Agent
skipSummarization bool
}
Purpose: Implements the
tool.Toolinterface by wrapping a sub-agent to enable its invocation as a tool.Fields:
agent: The sub-agent instance to invoke.skipSummarization: Configuration flag indicating whether to skip automatic summarization of the sub-agent session after execution.
Config struct
type Config struct {
SkipSummarization bool
}
Purpose: Configuration options for the
agentTool.Fields:
SkipSummarization: Iftrue, disables summarization after the sub-agent runs, allowing finer control over session event handling.
Functions and Methods
New
func New(agent agent.Agent, cfg *Config) tool.Tool
Purpose: Factory method to create a new
agentToolinstance wrapping the given sub-agent.Parameters:
agent: The sub-agent to wrap.cfg: Optional configuration; ifnil, defaults are applied (SkipSummarization=false).
Returns: An instance implementing
tool.Tool.Usage:
subAgentTool := agenttool.New(subAgent, &agenttool.Config{ SkipSummarization: true })
Name
func (t *agentTool) Name() string
Implements
tool.Tool.Name().Returns the name of the wrapped sub-agent.
Used to identify the tool in requests and invocation contexts.
Description
func (t *agentTool) Description() string
Implements
tool.Tool.Description().Returns the description of the wrapped sub-agent.
IsLongRunning
func (t *agentTool) IsLongRunning() bool
Implements
tool.Tool.IsLongRunning().Returns
false, indicating that this tool is not considered long-running by default.
Declaration
func (t *agentTool) Declaration() *genai.FunctionDeclaration
Purpose: Constructs the function declaration describing the callable interface of the sub-agent.
Behavior:
Attempts to extract the sub-agent's input schema via the internal
llminternal.Agentinterface.If no input schema is found, defaults to a generic schema expecting a
"request"string property.Builds and returns a
genai.FunctionDeclarationincluding the agent's name, description, and parameters.
Returns: A pointer to a
genai.FunctionDeclaration, describing the expected input to the sub-agent as a function schema.
Run
func (t *agentTool) Run(toolCtx tool.Context, args any) (map[string]any, error)
Purpose: Executes the wrapped sub-agent as a tool with the provided arguments.
Parameters:
toolCtx: The invocation context providing session, user, state, and action control.args: The input arguments as a genericanytype, expected to be amap[string]any.
Returns:
A map of output key-value pairs representing the sub-agent's output.
An error if invocation or validation fails.
Detailed Workflow:
Argument Validation:
Validates
argsagainst the sub-agent's input JSON schema if available.If no schema, expects a
"request"string argument.
Session Management:
Copies the current tool context state, filtering out internal keys.
Creates a new sub-agent session with the copied state.
Agent Runner Creation:
Instantiates a new
runner.Runnerconfigured with the sub-agent, in-memory services for session, artifact, and memory.
Sub-Agent Execution:
Runs the sub-agent asynchronously, streaming session events.
Collects the last LLM response event with content.
Output Processing:
Extracts and concatenates text parts from the response.
If the sub-agent declares an output schema, validates and parses the output JSON accordingly.
Otherwise, returns the raw output text under the
"result"key.
Special Behavior:
Honors the
skipSummarizationflag by settingActions().SkipSummarizationin the context.
Example Usage:
output, err := subAgentTool.Run(ctx, map[string]any{"request": "Hello"}) if err != nil { // handle error } fmt.Println(output["result"])
ProcessRequest
func (t *agentTool) ProcessRequest(ctx tool.Context, req *model.LLMRequest) error
Purpose: Adds the sub-agent's function declaration to the LLM request's toolset.
Parameters:
ctx: Current tool invocation context.req: The LLM request object to modify.
Behavior:
Ensures the tool is registered uniquely in
req.Tools.Appends the sub-agent's
FunctionDeclarationto the LLM request'sConfig.Toolslist.Ensures the request configuration is initialized if nil.
Use Case: Enables the LLM to recognize the sub-agent as a callable function during generation, facilitating function call integration.
Error Handling: Returns an error if a duplicate tool name is detected.
Important Implementation Details and Algorithms
Schema-Based Validation: Input arguments and output results are validated strictly against the sub-agent's declared JSON schemas (
InputSchemaandOutputSchema) via utility functions likeutils.ValidateMapOnSchemaandutils.ValidateOutputSchema. This ensures type safety and predictable data structures in agent composition.Isolated Sub-Agent Sessions: Each sub-agent invocation runs in its own session created dynamically with the session service (
session.InMemoryService). The parent tool context's state is copied selectively, excluding internal keys prefixed with_adk, isolating sub-agent state and preserving encapsulation.Agent Runner: The sub-agent runs within a dedicated
runner.Runnerinstance configured with in-memory artifact, memory, and session services. This decouples sub-agent execution from the main agent, allowing independent event streaming and lifecycle management.Streaming Event Consumption: The tool consumes events from the runner's asynchronous channel, capturing the last event containing LLM response content to determine the final output.
Summarization Control: The
skipSummarizationflag allows skipping automatic summarization of the sub-agent session, useful in multi-agent workflows where subsequent aggregation or handling is performed manually or by the parent agent.Fallback Input Schema: If the sub-agent does not provide an input schema, the tool uses a default schema with a single required string parameter
"request", simplifying compatibility with untyped agents.Output Parsing: When the sub-agent defines an output schema, the JSON textual output is parsed and validated, converting it into a structured map; otherwise, the output is returned as a simple map with a
"result"string.
Interactions with Other System Components
Interacts with the agent.Agent interface to wrap and invoke sub-agents.
Uses the tool.Tool interface to expose the sub-agent as a callable tool.
Utilizes the session service to create isolated sessions for sub-agent executions.
Leverages the runner to execute the sub-agent asynchronously and stream events.
Employs in-memory implementations of artifact, memory, and session services for ephemeral state during sub-agent runs.
Integrates with the LLM request lifecycle by adding function declarations for the sub-agent, enabling LLM function call support.
Coordinates with the Tooling System (80556) and Agent Tools (80578) for hierarchical agent composition.
Supports state forwarding and filtering from the parent agent context to the sub-agent, enabling contextual continuity.
Usage Example
// Create a sub-agent tool wrapping an existing agent instance.
subAgentTool := agenttool.New(mySubAgent, &agenttool.Config{
SkipSummarization: true,
})
// Add to LLM request before generation.
err := subAgentTool.ProcessRequest(toolCtx, llmRequest)
if err != nil {
// handle error
}
// Run the sub-agent tool with input arguments.
output, err := subAgentTool.Run(toolCtx, map[string]any{
"request": "Analyze this data.",
})
if err != nil {
// handle error
}
fmt.Println("Sub-agent output:", output)
Visual Diagram
classDiagram
class agentTool {
-agent: agent.Agent
-skipSummarization: bool
+Name(): string
+Description(): string
+IsLongRunning(): bool
+Declaration(): genai.FunctionDeclaration
+Run(tool.Context, any) map[string]any
+ProcessRequest(tool.Context, *model.LLMRequest) error
}
agentTool ..> agent.Agent : wraps >
agentTool ..> tool.Tool : implements >
agentTool ..> session.Service : uses >
agentTool ..> runner.Runner : uses >
agentTool ..> genai.FunctionDeclaration : produces >
References
See Tooling System for the core modular tool framework.
See Agent Tools for the concept and patterns of wrapping agents as tools.
See Agent Execution Runner for managing agent invocation lifecycles.
See Session Management for session handling and state persistence.
See LLM Integration and Agents for the interaction of agents with LLMs and tool invocation.