Sequential agents¶
SequentialAgent¶
SequentialAgent 是一種工作流程 agent,會依照列表中指定的順序執行其子 agent。
當你希望執行順序是固定且嚴格時,請使用 SequentialAgent。
範例¶
- 你想建立一個能摘要任意網頁的 agent,並使用兩個工具:
Get Page Contents和Summarize Page。由於 agent 必須在呼叫Summarize Page前先呼叫Get Page Contents(不能無中生有地摘要!),因此你應該使用SequentialAgent來建立你的 agent。
如同其他工作流程 agent,SequentialAgent 並非由大型語言模型 (LLM) 驅動,因此其執行方式是確定性的。需要注意的是,工作流程 agent 只關心執行順序(即依序執行),而不涉及內部邏輯;工作流程 agent 的工具或子 agent 可以使用 LLM,也可以不使用。
運作方式¶
當呼叫 SequentialAgent 的 Run Async 方法時,會執行以下動作:
- 迭代: 依照提供的順序,遍歷子 agent 列表。
- 子 agent 執行: 對列表中的每個子 agent,呼叫該子 agent 的
Run Async方法。

完整範例:程式碼開發流程¶
以簡化的程式碼開發流程為例:
- Code Writer Agent: 由大型語言模型 (LLM) 驅動的 agent,根據規格產生初始程式碼。
- Code Reviewer Agent: 由大型語言模型 (LLM) 驅動的 agent,負責檢查產生的程式碼是否有錯誤、風格問題,以及是否符合最佳實踐。它會接收 Code Writer Agent 的輸出。
- Code Refactorer Agent: 由大型語言模型 (LLM) 驅動的 agent,接收經過審查的程式碼(以及審查者的評論),並進行重構以提升品質並解決問題。
SequentialAgent 非常適合用於這種情境:
這可確保程式碼會先被撰寫,接著進行審查,最後再進行重構,並且按照嚴格且可靠的順序執行。每個子 agent 的輸出會透過 Output Key 儲存在 state 中,並傳遞給下一個子 agent。
Shared Invocation Context
SequentialAgent 會將相同的 InvocationContext 傳遞給其所有子 agent。這表示它們都共享相同的 session state,包括暫存(temp:)命名空間,使得在單一 agent 回合內於各步驟之間傳遞資料變得十分容易。
Code
# Part of agent.py --> Follow https://google.github.io/adk-docs/get-started/quickstart/ to learn the setup
# --- 1. Define Sub-Agents for Each Pipeline Stage ---
# Code Writer Agent
# Takes the initial specification (from user query) and writes code.
code_writer_agent = LlmAgent(
name="CodeWriterAgent",
model=GEMINI_MODEL,
# Change 3: Improved instruction
instruction="""You are a Python Code Generator.
Based *only* on the user's request, write Python code that fulfills the requirement.
Output *only* the complete Python code block, enclosed in triple backticks (```python ... ```).
Do not add any other text before or after the code block.
""",
description="Writes initial Python code based on a specification.",
output_key="generated_code" # Stores output in state['generated_code']
)
# Code Reviewer Agent
# Takes the code generated by the previous agent (read from state) and provides feedback.
code_reviewer_agent = LlmAgent(
name="CodeReviewerAgent",
model=GEMINI_MODEL,
# Change 3: Improved instruction, correctly using state key injection
instruction="""You are an expert Python Code Reviewer.
Your task is to provide constructive feedback on the provided code.
**Code to Review:**
```python
{generated_code}
```
**Review Criteria:**
1. **Correctness:** Does the code work as intended? Are there logic errors?
2. **Readability:** Is the code clear and easy to understand? Follows PEP 8 style guidelines?
3. **Efficiency:** Is the code reasonably efficient? Any obvious performance bottlenecks?
4. **Edge Cases:** Does the code handle potential edge cases or invalid inputs gracefully?
5. **Best Practices:** Does the code follow common Python best practices?
**Output:**
Provide your feedback as a concise, bulleted list. Focus on the most important points for improvement.
If the code is excellent and requires no changes, simply state: "No major issues found."
Output *only* the review comments or the "No major issues" statement.
""",
description="Reviews code and provides feedback.",
output_key="review_comments", # Stores output in state['review_comments']
)
# Code Refactorer Agent
# Takes the original code and the review comments (read from state) and refactors the code.
code_refactorer_agent = LlmAgent(
name="CodeRefactorerAgent",
model=GEMINI_MODEL,
# Change 3: Improved instruction, correctly using state key injection
instruction="""You are a Python Code Refactoring AI.
Your goal is to improve the given Python code based on the provided review comments.
**Original Code:**
```python
{generated_code}
```
**Review Comments:**
{review_comments}
**Task:**
Carefully apply the suggestions from the review comments to refactor the original code.
If the review comments state "No major issues found," return the original code unchanged.
Ensure the final code is complete, functional, and includes necessary imports and docstrings.
**Output:**
Output *only* the final, refactored Python code block, enclosed in triple backticks (```python ... ```).
Do not add any other text before or after the code block.
""",
description="Refactors code based on review comments.",
output_key="refactored_code", # Stores output in state['refactored_code']
)
# --- 2. Create the SequentialAgent ---
# This agent orchestrates the pipeline by running the sub_agents in order.
code_pipeline_agent = SequentialAgent(
name="CodePipelineAgent",
sub_agents=[code_writer_agent, code_reviewer_agent, code_refactorer_agent],
description="Executes a sequence of code writing, reviewing, and refactoring.",
# The agents will run in the order provided: Writer -> Reviewer -> Refactorer
)
# For ADK tools compatibility, the root agent must be named `root_agent`
root_agent = code_pipeline_agent
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.events.Event;
import com.google.adk.runner.InMemoryRunner;
import com.google.adk.sessions.Session;
import com.google.genai.types.Content;
import com.google.genai.types.Part;
import io.reactivex.rxjava3.core.Flowable;
public class SequentialAgentExample {
private static final String APP_NAME = "CodePipelineAgent";
private static final String USER_ID = "test_user_456";
private static final String MODEL_NAME = "gemini-2.0-flash";
public static void main(String[] args) {
SequentialAgentExample sequentialAgentExample = new SequentialAgentExample();
sequentialAgentExample.runAgent(
"Write a Java function to calculate the factorial of a number.");
}
public void runAgent(String prompt) {
LlmAgent codeWriterAgent =
LlmAgent.builder()
.model(MODEL_NAME)
.name("CodeWriterAgent")
.description("Writes initial Java code based on a specification.")
.instruction(
"""
You are a Java Code Generator.
Based *only* on the user's request, write Java code that fulfills the requirement.
Output *only* the complete Java code block, enclosed in triple backticks (```java ... ```).
Do not add any other text before or after the code block.
""")
.outputKey("generated_code")
.build();
LlmAgent codeReviewerAgent =
LlmAgent.builder()
.model(MODEL_NAME)
.name("CodeReviewerAgent")
.description("Reviews code and provides feedback.")
.instruction(
"""
You are an expert Java Code Reviewer.
Your task is to provide constructive feedback on the provided code.
**Code to Review:**
```java
{generated_code}
```
**Review Criteria:**
1. **Correctness:** Does the code work as intended? Are there logic errors?
2. **Readability:** Is the code clear and easy to understand? Follows Java style guidelines?
3. **Efficiency:** Is the code reasonably efficient? Any obvious performance bottlenecks?
4. **Edge Cases:** Does the code handle potential edge cases or invalid inputs gracefully?
5. **Best Practices:** Does the code follow common Java best practices?
**Output:**
Provide your feedback as a concise, bulleted list. Focus on the most important points for improvement.
If the code is excellent and requires no changes, simply state: "No major issues found."
Output *only* the review comments or the "No major issues" statement.
""")
.outputKey("review_comments")
.build();
LlmAgent codeRefactorerAgent =
LlmAgent.builder()
.model(MODEL_NAME)
.name("CodeRefactorerAgent")
.description("Refactors code based on review comments.")
.instruction(
"""
You are a Java Code Refactoring AI.
Your goal is to improve the given Java code based on the provided review comments.
**Original Code:**
```java
{generated_code}
```
**Review Comments:**
{review_comments}
**Task:**
Carefully apply the suggestions from the review comments to refactor the original code.
If the review comments state "No major issues found," return the original code unchanged.
Ensure the final code is complete, functional, and includes necessary imports and docstrings.
**Output:**
Output *only* the final, refactored Java code block, enclosed in triple backticks (```java ... ```).
Do not add any other text before or after the code block.
""")
.outputKey("refactored_code")
.build();
SequentialAgent codePipelineAgent =
SequentialAgent.builder()
.name(APP_NAME)
.description("Executes a sequence of code writing, reviewing, and refactoring.")
// The agents will run in the order provided: Writer -> Reviewer -> Refactorer
.subAgents(codeWriterAgent, codeReviewerAgent, codeRefactorerAgent)
.build();
// Create an InMemoryRunner
InMemoryRunner runner = new InMemoryRunner(codePipelineAgent, APP_NAME);
// InMemoryRunner automatically creates a session service. Create a session using the service
Session session = runner.sessionService().createSession(APP_NAME, USER_ID).blockingGet();
Content userMessage = Content.fromParts(Part.fromText(prompt));
// Run the agent
Flowable<Event> eventStream = runner.runAsync(USER_ID, session.id(), userMessage);
// Stream event response
eventStream.blockingForEach(
event -> {
if (event.finalResponse()) {
System.out.println(event.stringifyContent());
}
});
}
}