Runner drops callbackContextData written in onUserMessageCallback when it resumes an invocation
維護者通常 1 天內回覆
評估
研究方向
閱讀 Runner 實作中的 runResumedAgent、resumeCore 和 runAgentWithUpdatedSession。追蹤 initialContext 的建立方式及其如何傳遞給回呼,然後比較恢復路徑與新呼叫路徑。啟用可恢復功能,並使用一個在 onUserMessageCallback 中儲存資料的外掛程式來重現;當恢復後的 agent 回呼能看到這些資料,且現有的恢復行為由回歸測試涵蓋時,即為完成。
由索引模型根據 Issue 內容生成。
描述
Please make sure you read the contribution guide and file the issues in the right place.
Contribution guide.
🔴 Required Information
Describe the Bug
InvocationContext.callbackContextData() is "a map for storing temporary context data that can be shared
between different parts of the invocation", and InvocationContext.Builder passes the same instance to every
copy "so that Plugins can access the same data … across all types of callbacks."
A new invocation keeps that promise. runNewInvocation runs onUserMessageCallback on initialContext, and
runAgentWithUpdatedSession builds the agent's context with initialContext.toBuilder(), so the map is shared.
A resumed invocation does not. resumeCore runs onUserMessageCallback on its own initialContext, but
runResumedAgent is not given that context and builds the agent's from a second builder:
// runResumedAgent
InvocationContext rootContext =
newInvocationContextBuilder(session, rootAgent)
.invocationId(resolvedInvocationId)
.runConfig(runConfig)
.userContent(userContentFor(session, resolvedInvocationId, userContent))
.build();
newInvocationContextBuilder starts a new, empty callbackContextData, so whatever a plugin stored in
onUserMessageCallback is missing from beforeRunCallback and from every callback that runs with the agent.
The same builder also resets endInvocation: a plugin that ends the invocation in onUserMessageCallback stops
a new invocation, but a resumed one still calls the model. On every resume, onRunErrorCallback also runs on
initialContext, so it does not see what beforeRunCallback stored, even when no new message is sent.
Trigger: resumability enabled and an invocation paused (for example on a long-running tool) that is then
resumed, with or without a new message. New invocations are unaffected.
Steps to Reproduce
- A
RunnerwithResumabilityConfig.builder().resumable(true), anLlmAgentwith a long-running tool, and a
plugin whoseonUserMessageCallbackputs a value intoinvocationContext.callbackContextData()and whose
beforeAgentCallbackreads it back. - Send a message. The model calls the tool and the invocation pauses.
- Send the tool's function response, which resumes the invocation.
Expected Behavior
On the resumed turn, beforeAgentCallback reads the value that turn's onUserMessageCallback stored, as it
does on the first turn.
Observed Behavior
The first turn reads its value, and the resumed turn reads null (the plugin stores message-1, then
message-2). beforeAgentCallback reads, per turn:
[agent:message-1, agent:null]
The same happens when the resume is routed to a sub-agent instead of the root.
Environment Details
- ADK Library Version:
main@84bae34a(pom 1.13.0) - OS: not OS-specific
- TS Version: N/A (Java)
Model Information
N/A
🟡 Optional Information
Regression
No. Present since resuming an invocation was added (v1.11.0).
Willingness to contribute
Yes, a PR follows. runResumedAgent takes initialContext and builds the agent's context with
initialContext.toBuilder(), as runAgentWithUpdatedSession does:
InvocationContext rootContext =
initialContext.toBuilder()
.agent(rootAgent)
.userContent(...)
.build();
How often has this issue occurred?
Always (100%), on a resumed invocation.
- 主要語言
- Java
- 星號
- 1.8k
- 分支
- 440
- 平均合併
- 3 天 22 小時
- 30 天內合併 PR
- 88
環境準備
在瀏覽器裡用你自己的 GitHub 帳號啟動這個專案的開發容器。
- 沒有 Dockerfile 或 Docker Compose 檔案
- 有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
google/adk-java 的其他 Issue
-
InMemorySessionService.appendEvent recreates a deleted session可能已有人在做 @hirematha 於 3 天前認領。 未關閉needs review
難度 2/5 1-3 小時 新手友好度 84/100
google/adk-java#1697 · 2 則留言 · 已指派 1 人 ·
維護者通常 1 天內回覆
-
[spring-ai] Streaming responses ending with CJK punctuation (。!?) are misclassified as partial and never persisted to the session可能已有人在做 @hirematha 於 24 天前認領。 未關閉needs review
難度 2/5 1-3 小時 新手友好度 84/100
google/adk-java#1608 · 3 則留言 · 已指派 1 人 ·
維護者通常 1 天內回覆
-
AgentExecutor ignores the A2A contextId when creating a session, so multi-turn conversations start over every turn可能已有人在做 @hirematha 於 1 天前認領。 未關閉needs review
google/adk-java#1718 · 2 則留言 · 已指派 1 人 ·
維護者通常 1 天內回覆
-
McpToolset hangs silently for ~5 minutes per retry (3 retries) when stdio command is an npm shim ("npx") on Windows可能已有人在做 @hemasekhar-p 於 7 天前認領。 未關閉needs review
google/adk-java#1686 · 4 則留言 · 已指派 1 人 ·
維護者通常 1 天內回覆
-
runLive passes partial events to appendEvent and never aggregates text chunks, unlike ADK Python可能已有人在做 @hemasekhar-p 於 17 天前認領。 未關閉needs review
難度 4/5 3-5 天 新手友好度 45/100
google/adk-java#1648 · 3 則留言 · 已指派 1 人 ·
維護者通常 1 天內回覆
相似的 Issue
-
難度 2/5 1-3 小時 新手友好度 76/100
oracle/graalvm-reachability-metadata#11472 ·
維護者通常 1 天內回覆
-
難度 1/5 1 小時以內 新手友好度 89/100
objectionary/hone-maven-plugin#1353 ·
維護者通常 9 天內回覆
-
難度 2/5 1-3 小時 新手友好度 88/100
維護者通常 1 天內回覆
-
Update samples to Citrus 5.1.0可能已有人在做 @asuruceanu 今天認領。 未關閉
難度 2/5 1-3 小時 新手友好度 82/100
-
難度 2/5 1-3 小時 新手友好度 78/100
維護者通常 1 天內回覆