agent_test.go
Overview
The agent_test.go file contains unit tests and helper implementations for validating the behavior of the Sequential Agent within the Agent Workflow Management system. Specifically, it tests the construction, execution, and error scenarios of the sequentialagent package, which implements an agent that runs its sub-agents sequentially exactly once per invocation.
This test suite ensures:
The correct ordering and content of events produced by sequential execution of sub-agents.
Proper handling of nested
SequentialAgentinstances.Enforcement of unique agent names and prevention of duplicate sub-agent usage across the agent tree.
Interaction correctness between the sequential agent, its sub-agents, the session service, and the runner.
In addition to tests, the file includes mock implementations of LLM models (FakeLLM) and utility functions to create custom or sequential agents for testing purposes.
Detailed Explanation of Components
Test Function: TestNewSequentialAgent
Purpose
Validates the creation and runtime execution of a SequentialAgent with various configurations of sub-agents, including nested sequential agents and error cases related to duplicate agent names and multiple parenting.
Test Structure
Input Arguments:
maxIterations (uint): Passed to configure the sequential agent, but always zero here, meaning no explicit iteration limit (consistent with sequential agent semantics).
subAgents([]agent.Agent): The list of sub-agents to run in order.
Expected Outputs:
wantEvents ([]*session.Event): The expected sequence of session events produced by running the agent.
wantErr (bool): Indicates if an error is expected.
wantErrMessage (string): Expected error message substring for validation.
Test Cases
"ok": Runs two custom agents sequentially, expects events with LLMResponse content "hello 0" and "hello 1".
"ok with inner sequential": Runs a three-step sequence where the middle step is itself a sequential agent running two custom agents. The expected events reflect the unfolding of all sub-agents in strict order.
Error cases:
Duplicate agent names anywhere in the agent tree cause creation failure.
Duplicate usage of the same sub-agent instance in multiple places triggers errors.
Multiple parents for the same sub-agent instance also causes errors.
Implementation Details
The test uses a runner (
runner.New) that manages agent execution within a session context (session.InMemoryService).The agent is run twice to confirm idempotency and consistent event sequences.
Event comparison uses the
go-cmplibrary, ignoring non-deterministic fields (ID, Timestamp, InvocationID).Errors during agent creation or execution are checked against expected values.
Helper Function: newCustomAgent
Purpose
Creates a simple llmagent.Agent with a mocked LLM that returns a deterministic response identifying the agent by an integer ID.
Parameters
t *testing.T: Test handle for reporting errors.id int: Identifier for naming and response content.
Returns
agent.Agent: Configured with aFakeLLMinstance.
Usage Example
agent := newCustomAgent(t, 5) // Creates a custom agent named "custom_agent_5"
Helper Function: newSequentialAgent
Purpose
Constructs a SequentialAgent instance for testing, wrapping the sub-agents provided.
Parameters
t *testing.T: Test handle.subAgents []agent.Agent: List of sub-agents to execute sequentially.name string: Name of the sequential agent instance.
Returns
agent.Agent: The constructed sequential agent or fails the test if creation errors occur.
Usage Example
seqAgent := newSequentialAgent(t, []agent.Agent{agent1, agent2}, "test_seq_agent")
Mock Implementation: FakeLLM
Purpose
Provides a mocked implementation of the model.LLM interface for controlled test responses.
Properties
id int: Used to differentiate responses.callCounter int: Tracks how many timesGenerateContenthas been called.
Methods
Name() string
Returns a fixed string"fake-llm"identifying the mock model.GenerateContent(ctx context.Context, req *model.LLMRequest, stream bool) iter.Seq2[*model.LLMResponse, error]
Returns a single response with content"hello <id>"where<id>is theFakeLLMinstance ID.
This method implements a generator pattern yielding exactly oneLLMResponseand no error.
Usage
Injected into llmagent instances to simulate LLM responses during tests.
Important Implementation Details
The test enforces strict rules on agent tree construction to avoid ambiguous workflows:
Agent names must be unique across the entire tree.
Sub-agent instances cannot appear multiple times in the sub-agent list.
Sub-agents cannot have more than one parent agent.
The
SequentialAgentitself is implemented by thesequentialagent.Newfunction, which internally creates a loop agent configured for exactly one iteration (see Sequential Agent).The
runnerpackage coordinates the execution flow and manages session state, feeding user input and collecting agent-generated events.The
session.InMemoryService()is used to store session events and state in-memory for test isolation and simplicity.The
FakeLLMsimulates asynchronous LLM generation through a generator function returning a single deterministic response for each call.
Interaction with Other Parts of the System
Sequential Agent (
sequentialagent): The primary subject under test; constructs sequential workflows of sub-agents.Sub-agents (
llmagent): Leaf agents producing LLM responses; here mocked withFakeLLMfor deterministic test behavior.Session Service (
session.InMemoryService): Manages session lifecycle and event history during agent runs.Runner (
runner): Orchestrates agent execution within sessions, feeding input and collecting output events.Agent Interface (
agent.Agent): The interface implemented by all agents including sequential and LLM agents, enabling polymorphic execution.
This file tests the end-to-end integration of these components in the context of sequential workflows.
Usage Example Snippet
// Create sub-agents
agent1 := newCustomAgent(t, 0)
agent2 := newCustomAgent(t, 1)
// Create sequential agent with sub-agents
seqAgent := newSequentialAgent(t, []agent.Agent{agent1, agent2}, "test_agent")
// Create runner and session service
sessionService := session.InMemoryService()
agentRunner, _ := runner.New(runner.Config{
AppName: "test_app",
Agent: seqAgent,
SessionService: sessionService,
})
// Create session and run agent
ctx := context.Background()
sessionService.Create(ctx, &session.CreateRequest{
AppName: "test_app",
UserID: "user1",
SessionID: "session1",
})
for event, err := range agentRunner.Run(ctx, "user1", "session1", genai.NewContentFromText("hello", genai.RoleUser), agent.RunConfig{}) {
if err != nil {
t.Error(err)
}
fmt.Println(event.Author, event.LLMResponse.Content.Parts[0].Text)
}
Visual Diagram: Structure and Workflow of agent_test.go
flowchart TD
TestNewSequentialAgent --> SequentialAgentCreation[Create SequentialAgent]
TestNewSequentialAgent --> RunnerSetup[Setup Runner & SessionService]
TestNewSequentialAgent --> AgentRun[Run Agent Twice]
TestNewSequentialAgent --> EventValidation[Validate Output Events]
SequentialAgentCreation --> SubAgentsCreation[Create Sub-Agents]
SubAgentsCreation --> FakeLLM[FakeLLM Returns "hello <id>"]
AgentRun --> SessionService[SessionService Stores Events]
EventValidation --> goCmp[Compare Using go-cmp]
subgraph Helpers
newCustomAgent
newSequentialAgent
FakeLLM
end
newCustomAgent --> FakeLLM
newSequentialAgent --> SequentialAgentCreation
This flowchart represents the core testing workflow: test case setups create sequential agents composed of custom sub-agents backed by FakeLLM. The agent is run via a runner that interacts with an in-memory session service. The test validates the streamed events against expected outputs.
References to Related Topics
The tested agent is an implementation of the Sequential Agent pattern within Agent Workflow Management.
The mock LLM agents relate to LLM Integration and Agents.
Execution is coordinated by the Agent Execution Runner.
Session persistence and event streaming rely on Session Management.
The underlying structure and invocation context relate to Agent Invocation Context.
This documentation describes the testing mechanisms, helper constructs, and system interactions for validating sequential agent workflows, ensuring robust and predictable multi-agent orchestration within the framework.