Skip to content

fix(adk): fix concurrent compile race in ChatModelAgent#775

Merged
N3kox merged 1 commit intoalpha/08from
fix/chatmodel_compile
Feb 6, 2026
Merged

fix(adk): fix concurrent compile race in ChatModelAgent#775
N3kox merged 1 commit intoalpha/08from
fix/chatmodel_compile

Conversation

@shentongmartin
Copy link
Contributor

Summary

Problem Solution
Data race when multiple requests call chain.Compile() concurrently on shared chain/graph instances in ChatModelAgent Move chain and inner graph creation inside closures so each request has its own instance

Problem

In ChatModelAgent, both buildNoToolsRunFunc and buildReactRunFunc create a shared chain (and inner graph g for react) outside the closure, then call chain.Compile() inside. When multiple requests execute concurrently, they race on:

  1. chain.addEndIfNeeded() - modifies hasEnd flag
  2. graph.compile() - modifies internal state like compiled, handlerPreNode
  3. For react: innerGraph.compile() - nested graph also gets compiled with races

Solution

Create chain and inner graph per request inside the closure:

// Before (race condition)
g, err := newReact(ctx, conf)  // shared
chain := NewChain[...]().AppendGraph(g)  // shared
return func(...) {
    runnable, _ := chain.Compile(...)  // RACE
}

// After (safe)
return func(...) {
    g, err := newReact(ctx, conf)  // per request
    chain := NewChain[...]().AppendGraph(g)  // per request
    runnable, _ := chain.Compile(...)  // safe
}

Key Insight

Neither Chain nor Graph in the compose package supports concurrent Compile() calls on the same instance. The compile operation modifies internal state without synchronization. Creating instances per request is the safe pattern when each request may have different compile options (like WithCheckPointStore(store)).


概述

问题 解决方案
多个请求并发调用共享 chain/graph 实例的 chain.Compile() 时存在数据竞争 将 chain 和内部 graph 的创建移入闭包内,使每个请求拥有独立实例

问题

ChatModelAgent 中,buildNoToolsRunFuncbuildReactRunFunc 都在闭包外创建共享的 chain(react 模式还有内部 graph g),然后在闭包内调用 chain.Compile()。当多个请求并发执行时,会在以下位置产生竞争:

  1. chain.addEndIfNeeded() - 修改 hasEnd 标志
  2. graph.compile() - 修改内部状态如 compiledhandlerPreNode
  3. React 模式:innerGraph.compile() - 嵌套的 graph 也会被编译并产生竞争

解决方案

在闭包内为每个请求创建 chain 和内部 graph。

关键洞察

compose 包中的 ChainGraph 都不支持在同一实例上并发调用 Compile()。编译操作会修改内部状态而没有同步机制。当每个请求可能有不同的编译选项时(如 WithCheckPointStore(store)),为每个请求创建新实例是安全的模式。

Move chain and inner graph creation inside closures to avoid data races
when multiple requests call Compile() concurrently on shared instances.

Changes:
- buildNoToolsRunFunc: create chain per request instead of sharing
- buildReactRunFunc: create both inner graph (g) and chain per request

Change-Id: I9a44697675c892ac7658909010b72d3a2718c25a
@codecov
Copy link

codecov bot commented Feb 6, 2026

Codecov Report

❌ Patch coverage is 68.18182% with 7 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (alpha/08@f887fed). Learn more about missing BASE report.

Files with missing lines Patch % Lines
adk/chatmodel.go 68.18% 4 Missing and 3 partials ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             alpha/08     #775   +/-   ##
===========================================
  Coverage            ?   79.79%           
===========================================
  Files               ?      146           
  Lines               ?    15844           
  Branches            ?        0           
===========================================
  Hits                ?    12642           
  Misses              ?     2218           
  Partials            ?      984           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@N3kox N3kox merged commit 13ae5b9 into alpha/08 Feb 6, 2026
16 checks passed
@N3kox N3kox deleted the fix/chatmodel_compile branch February 6, 2026 11:17
hi-pender pushed a commit that referenced this pull request Feb 14, 2026
Move chain and inner graph creation inside closures to avoid data races
when multiple requests call Compile() concurrently on shared instances.

Changes:
- buildNoToolsRunFunc: create chain per request instead of sharing
- buildReactRunFunc: create both inner graph (g) and chain per request

Change-Id: I9a44697675c892ac7658909010b72d3a2718c25a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants