Skip to content

Commit 49ff63b

Browse files
damianmomotgooglecopybara-github
authored andcommitted
docs: clarify LlmAgent composition for workflow agents
Document on ParallelAgent, SequentialAgent, and LoopAgent that they do not transfer control back to an LlmAgent orchestrator after they complete, and that placing the workflow agent and any follow-up agent as siblings inside a SequentialAgent (used as the root or transferred-to agent) is the recommended pattern. This matches the behavior of adk-python v1.x, which is the line that Java ADK currently tracks. A more robust orchestration will be available once Java reaches the Graph Workflows milestone aligned with adk-python v2.0. PiperOrigin-RevId: 922080205
1 parent a0c4b7b commit 49ff63b

3 files changed

Lines changed: 82 additions & 1 deletion

File tree

core/src/main/java/com/google/adk/agents/LoopAgent.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,30 @@
3030
*
3131
* <p>The loop continues until a sub-agent escalates, or until the maximum number of iterations is
3232
* reached (if specified).
33+
*
34+
* <p><b>Composition with {@link LlmAgent}s:</b> a {@code LoopAgent} does not transfer control back
35+
* to a parent {@link LlmAgent}. To react to loop results, place the {@code LoopAgent} and the
36+
* follow-up {@link LlmAgent} as siblings inside a {@link SequentialAgent}. Loop sub-agents publish
37+
* via {@code outputKey} and the follow-up reads via {@code {key}} placeholders in its instruction:
38+
*
39+
* <pre>{@code
40+
* var refiner =
41+
* LlmAgent.builder()
42+
* .name("refiner")
43+
* .model("gemini-flash-latest")
44+
* .instruction("Refine: {draft?}")
45+
* .outputKey("draft")
46+
* .build();
47+
* var publisher =
48+
* LlmAgent.builder()
49+
* .name("publisher")
50+
* .model("gemini-flash-latest")
51+
* .instruction("Publish: {draft}")
52+
* .build();
53+
* var loop =
54+
* LoopAgent.builder().name("loop").subAgents(refiner).maxIterations(3).build();
55+
* var root = SequentialAgent.builder().name("root").subAgents(loop, publisher).build();
56+
* }</pre>
3357
*/
3458
public class LoopAgent extends BaseAgent {
3559
private static final Logger logger = LoggerFactory.getLogger(LoopAgent.class);

core/src/main/java/com/google/adk/agents/ParallelAgent.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,38 @@
3434
* <p>This approach is beneficial for scenarios requiring multiple perspectives or attempts on a
3535
* single task, such as running different algorithms simultaneously or generating multiple responses
3636
* for review by a subsequent evaluation agent.
37+
*
38+
* <p><b>Composition with {@link LlmAgent}s:</b> a {@code ParallelAgent} does not transfer control
39+
* back to a parent {@link LlmAgent}. To follow a fan-out with an aggregation step, wrap both in a
40+
* {@link SequentialAgent} (used as the root or transferred-to agent). Each parallel sub-agent
41+
* publishes via {@code outputKey} and the aggregator reads via {@code {key}} placeholders in its
42+
* instruction:
43+
*
44+
* <pre>{@code
45+
* var contacts =
46+
* LlmAgent.builder()
47+
* .name("contacts")
48+
* .model("gemini-flash-latest")
49+
* .instruction("List contacts.")
50+
* .outputKey("contacts")
51+
* .build();
52+
* var schedule =
53+
* LlmAgent.builder()
54+
* .name("schedule")
55+
* .model("gemini-flash-latest")
56+
* .instruction("List schedule.")
57+
* .outputKey("schedule")
58+
* .build();
59+
* var writer =
60+
* LlmAgent.builder()
61+
* .name("writer")
62+
* .model("gemini-flash-latest")
63+
* .instruction("Write: contacts={contacts}, schedule={schedule}")
64+
* .build();
65+
* var gather =
66+
* ParallelAgent.builder().name("gather").subAgents(contacts, schedule).build();
67+
* var root = SequentialAgent.builder().name("root").subAgents(gather, writer).build();
68+
* }</pre>
3769
*/
3870
public class ParallelAgent extends BaseAgent {
3971

core/src/main/java/com/google/adk/agents/SequentialAgent.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,32 @@
2222
import org.slf4j.Logger;
2323
import org.slf4j.LoggerFactory;
2424

25-
/** An agent that runs its sub-agents sequentially. */
25+
/**
26+
* An agent that runs its sub-agents sequentially.
27+
*
28+
* <p><b>Composition with {@link LlmAgent}s:</b> a {@code SequentialAgent} does not transfer control
29+
* back to a parent {@link LlmAgent}. Use it as the root or transferred-to agent and place any
30+
* follow-up {@link LlmAgent} as the next sibling. Upstream publishes via {@code outputKey} and
31+
* downstream reads via {@code {key}} placeholders in its instruction:
32+
*
33+
* <pre>{@code
34+
* var draft =
35+
* LlmAgent.builder()
36+
* .name("draft")
37+
* .model("gemini-flash-latest")
38+
* .instruction("Draft a summary.")
39+
* .outputKey("draft")
40+
* .build();
41+
* var reviewer =
42+
* LlmAgent.builder()
43+
* .name("reviewer")
44+
* .model("gemini-flash-latest")
45+
* .instruction("Polish the draft: {draft}")
46+
* .build();
47+
* var pipeline =
48+
* SequentialAgent.builder().name("pipeline").subAgents(draft, reviewer).build();
49+
* }</pre>
50+
*/
2651
public class SequentialAgent extends BaseAgent {
2752

2853
private static final Logger logger = LoggerFactory.getLogger(SequentialAgent.class);

0 commit comments

Comments
 (0)