Skip to content

fix(adk): avoid racing on shared react config when concurrent Run reuses one ChatModelAgent - #1218

Open
GerardGao wants to merge 1 commit into
cloudwego:mainfrom
GerardGao:fix/issue-1177-adk-react-config-race
Open

fix(adk): avoid racing on shared react config when concurrent Run reuses one ChatModelAgent#1218
GerardGao wants to merge 1 commit into
cloudwego:mainfrom
GerardGao:fix/issue-1177-adk-react-config-race

Conversation

@GerardGao

Copy link
Copy Markdown

What

buildMessageReActRunFunc and buildAgenticReActRunFunc build the react config
(reactConfig / agenticReactConfig) once per agent and then write the per-run
cancel scope into it on every Run:

msgConf.cancelCtx = cancelCtx
msgConf.modelWrapperConf.cancelContext = cancelCtx

When one long-lived ChatModelAgent is reused across concurrent Run calls
(e.g. a multi-tenant gateway), these writes race with newReact /
newAgenticReact reading the same fields, and two runs can observe each other's
cancel pointer — so a plain run can be cancelled by another run's cancel scope.
Fixes #1177.

How

Inside the run closure, shallow-copy the once-built config before assigning the
cancel fields and hand the copy to newReact / newAgenticReact:

runConf := *msgConf
if msgConf.modelWrapperConf != nil {
    mw := *msgConf.modelWrapperConf
    mw.cancelContext = cancelCtx
    runConf.modelWrapperConf = &mw
}
runConf.cancelCtx = cancelCtx
g, err := newReact(ctx, &runConf)

All other fields are read-only after construction, and buildModelWrappers
snapshots the wrapper config fields at build time, so a struct copy is
sufficient. The per-run cancel injection points (ReAct cancel safe-points, model
wrapper stack, graph interrupt wiring) are preserved unchanged.

Tests

  • New TestConcurrentRunSharedAgentWithTools_Race: 4 concurrent runs on one
    shared agent with a start barrier. Fails reliably under go test -race
    before this change and passes after.
  • go test -race ./adk/ passes; golangci-lint run ./adk/... reports 0 issues.

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.

adk: data race on shared reactConfig.cancelCtx when concurrent Run reuses one ChatModelAgent (tools/ReAct path)

1 participant