[FEATURE] Port ReflectAndRetryToolPlugin from adk-python
Maintainers usually reply within 1 day
Assessment
This issue has not been assessed yet.
Description
Please make sure you read the contribution guide and file the issues in the right place.
Contribution guide.
🔴 Required Information
Is your feature request related to a specific problem?
When a tool fails, adk-java gives the model no way to learn what went wrong and try again. A tool
that reports its failure ends the invocation on the first attempt, even when the failure is one the
model could have corrected — malformed arguments, the wrong tool for the job, a precondition it
could have satisfied first.
adk-python ships a plugin for exactly this — ReflectAndRetryToolPlugin. adk-java
has no equivalent.
Describe the Solution You'd Like
ReflectAndRetryToolPlugin in com.google.adk.plugins.reflectandretry, registered on a Runner
like any other plugin, behaving as adk-python's does:
- intercept tool failures through the two hooks that already exist on
Plugin—
onToolErrorCallbackfor a tool that signals an error, andafterToolCallbackfor a result that
carries one; - track consecutive failures per tool within a scope, so a success with one tool resets that
tool's counter without forgiving another's; - substitute a structured reflection response — error type, error details, retry count, and guidance
telling the model to analyze the arguments and not repeat the identical call — for each failure up
tomaxRetries; - past the limit, either propagate the original error or return a final "stop using this tool"
message, per a constructor flag; - scope the counters per invocation (default) or globally, via a
TrackingScopeenum.
No existing class changes and no existing API changes: registration uses the plugin surfaces already
present.
Impact on your work
Applications wanting adk-python's behavior have to reimplement it in application code, where it
drifts from upstream. Not blocking and there is no timeline — this is a parity gap, not an outage.
Willingness to contribute
Yes. A PR follows immediately after this issue: one new public plugin class plus four small
supporting types in a plugins.reflectandretry subpackage, with tests. No existing file is
modified.
🟡 Recommended Information
Describe Alternatives You've Considered
Retry inside the tool itself. This is the obvious workaround and it is not the same thing. A
loop inside the tool repeats the identical call; the point of reflection is to hand the model the
error and its own arguments so it can call differently. A tool cannot fix arguments it did not
choose.
Implement the plugin in application code. It works — the behavior above was verified using
public API only. But it is per-application boilerplate for something the plugin surface exists to
ship once, and every copy drifts from upstream separately.
Widen onToolErrorCallback semantics instead. That would change existing behavior for every
plugin. A new opt-in plugin changes nothing for anyone who does not register it.
Proposed API / Implementation
Registration needs no new API:
Runner runner =
new InMemoryRunner(agent, "my-app", ImmutableList.of(new ReflectAndRetryToolPlugin(3)));
Both hooks are already declared on Plugin, and both already return the type the plugin needs —
Maybe<Map<String, Object>>, matching Python's Optional[dict[str, Any]]:
// Plugin.java:188
default Maybe<Map<String, Object>> afterToolCallback(
BaseTool tool, Map<String, Object> toolArgs, ToolContext toolContext, Map<String, Object> result)
// Plugin.java:206
default Maybe<Map<String, Object>> onToolErrorCallback(
BaseTool tool, Map<String, Object> toolArgs, ToolContext toolContext, Throwable error)
The class is written and tested; the PR carries it.
Additional Context
Observed on 1.7.1-SNAPSHOT, Windows 11 (not OS-specific).
- Dominant language
- Java
- Stars
- 1.7k
- Forks
- 433
- Avg merge
- 3d 11h
- Merged PRs (30d)
- 50
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from google/adk-java
-
GeminiUtil placeholder user turn ("Continue output. DO NOT look at this line ...") is flagged by prompt injection filtersPossibly taken @hemasekhar-p claimed this 1 day ago. Openneeds review
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
google/adk-java#1628 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
[spring-ai] ToolConverter silently drops enum and items from tool parameter schemasPossibly taken @hirematha claimed this 3 days ago. Openneeds review
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
google/adk-java#1609 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
[spring-ai] Streaming responses ending with CJK punctuation (。!?) are misclassified as partial and never persisted to the sessionPossibly taken @hirematha claimed this 3 days ago. Openneeds review
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
google/adk-java#1608 · 3 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
Claude model throws UnsupportedOperationException("Not supported yet.") on thinking blocks from Claude 5 modelsPossibly taken @hemasekhar-p claimed this 1 day ago. Openneeds review
google/adk-java#1630 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
[core] Client disconnects don't cancel the model stream (per-step flow is cached) — and there is no public API to cancel an in-flight runPossibly taken @hemasekhar-p claimed this 3 days ago. Openneeds review
google/adk-java#1618 · 6 comments · 1 assignee ·
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
PCL-Community/PCL-CE#3658 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Team/Identity Server Core Type/Improvement U2
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
wso2/product-is#28553 ·
Maintainers usually reply within 1 day
-
frontend
Difficulty 1/5 Under an hour Newbie friendliness 72/100
Paul-Austin-Oswego-CSC480-HCI521/gift-app#116 ·
Maintainers usually reply within 2 days
-
dependencies java
Difficulty 1/5 Under an hour Newbie friendliness 62/100
micrometer-metrics/tracing#1588 ·
Maintainers usually reply within 1 day