runner.go
Overview
This file implements the Runner, a core component responsible for managing the execution lifecycle of AI agents within user sessions. The Runner coordinates user input handling, session state updates, agent selection, event streaming, and integration with artifact and memory services. It facilitates multi-agent conversations by selecting the appropriate agent from an agent hierarchy based on session history and transfer policies.
The Runner acts as the execution runtime for ADK agents, bridging user messages to agent invocations, and maintaining session consistency by appending generated events and managing artifacts. It supports streaming outputs and handles saving inline input blobs as artifacts prior to agent execution.
Main Types and Functions
Config
type Config struct {
AppName string
Agent agent.Agent
SessionService session.Service
ArtifactService artifact.Service // optional
MemoryService memory.Service // optional
}
Purpose: Configuration structure used to instantiate a
Runner.Fields:
AppName: Name of the application.Agent: The root agent that initiates execution (required).SessionService: Service to manage sessions (required).ArtifactService: Optional service for artifact storage.MemoryService: Optional service for agent memory persistence.
New
func New(cfg Config) (*Runner, error)
Purpose: Creates and initializes a new
Runner.Parameters:
cfg: Configuration object containing root agent and services.
Returns:
A pointer to a
Runnerinstance or an error if configuration is invalid.
Behavior:
Validates presence of required parameters (
AgentandSessionService).Builds a parent map of agents for hierarchical traversal.
Initializes internal references to services and agent hierarchy.
Usage Example:
runner, err := runner.New(runner.Config{ AppName: "myApp", Agent: rootAgent, SessionService: sessionSvc, ArtifactService: artifactSvc, // optional MemoryService: memorySvc, // optional }) if err != nil { log.Fatal(err) }
Runner
type Runner struct {
appName string
rootAgent agent.Agent
sessionService session.Service
artifactService artifact.Service
memoryService memory.Service
parents parentmap.Map
}
Purpose: Manages agent execution, session event processing, artifact and memory integration.
Fields:
appName: Application name for session scoping.rootAgent: Root agent of the agent tree.sessionService: Session management interface.artifactService: Optional artifact storage interface.memoryService: Optional memory storage interface.parents: Map of agent parent relationships for hierarchy traversal.
Run
func (r *Runner) Run(ctx context.Context, userID, sessionID string, msg *genai.Content, cfg agent.RunConfig) iter.Seq2[*session.Event, error]
Purpose: Executes the agent for a given user input and streams back session events.
Parameters:
ctx: Context for cancellation and deadlines.userID: User identifier.sessionID: Session identifier.msg: User input message content.cfg: Agent run configuration options.
Returns:
A generator function yielding pairs of session events and errors.
Behavior:
Retrieves the session via
sessionService.Get.Determines the appropriate agent to run using
findAgentToRun.Sets up invocation context embedding artifacts, memory, session, user content, and run config.
Optionally saves input blobs as artifacts and appends the user message event.
Runs the selected agent, streaming generated events.
Appends non-partial events to the session.
Yields events/errors to the caller for incremental processing.
Notes:
Streaming mode and other run configurations are applied via context.
Partial events (e.g., streaming LLM output) are not persisted until complete.
Usage Example:
events := runner.Run(ctx, "user123", "sess456", userMsgContent, runConfig) for event, err := range events { if err != nil { log.Println("Error:", err) break } fmt.Println("Event:", event) }
appendMessageToSession
func (r *Runner) appendMessageToSession(ctx agent.InvocationContext, storedSession session.Session, msg *genai.Content, saveInputBlobsAsArtifacts bool) error
Purpose: Appends a user message as a new event to the session, optionally saving inline blobs as artifacts.
Parameters:
ctx: Agent invocation context providing artifact and session services.storedSession: The session object to append to.msg: User message content to save.saveInputBlobsAsArtifacts: Flag to enable saving inline blobs as artifacts.
Returns:
Error if artifact saving or session appending fails, nil otherwise.
Behavior:
If enabled, scans message parts for inline blobs (
InlineData).Saves each blob to artifact service with a unique filename.
Replaces original blob-containing part with a textual placeholder.
Creates a new session event authored by "user" with the modified message.
Appends event to session via
sessionService.
Example:
If a user sends a file inline, it is saved as an artifact named likeartifact_<invocation_id>0and the message part is replaced with "Uploaded file: artifact_0. It has been saved to the artifacts."
findAgentToRun
func (r *Runner) findAgentToRun(session session.Session) (agent.Agent, error)
Purpose: Determines which agent should handle the current user input based on session history.
Parameters:
session: The current session containing event history.
Returns:
The selected
agent.Agentto run.Error if any issues occur (though usually nil).
Behavior:
Iterates events in reverse chronological order.
Skips user-authored events.
For agent-authored events, attempts to find the corresponding sub-agent by name.
Checks if the agent and its parents allow transfer via
isTransferableAcrossAgentTree.Returns the first transferable agent found.
Falls back to the root agent if none found.
Usage: Supports multi-agent workflows by resuming conversations with the last active sub-agent.
isTransferableAcrossAgentTree
func (r *Runner) isTransferableAcrossAgentTree(agentToRun agent.Agent) bool
Purpose: Checks if the specified agent and its parent chain allow transfer of control upward in the agent hierarchy.
Parameters:
agentToRun: Candidate agent for transfer eligibility.
Returns:
trueif transfer is allowed (no agent in chain disallows it).falseotherwise.
Behavior:
Walks up the parent chain using
r.parents.For each agent, checks if it implements the internal
llminternal.Agentinterface.Examines
DisallowTransferToParentflag; if set, returns false.If no disallow flags found, returns true.
Significance: Prevents unauthorized or disallowed agent switches in conversations.
findAgent (helper function)
func findAgent(curAgent agent.Agent, targetName string) agent.Agent
Purpose: Recursively searches the agent tree to find an agent by name.
Parameters:
curAgent: Current agent node in recursion.targetName: Name of the agent to find.
Returns:
The located agent or nil if not found.
Behavior:
If
curAgentis nil or matchestargetName, returns it.Otherwise, recursively searches sub-agents.
Usage: Used internally by
findAgentToRunto map event authorship to agents.
Implementation Details and Algorithms
Agent Tree Parent Map:
On initialization, a parent map is constructed for the entire agent tree, allowing upward traversal from any agent to its parents. This is critical for transfer permission checks.Session Event Iteration:
Agent selection scans events backward to find the last non-user event authored by an agent, enabling resumption of conversations where agents left off.Artifact Saving:
Inline blob data in user messages is externalized into artifacts to avoid bloating session storage. The message parts containing blobs are replaced with textual placeholders referencing the saved artifact.Invocation Context Assembly:
A rich context encapsulating artifacts, memory, session state, user content, and run configurations is built and passed to the agent'sRunmethod, supporting extensible agent execution environments.Streaming Event Yielding:
TheRunmethod returns a generator streaming events and errors, allowing the client to process output incrementally, supporting real-time or batch modes.
Interactions with Other Components
Session Service:
Used to retrieve session state, append user and agent events, and maintain conversation history.Artifact Service:
Optionally used to save input blobs as artifacts and provide artifact access during agent execution.Memory Service:
Optionally used to provide persistent or contextual memory to agents across sessions.Agent Tree and Parent Map:
Maintains hierarchical agent relationships to support multi-agent workflows and transfer logic.Invocation Context:
Integrates with the invocation context system (Agent Invocation Context) to provide runtime dependencies to agents.
Visual Diagram of Runner Structure and Workflow
flowchart TD
Config[Config]
New["New(cfg Config)"]
Runner[Runner]
Run["Run(ctx, userID, sessionID, msg, cfg)"]
GetSession[sessionService.Get]
FindAgent[findAgentToRun]
SetupCtx[Setup InvocationContext]
AppendMsg[appendMessageToSession]
AgentRun[agent.Run]
YieldEvents[Yield Events]
AppendEvent[sessionService.AppendEvent]
ArtifactSave[Save Input Blobs as Artifacts]
TransferCheck[isTransferableAcrossAgentTree]
Config --> New --> Runner
Runner --> Run
Run --> GetSession
Run --> FindAgent
Run --> SetupCtx
Run --> AppendMsg
AppendMsg --> ArtifactSave
Run --> AgentRun
AgentRun --> YieldEvents
YieldEvents --> AppendEvent
FindAgent --> TransferCheck
This flowchart shows how the runner is created with configuration, runs agents by retrieving sessions, selecting agents based on session events and transfer rules, prepares context including artifact saving, invokes the agent, streams and appends events.
References to Related Topics
The agent invocation context construction and usage relate to Agent Invocation Context.
The selection of agents by traversing the agent hierarchy aligns with Agent Selection Logic.
The artifact saving functionality is connected to Input Blob Artifact Saving and Artifact Management.
The overall coordination of agent runs is detailed in Agent Execution Runner.
The hierarchical agent relationships and transfer policies derive from the AI Agent Framework.
Streaming event handling and lifecycle callbacks relate to Agent Lifecycle and Callbacks.
This documentation describes the structure, purpose, and detailed operation of the runner.go file, which is central to orchestrating agent executions within user sessions, handling inputs, outputs, and multi-agent conversation flows.