LLM Integration and Agents
Overview
The LLM Integration and Agents module provides specialized AI agents designed to interact seamlessly with large language models (LLMs). These agents serve as intelligent intermediaries that encapsulate the logic to communicate with LLM backends, manage invocation contexts, orchestrate tool usage, process instructions, and handle callbacks. This module solves the problem of integrating complex LLM interactions into an extensible agent framework that supports dynamic instruction injection, tool invocation, sub-agent delegation, and rich lifecycle hooks.
By abstracting LLM communication and agent behavior into configurable components, this module enables the creation of AI agents that can perform varied tasks such as answering queries, invoking external tools, maintaining state, and transferring control to sub-agents, all driven by the capabilities of underlying LLMs like Google's Gemini models.
Core Concepts
LLMAgent
The centerpiece of this module is the LLMAgent, a concrete implementation of the generic agent.Agent interface, which integrates an LLM model with a set of tools, instructions, and callback mechanisms.
Configurable Model: The agent is constructed with a pluggable
model.LLMimplementation representing the LLM backend. This allows it to send requests and receive responses from any supported LLM provider.Instruction Handling: The agent can be configured with static or dynamic instructions (prompts) guiding the LLM's behavior. These instructions can include runtime placeholders injected with session state or artifact data.
Tools and Toolsets: The agent supports invoking external tools that complement the LLM's reasoning, such as function calls or artifact loading.
Callbacks: It supports lifecycle callbacks before and after the LLM call, as well as before and after tool execution, enabling logging, caching, error handling, or result post-processing.
Agent Hierarchy: Supports sub-agents allowing complex delegation and transfer of control between agents.
Session Integration: The agent interacts closely with the session and state management system to maintain conversation history, state deltas, and output persistence.
Instruction Injection
Instructions given to the LLM can be dynamically generated or templated. This module supports:
Static instructions with placeholders that are resolved at runtime using session variables or artifact contents.
Dynamic instructions via
InstructionProviderfunctions that build instructions based on the current invocation context.Support for a Global Instruction that applies across the entire agent tree to ensure consistent agent personality or behavior.
This flexible instruction handling allows agents to adapt their prompts dynamically based on user context or session state.
Callbacks and Hooks
The agent defines four main callback types to hook into the invocation lifecycle:
BeforeAgentCallbacks: Run before the agent begins processing a request.
AfterAgentCallbacks: Run after the agent completes its processing.
BeforeModelCallbacks: Run before the LLM request is sent; can modify or short-circuit the request.
AfterModelCallbacks: Run after the LLM response is received; can modify or replace the response.
BeforeToolCallbacks: Run before a tool is invoked; can alter arguments or short-circuit the tool call.
AfterToolCallbacks: Run after a tool invocation; can modify the tool's result or handle errors.
These callbacks provide extensibility points for logging, caching, auditing, validation, error handling, and result enhancement.
How It Works
Agent Construction
Agents are instantiated via the constructor llmagent.New(cfg Config). The configuration includes the agent name, description, LLM model, instructions, tools, and callbacks.
During construction:
The agent compiles lists of callbacks wrapping them into internal types.
It initializes the internal state with provided configuration such as toolsets, instruction providers, and schemas.
It creates a base agent (
agent.New) with the configured run function (a.run).
Invocation Flow
When the agent is invoked via its run method, it performs the following core steps:
Invocation Context Setup: It wraps the invocation context with internal types, attaching session, artifacts, memory, and other context data.
Flow Execution: It creates an
llminternal.Flowobject that orchestrates the interaction with the LLM and tools, configured with:The LLM model.
Request and response processors.
The before/after model and tool callbacks.
Running the Flow: It runs the flow as a generator yielding
session.Eventobjects representing LLM responses, tool calls, or other agent events.Output State Saving: As events are produced, the agent conditionally saves output text to the session state if configured (
OutputKey).
Tool Execution
The LLM-generated content may include function calls to tools. When a tool call is detected:
The agent invokes the
BeforeToolCallbacksin order. If any callback returns a non-nil response or error, the actual tool call is skipped.If not short-circuited, the tool's
Runmethod is called with the given arguments.After execution, the
AfterToolCallbacksare invoked with the result or error, allowing modification of the tool output.The final tool result or error is returned to the LLM flow for further processing.
Agent Transfer
Agents can delegate control to sub-agents by issuing special function calls (transfer_to_agent). This enables hierarchical and cooperative agent compositions, where complex tasks are routed dynamically.
Output Persistence
If the agent has an OutputKey configured, it extracts the text content from the final LLM response event and saves it to the session state under that key. This allows subsequent agents or tools to reference prior outputs.
Interaction with Other Modules
Agent Framework: The LLMAgent extends the core agent interfaces and lifecycle defined in the
[AI Agent Framework](None - AI Agent Framework).Session Management: It reads from and writes to session state via the invocation context, interacting with the
[Session Management](None - Session Management)module to persist conversation history and state.Tools: The agent integrates with the
[Tooling System](None - Tooling System)by invoking tools during LLM function calls.Instruction Injection: The instructions used by the agent are processed and injected dynamically using the
[Instruction Template Processing](None - Instruction Template Processing)utilities.Telemetry and Observability: Callback hooks allow integration with
[Telemetry and Observability](None - Telemetry and Observability)for tracing and metrics.Agent Execution Runner: Agents are executed within sessions by the
[Agent Execution Runner](None - Agent Execution Runner), which handles session event appending and state updates.
Important Design Patterns and Approaches
Callback Chains: The use of ordered callback chains before and after model and tool invocations enables flexible, composable interception and extension points without modifying core logic.
Event Streaming: The agent emits a stream of session events representing partial and full responses, enabling real-time interaction models such as streaming or SSE.
Hierarchical Agents: Sub-agent trees allow complex workflows to be decomposed into smaller, specialized agents that can be dynamically invoked or delegated to.
Instruction Providers: Dynamic instruction providers decouple prompt generation from static configuration, enabling runtime customization.
Stateful Output Capture: The agent can capture and store its output in session state for later retrieval or cross-agent communication.
Key Code References and Illustrations
Agent Construction and Configuration
func New(cfg Config) (agent.Agent, error) {
// Wrap callbacks into internal types
// Initialize llmAgent with model, tools, instruction, callbacks
// Create base agent with agent.New, setting run function
// Return the constructed LLMAgent
}
The constructor accepts a rich configuration structure (Config) that includes agent naming, description, sub-agents, LLM model, instructions, tools, schemas, and callbacks.
Agent Run Method
func (a *llmAgent) run(ctx agent.InvocationContext) iter.Seq2[*session.Event, error] {
// Wrap context with internal invocation context
// Create llminternal.Flow with model, callbacks, processors
// Execute flow.Run to generate event stream
// Save output to state if configured
// Yield events to caller
}
This method encapsulates the core flow of interacting with the LLM and tools, producing events representing the agent's ongoing actions.
Output State Saving
func (a *llmAgent) maybeSaveOutputToState(event *session.Event) {
if event.Author != a.Name() { return }
if a.OutputKey != "" && !event.Partial && event.Content != nil {
// Concatenate text parts excluding thoughts
// Save result under OutputKey in event.Actions.StateDelta
}
}
This function ensures that the agent's final textual output is persisted into session state, enabling stateful agent coordination.
Callback Types
type BeforeModelCallback func(ctx agent.CallbackContext, llmRequest *model.LLMRequest) (*model.LLMResponse, error)
type AfterModelCallback func(ctx agent.CallbackContext, llmResponse *model.LLMResponse, llmResponseError error) (*model.LLMResponse, error)
type BeforeToolCallback func(ctx tool.Context, tool tool.Tool, args map[string]any) (map[string]any, error)
type AfterToolCallback func(ctx tool.Context, tool tool.Tool, args, result map[string]any, err error) (map[string]any, error)
These callback signatures define the interception points for model and tool invocation, allowing early return, error handling, and result modification.
Visualization of Agent Invocation Flow
sequenceDiagram
participant User as User Input
participant Agent as LLMAgent
participant LLM as LLM Model
participant Tools as Tooling System
participant Session as Session Management
User->>Agent: Send user message
Agent->>Session: Append message to session state
Agent->>Agent: Run BeforeAgentCallbacks
Agent->>Agent: Prepare instruction (static or via InstructionProvider)
Agent->>LLM: Send LLMRequest with instruction and user input
LLM-->>Agent: Return LLMResponse (streamed)
alt LLMResponse contains function call
Agent->>Agent: Run BeforeToolCallbacks
Agent->>Tools: Invoke tool with arguments
Tools-->>Agent: Tool result or error
Agent->>Agent: Run AfterToolCallbacks
Agent->>LLM: Continue LLM interaction with tool result
else LLMResponse is final
Agent->>Agent: Run AfterModelCallbacks
Agent->>Agent: Run AfterAgentCallbacks
Agent->>Session: Append LLM response event, save output to state if configured
Agent-->>User: Return response events
end
This sequence diagram illustrates the interaction among the user, agent, LLM, tools, and session during a single invocation cycle.
Subtopics
[LLM Agent Configuration](/LLM Agent Configuration): Details about configuring the LLM agent, including model setup, tools, callbacks, and instruction parameters.
[Instruction Injection](/Instruction Injection): Explains how instruction templates are processed and injected with dynamic session state and artifact data at runtime.