Skip to content

Conversation

leweii
Copy link

@leweii leweii commented Aug 28, 2025

Move the planning_re_act_planner python implementation to java version.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @leweii, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces comprehensive support for 'Planners' within the ADK Java library, porting functionality previously available in Python. The core change involves integrating a BasePlanner interface into the LlmAgent, allowing agents to utilize various planning strategies. New planner implementations, including a BuiltInPlanner and a PlanReActPlanner, are provided, along with new request and response processors that seamlessly integrate planning logic into the existing LLM interaction flows. This enhancement enables LLM agents to perform more structured reasoning and action sequences.

Highlights

  • LlmAgent Enhancements for Planner Integration: The LlmAgent class has been extended to support the integration of BasePlanner instances, allowing agents to leverage planning capabilities. This includes adding a new planner field and corresponding builder and getter methods.
  • Introduction of Planning Framework: New interfaces and classes (BasePlanner, BuiltInPlanner, PlanReActPlanner) have been introduced to define and implement different planning strategies. BasePlanner sets the contract, BuiltInPlanner handles generic thinking configurations, and PlanReActPlanner provides a structured approach for reasoning and acting.
  • Integration of Planning into LLM Flows: The core LLM processing flow, specifically SingleFlow, has been updated to incorporate new request and response processors from the NLPlanning class. This ensures that planning logic is applied during both the request preparation and response handling phases of LLM interactions.
  • New NLPlanning Processors: A new NLPlanning class has been added, containing dedicated request and response processors. These processors are responsible for generating planning instructions for the LLM and processing the LLM's responses, including handling thought annotations and integrating with the BasePlanner implementation.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for Planners in the Java ADK, notably porting the Plan-ReAct planner from its Python counterpart. The changes are extensive, adding new interfaces and classes for planners and integrating them into the agent and flow logic. The implementation is largely solid, but I've identified a critical bug where a method's return value is ignored, which would prevent a feature from working as intended. I have also included some suggestions to improve code quality and style by removing redundant checks and adopting more modern Java features.

Comment on lines +129 to +135
private static Optional<BasePlanner> getPlanner(InvocationContext invocationContext) {
if (!(invocationContext.agent() instanceof LlmAgent agent)) {
return Optional.empty();
}

return agent.planner();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The check for invocationContext.agent() instanceof LlmAgent is redundant here. The callers of this method, NlPlanningRequestProcessor.processRequest and NlPlanningResponseProcessor.processResponse, already perform this validation and throw an IllegalArgumentException if the agent is not an LlmAgent. You can simplify this method by removing the redundant check and casting directly.

  private static Optional<BasePlanner> getPlanner(InvocationContext invocationContext) {
    return ((LlmAgent) invocationContext.agent()).planner();
  }

Comment on lines +148 to +157
String highLevelPreamble =
String.format(
"""
When answering the question, try to leverage the available tools to gather the information instead of your memorized knowledge.

Follow this process when answering the question: (1) first come up with a plan in natural language text format; (2) Then use tools to execute the plan and provide reasoning between tool code snippets to make a summary of current state and next step. Tool code snippets and reasoning should be interleaved with each other. (3) In the end, return one final answer.

Follow this format when answering the question: (1) The planning part should be under %s. (2) The tool code snippets should be under %s, and the reasoning parts should be under %s. (3) The final answer part should be under %s.
""",
PLANNING_TAG, ACTION_TAG, REASONING_TAG, FINAL_ANSWER_TAG);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For improved readability and to leverage modern Java features, consider using the String.formatted() instance method, which was introduced in Java 15. It can be called directly on a text block, making the code more fluent than using the static String.format() method.

    String highLevelPreamble =
        """
        When answering the question, try to leverage the available tools to gather the information instead of your memorized knowledge.

        Follow this process when answering the question: (1) first come up with a plan in natural language text format; (2) Then use tools to execute the plan and provide reasoning between tool code snippets to make a summary of current state and next step. Tool code snippets and reasoning should be interleaved with each other. (3) In the end, return one final answer.

        Follow this format when answering the question: (1) The planning part should be under %s. (2) The tool code snippets should be under %s, and the reasoning parts should be under %s. (3) The final answer part should be under %s.
        """.formatted(PLANNING_TAG, ACTION_TAG, REASONING_TAG, FINAL_ANSWER_TAG);

Comment on lines +159 to +166
String planningPreamble =
String.format(
"""
Below are the requirements for the planning:
The plan is made to answer the user query if following the plan. The plan is coherent and covers all aspects of information from user query, and only involves the tools that are accessible by the agent. The plan contains the decomposed steps as a numbered list where each step should use one or multiple available tools. By reading the plan, you can intuitively know which tools to trigger or what actions to take.
If the initial plan cannot be successfully executed, you should learn from previous execution results and revise your plan. The revised plan should be be under %s. Then use tools to follow the new plan.
""",
REPLANNING_TAG);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the previous comment, you can use the String.formatted() instance method here for better code style and readability.

    String planningPreamble =
        """
        Below are the requirements for the planning:
        The plan is made to answer the user query if following the plan. The plan is coherent and covers all aspects of information from user query, and only involves the tools that are accessible by the agent. The plan contains the decomposed steps as a numbered list where each step should use one or multiple available tools. By reading the plan, you can intuitively know which tools to trigger or what actions to take.
        If the initial plan cannot be successfully executed, you should learn from previous execution results and revise your plan. The revised plan should be be under %s. Then use tools to follow the new plan.
        """.formatted(REPLANNING_TAG);

@isctylr
Copy link

isctylr commented Oct 1, 2025

Hey @leweii I'd love to see this get approved. Have you reviewed https://github.com/google/adk-java/blob/main/CONTRIBUTING.md ? Make sure you sign the CLA if you haven't already.

But also this won't be accepted because the PR is 9 commits and needs to be one.

Additionally, I expect at least minimum unit tests need to be implemented - hopefully they can be ported over from python without too much extra effort as well. Happy to help with that if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants