feat: concurrent mode — per-chat turn serialization + parallel tool execution#320
Merged
feat: concurrent mode — per-chat turn serialization + parallel tool execution#320
Conversation
…allel tool execution Addresses #307 by adding two core concurrency features: 1. ChatTurnQueue: Universal per-chat turn serialization that ensures at most one agent run per (channel, chat_id) at a time. Messages arriving during an active run are queued and coalesced. Replaces ad-hoc per-channel locks in Slack, Feishu, and Matrix. Adds missing per-chat locking to Telegram and Discord. Configurable via chat_turn_serialization, chat_turn_queue_strategy, and chat_turn_queue_max_pending. 2. ParallelToolExecutor: When parallel_tool_execution is enabled, tool calls from a single LLM response are partitioned into execution waves based on ToolConcurrencyClass (ReadOnly/SideEffect/Exclusive). ReadOnly tools run concurrently via futures::join_all, SideEffect tools run sequentially, Exclusive tools run alone. Defaults to off (sequential, identical to current behavior). Key changes: - New src/chat_turn_queue.rs with ChatTurnQueue, TurnGuard, PendingMessage - New src/tool_executor.rs with wave partitioning and parallel execution - New ToolConcurrencyClass enum in microclaw-tools - Extracted ~360-line tool execution loop from agent_engine.rs into tool_executor - New AgentEvent variants: ToolWaveStart, ToolWaveComplete - 6 new config fields for concurrency control - No database migrations required — all new state is in-memory Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The coverage CI job (--all-features -Dwarnings) caught this unused import after removing the ad-hoc matrix_chat_lock in favor of ChatTurnQueue. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…config Remove `chat_turn_serialization` and `chat_turn_queue_strategy` config fields. Turn serialization is now a built-in capability that is always enabled with the queue_then_rerun strategy hardcoded. Only `chat_turn_queue_max_pending` remains as a configurable safety limit. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Parallel tool execution is now a built-in core capability, always on. The `parallel_tool_execution` config field is removed. Only `parallel_tool_max_concurrency` and `tool_concurrency_overrides` remain as tuning knobs. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…r_enqueue The previous two-step pattern (enqueue_if_busy then acquire) had a race window: rapid messages could all pass enqueue_if_busy before the first message acquired the lock, causing all messages to serialize through acquire() instead of being properly queued. New try_start_or_enqueue() atomically either starts a turn (returns guard) or queues the message (returns None), eliminating the race. Channel adapters now pass the pre-acquired TurnGuard into the agent engine via process_with_agent_with_events_guarded(). Also promoted queue log messages from debug to info level for visibility. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Addresses #307 — moves MicroClaw toward a concurrent, non-blocking architecture.
Per-Chat Turn Serialization (
ChatTurnQueue): Universal per-chat lock ensuring at most one agent run per (channel, chat_id) at a time. Messages arriving during an active run are queued and coalesced via configurable strategy (queue_then_rerun/queue_only). Replaces ad-hocCHAT_LOCKSstatics in Slack, Feishu, and Matrix. Adds missing per-chat serialization to Telegram and Discord (which previously had none — causing session race conditions).Parallel Tool Execution (
ParallelToolExecutor): Whenparallel_tool_execution: true, tool calls from a single LLM response are partitioned into execution waves byToolConcurrencyClass:futures::join_allKey files
src/chat_turn_queue.rssrc/tool_executor.rscrates/microclaw-tools/src/runtime.rssrc/agent_engine.rssrc/channels/*.rssrc/config.rsConfig
No database migrations needed
All new state is in-memory only.
Test plan
cargo build— zero errors, zero warningscargo clippy -- -D warnings— cleancargo test -q— all tests pass (including 8 new ChatTurnQueue tests + 6 partition tests)parallel_tool_execution: true, ask bot to read 3 files → verify parallel execution in logs🤖 Generated with Claude Code