Feature Request: Run Cancellation / Abort Support for Java ADK
Maintainers usually reply within 1 day
@hemasekhar-p is already working on this.
Since Jul 9, 2026.
Assessment
This issue has not been assessed yet.
Description
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), 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
// Option A: CancellationToken (similar to .NET / structured concurrency)
CancellationTokenSource cts = new CancellationTokenSource();
RunConfig config = RunConfig.builder()
.cancellationToken(cts.token())
.build();
Flowable<Event> 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:
- Before each LLM call —
BaseLlmFlow.runOneStep()(already checksendInvocation, easy to extend) - Before each tool execution —
Functions.handleFunctionCalls()(currently has NO cancellation check) - During LLM streaming — between chunks (for long generations)
- 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
- API preference:
CancellationToken(explicit, testable) vs. leveraging RxJavaDisposablesemantics (less new API surface but less portable)? - Scope: Should cancellation also cover
runLive(streaming/live mode), or start withrunAsynconly? - Event emission on cancel: Should the framework emit a final "cancelled" event (like Python's
temp:cancelledstate 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
/cancelAPI 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).
- Dominant language
- Java
- Stars
- 1.7k
- Forks
- 433
- Avg merge
- 3d 9h
- Merged PRs (30d)
- 46
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 2 days 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 5 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 5 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
-
FirestoreSessionService loses event fields on reload, breaking later turns and tool confirmationsPossibly taken @innoprej claimed this today. Open
Difficulty 4/5 3-5 days Newbie friendliness 22/100
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 2 days ago. Openneeds review
google/adk-java#1630 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
Similar issues
-
`Processing lsp` never exits and leaves orphaned processesPossibly taken @overcast302 claimed this today. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
processing/processing4#1578 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 60/100
Maintainers usually reply within 1 day
-
[BUG] S3 CORS responses omit Access-Control-Allow-Credentials for matched originsPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
floci-io/floci#5369 · 1 comment ·
Maintainers usually reply within 1 day
-
securityHeaders replaces a route's own Content-Security-Policy (0.9.9; weakens embedders' pages)Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
sqlcipher/sqlcipher-android#97 · 1 comment ·