google / google/adk-java

[FEATURE] Port ReflectAndRetryToolPlugin from adk-python

Abierto
#1,390 1 comentario 0 reacciones 1 asignado Reclamado por @hemasekhar-p Ver en GitHub
needs review
Lenguaje dominante
Java
Estrellas
1.7k
Forks
420
Merge medio
4 d 12 h
PR fusionados (30 d)
31

Descripción

**Please make sure you read the contribution guide and file the issues in the right place.**
[Contribution guide.](https://google.github.io/adk-docs/contributing-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` —
`onToolErrorCallback` for a tool that signals an error, and `afterToolCallback` for 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
to `maxRetries`;
- 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 `TrackingScope` enum.

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:

```java
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>`, matching Python's `Optional[dict[str, Any]]`:

```java
// Plugin.java:188
default Maybe> afterToolCallback(
BaseTool tool, Map toolArgs, ToolContext toolContext, Map result)

// Plugin.java:206
default Maybe> onToolErrorCallback(
BaseTool tool, Map 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).

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.