Summary
execute_parallel (executor.py:187-203) runs async tools via asyncio.gather sharing the same ToolContext contextvar. Unlike sync tools (which get a contextvars.copy_context()), async tools all operate on the same ToolContext object.
Race Conditions
current_tool_call_id: Set at line 69/140 before each execution — whichever tool runs last wins. PendingMemoryOps created by concurrent tools may reference the wrong tool call ID.
memory_modified: _check_memory_modified (line 255-263) reads the flag and resets it to False. If tool A sets it and tool B's check clears it before tool A's result is processed, the memory refresh callback is skipped.
Fix
For parallel async execution, either:
- Scope
current_tool_call_id per-call (pass it as an argument rather than via ToolContext)
- Create a context copy for each async tool invocation
- Track
memory_modified per-result rather than via shared mutable state
Files
apps/server/src/anima_server/services/agent/executor.py:187-203, 206-252
Severity
Medium — incorrect tool call ID attribution and missed memory refreshes under parallel tool execution.
Summary
execute_parallel(executor.py:187-203) runs async tools viaasyncio.gathersharing the sameToolContextcontextvar. Unlike sync tools (which get acontextvars.copy_context()), async tools all operate on the sameToolContextobject.Race Conditions
current_tool_call_id: Set at line 69/140 before each execution — whichever tool runs last wins. PendingMemoryOps created by concurrent tools may reference the wrong tool call ID.memory_modified:_check_memory_modified(line 255-263) reads the flag and resets it toFalse. If tool A sets it and tool B's check clears it before tool A's result is processed, the memory refresh callback is skipped.Fix
For parallel async execution, either:
current_tool_call_idper-call (pass it as an argument rather than via ToolContext)memory_modifiedper-result rather than via shared mutable stateFiles
apps/server/src/anima_server/services/agent/executor.py:187-203, 206-252Severity
Medium — incorrect tool call ID attribution and missed memory refreshes under parallel tool execution.