google / google/adk-java

Feature Request: Run Cancellation / Abort Support for Java ADK

Abierto
#1,341 2 comentarios 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

## Summary

Java ADK currently lacks a mechanism to cancel/abort a running agent invocation. TypeScript ADK already ships mature `AbortSignal`-based cancellation ([docs/runtime/cancel.md](https://google.github.io/adk-docs/runtime/cancel/)), and Python ADK has active work in progress (google/adk-python#4825, google/adk-python#5983). **Java ADK has no equivalent — no API, no internal checkpoints, and no graceful shutdown path.**

## Motivation

Cancellation is essential for production agent deployments:

- **User-facing "Stop" button** — long-running multi-tool loops need immediate, graceful termination when the user clicks stop.
- **Timeout enforcement** — server-side request deadlines (e.g., HTTP gateway timeouts) must propagate into the agent execution.
- **Resource cleanup** — without cooperative cancellation, in-flight LLM streaming connections and tool executions leak resources.
- **Cost control** — aborting early avoids unnecessary LLM token consumption.

## Current State

| Language | Status | Mechanism |
|----------|--------|-----------|
| **TypeScript** | ✅ Shipped | `runner.runAsync(params, { signal })` with `AbortSignal`; checkpoints in LLM call, tool execution, and plugin callbacks; graceful generator completion (no throw) |
| **Python** | 🚧 In progress | google/adk-python#4825 (`stop_event: asyncio.Event`), google/adk-python#5983 (`/cancel` API + `task.cancel()`) |
| **Java** | ❌ Missing | Only `InvocationContext.endInvocation` (internal flag, not externally triggerable); `Disposable.dispose()` is a hard RxJava cut (not graceful, tools don't check it); no `RunConfig` timeout/cancel field |

## Proposed Design (aligned with TypeScript)

### API Surface

```java
// Option A: CancellationToken (similar to .NET / structured concurrency)
CancellationTokenSource cts = new CancellationTokenSource();
RunConfig config = RunConfig.builder()
.cancellationToken(cts.token())
.build();

Flowable events = runner.runAsync(userId, sessionId, content, config);
// Later:
cts.cancel(); // triggers graceful shutdown

// Option B: RxJava-native (Disposable already exists, but needs cooperative checks)
// Enhance internal checkpoints to check subscription disposal state
```

### Internal Checkpoints (minimum)

Following TypeScript's lead, cancellation should be checked at:

1. **Before each LLM call** — `BaseLlmFlow.runOneStep()` (already checks `endInvocation`, easy to extend)
2. **Before each tool execution** — `Functions.handleFunctionCalls()` (**currently has NO cancellation check**)
3. **During LLM streaming** — between chunks (for long generations)
4. **Plugin/callback boundaries** — `beforeModel` / `afterModel` / `beforeTool` / `afterTool`

### Semantics (align with TypeScript `cancel.md`)

- **Graceful**: the Flowable completes normally (no error signal), already-emitted events are preserved in the session.
- **Cooperative**: cancellation is checked at defined points; in-flight atomic operations (single LLM call, single tool run) may complete before the next checkpoint.
- **Idempotent**: calling cancel multiple times is safe.

## Questions for Maintainers

1. **API preference**: `CancellationToken` (explicit, testable) vs. leveraging RxJava `Disposable` semantics (less new API surface but less portable)?
2. **Scope**: Should cancellation also cover `runLive` (streaming/live mode), or start with `runAsync` only?
3. **Event emission on cancel**: Should the framework emit a final "cancelled" event (like Python's `temp:cancelled` state proposal), or just complete silently (like TypeScript)?

## References

- TypeScript ADK cancel docs: https://google.github.io/adk-docs/runtime/cancel/
- Python ADK cancellation PR: google/adk-python#4825
- Python ADK `/cancel` API PR: google/adk-python#5983
- Python ADK cancellation discussion: google/adk-python#4156

---

I'm happy to contribute the implementation once the API direction is agreed upon. I have production experience implementing cooperative cancellation in a Java ADK-based agent platform (checkpoint-based, with checks at beforeModel/beforeTool/afterEvent boundaries).

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.