main.go
Overview
The main.go file implements a command-line executable that constructs and launches a sequential AI agent pipeline for automated Python code generation, review, and refactoring. It leverages the Google AI Developer Kit (ADK) to create three specialized sub-agents—Code Writer, Code Reviewer, and Code Refactorer—and orchestrates their execution in a fixed sequence using a SequentialAgent. This pipeline accepts a user specification, generates Python code, reviews it for quality and correctness, and refactors it based on review feedback. The final orchestrated agent is launched via the ADK framework's launcher subsystem, enabling runtime interaction.
This file primarily demonstrates agent composition, LLM integration, and workflow orchestration within the ADK ecosystem, referencing topics on LLM Integration and Agents, Agent Workflow Management, and Sequential Agent.
Detailed Explanation
Imports and Package
Uses core packages:
context,log, andosfor execution context, logging, and command-line argument access.Imports ADK packages for agent creation (
agent,llmagent,sequentialagent), model loading (gemini), and launching (launcher,full).Imports Gemini LLM client support (
genai).
main Function
The main function is the entry point that performs the following steps:
1. Context Initialization
ctx := context.Background()
Initializes a background context used across API calls and agent creation for cancellation and tracing.
2. Model Creation
model, err := gemini.NewModel(ctx, "gemini-2.5-flash", &genai.ClientConfig{})
Creates a Gemini LLM model instance named
"gemini-2.5-flash"with default client configuration.The model is the core LLM used by all sub-agents for text generation and analysis.
If model creation fails, the program logs a fatal error and terminates.
3. Sub-Agent Definitions
Three specialized LLM agents are created using llmagent.New with different instructions and output keys:
a. Code Writer Agent
Purpose: Generate initial Python code from a user specification.
Instruction: Generates only a Python code block enclosed in triple backticks without extraneous text.
OutputKey:
"generated_code"— stores generated code in the agent state.
codeWriterAgent, err := llmagent.New(llmagent.Config{
Name: "CodeWriterAgent",
Model: model,
Instruction: "...",
Description: "Writes initial Python code based on a specification.",
OutputKey: "generated_code",
})
b. Code Reviewer Agent
Purpose: Review the generated Python code for correctness, readability, efficiency, edge cases, and best practices.
Instruction: Receives
{generated_code}as input, applies review criteria, and outputs bulleted feedback or "No major issues found."OutputKey:
"review_comments"— stores review feedback in the agent state.
codeReviewerAgent, err := llmagent.New(llmagent.Config{
Name: "CodeReviewerAgent",
Model: model,
Instruction: "...",
Description: "Reviews code and provides feedback.",
OutputKey: "review_comments",
})
c. Code Refactorer Agent
Purpose: Refactor the original code based on the review comments.
Instruction: Takes
{generated_code}and{review_comments}, applies improvements, returns a complete, functional, and well-documented Python code block.Returns original code unchanged if no issues are found.
OutputKey:
"refactored_code"— stores the final refactored code.
codeRefactorerAgent, err := llmagent.New(llmagent.Config{
Name: "CodeRefactorerAgent",
Model: model,
Instruction: "...",
Description: "Refactors code based on review comments.",
OutputKey: "refactored_code",
})
Each agent creation includes error handling to abort execution if initialization fails.
Usage example for sub-agent instantiation:
agent, err := llmagent.New(llmagent.Config{...})
if err != nil {
log.Fatalf("failed to create agent: %s", err)
}
4. Sequential Agent Creation
codePipelineAgent, err := sequentialagent.New(sequentialagent.Config{
AgentConfig: agent.Config{
Name: "CodePipelineAgent",
SubAgents: []agent.Agent{codeWriterAgent, codeReviewerAgent, codeRefactorerAgent},
Description: "Executes a sequence of code writing, reviewing, and refactoring.",
},
})
Wraps the three sub-agents into a single pipeline agent that runs them in order.
Uses the
SequentialAgentimplementation from Agent Workflow Management and Sequential Agent.Orchestrates the flow of data by passing the state between stages keyed by
OutputKey.
5. Agent Launching
The pipeline agent is assigned to
rootAgent.A launcher configuration is created with the single root agent loader.
The launcher (
full.NewLauncher()) executes the agent pipeline using command-line arguments.
config := &launcher.Config{
AgentLoader: agent.NewSingleLoader(rootAgent),
}
l := full.NewLauncher()
if err = l.Execute(ctx, config, os.Args[1:]); err != nil {
log.Fatalf("Run failed: %v\n\n%s", err, l.CommandLineSyntax())
}
The launcher manages the lifecycle, CLI parsing, and runtime environment according to REST API and Web Launchers.
Implementation Details
The pipeline leverages LLM agents configured with detailed instructions to fulfill distinct roles, demonstrating specialization and modularity as discussed in LLM Integration and Agents.
Uses context propagation for cancellation and observability.
Implements error handling by terminating on critical failures.
The state dictionary shared across agents uses keys (
generated_code,review_comments,refactored_code) to pass outputs forward.The instructions explicitly require output formatting (e.g., triple backticks) to ensure parsable LLM responses.
The sequential execution pattern is essential to enforce the pipeline logic of generation → review → refactor, covered by Sequential Agent.
Integration with the launcher subsystem supports runtime command-line invocation and is extensible for other deployment modes.
Interaction with Other System Components
Model Loading: Uses Gemini model from the
geminipackage, which wraps the underlying LLM client (genai).Agent Framework: Uses the core agent interfaces and lifecycle from
agentandllmagentpackages.Workflow: The
sequentialagentmanages sub-agent orchestration as a composite agent.Launcher: The
launcherandfullpackages provide executable runtime environment and CLI integration.Logging: The standard logger outputs critical errors and startup information.
This file acts as a bridge between the underlying ADK libraries and the user-facing executable.
Usage Example
To run the pipeline, invoke the compiled binary with user specification input as arguments or via interactive session (depending on launcher capabilities). The pipeline will:
Receive a specification string.
Generate Python code fulfilling the spec.
Review the generated code.
Refactor the code based on review.
Output the final improved Python code snippet.
Diagram: Agent Structure and Workflow
flowchart TD
A[main.go] --> B[Gemini Model]
A --> C[CodeWriterAgent]
C --> D[generated_code]
D --> E[CodeReviewerAgent]
E --> F[review_comments]
F --> G[CodeRefactorerAgent]
G --> H[refactored_code]
H --> I[SequentialAgent: Runs C->E->G]
I --> J[Launcher: Executes SequentialAgent]
Gemini Model is shared by all LLM agents.
Outputs from one agent feed as inputs (via state keys) to the next.
The
SequentialAgentenforces linear execution.The
Launcherhandles execution lifecycle and CLI.
This file exemplifies orchestrating multiple LLM-powered agents into a cohesive AI pipeline using the ADK framework, demonstrating modular design, instruction templating, and sequential workflow management concepts from related topics.