Problem
Two independent concurrency control systems exist that are completely unaware of each other:
System A: Execution Queue (for /api/chat)
- File:
services/execution_queue.py
- Serial execution (1 at a time per agent)
- Redis keys:
agent:running:{name}, agent:queue:{name}
- Max 3 queued requests
- 600s TTL
System B: Slot Service (for /api/task, scheduler, public, paid)
- File:
services/slot_service.py
- Parallel execution (1-10 concurrent per agent)
- Redis keys:
agent:slots:{name}, agent:slot:{name}:{exec_id}
- 1800s TTL
Impact
- A
/chat execution occupies the queue but NOT a slot → capacity meter doesn't show it
- A
/task execution occupies a slot but NOT the queue → queue doesn't know about it
- An agent could have 1 chat + 10 tasks running simultaneously (11 total) while capacity shows 10/10
- No single system gives a true picture of agent load
Required Changes
Option A (Recommended): SlotService becomes the single source of truth
/api/chat acquires a slot in addition to using the queue
- Capacity meter shows ALL execution types
- Queue continues to enforce serial chat, but slot tracks the resource usage
- Total capacity = max_parallel_tasks (shared between chat and tasks)
Option B: Merge into one system
- Replace both with a unified
ExecutionManager
- Supports both serial (chat) and parallel (task) modes per agent
- Single Redis key namespace
- Single capacity counter
Files to Change
src/backend/services/execution_queue.py — Integrate with SlotService
src/backend/services/slot_service.py — Accept queue-based executions
src/backend/routers/chat.py — Acquire slot alongside queue
src/frontend/src/components/CapacityMeter.vue — May need to show queue vs task breakdown
Problem
Two independent concurrency control systems exist that are completely unaware of each other:
System A: Execution Queue (for
/api/chat)services/execution_queue.pyagent:running:{name},agent:queue:{name}System B: Slot Service (for
/api/task, scheduler, public, paid)services/slot_service.pyagent:slots:{name},agent:slot:{name}:{exec_id}Impact
/chatexecution occupies the queue but NOT a slot → capacity meter doesn't show it/taskexecution occupies a slot but NOT the queue → queue doesn't know about itRequired Changes
Option A (Recommended): SlotService becomes the single source of truth
/api/chatacquires a slot in addition to using the queueOption B: Merge into one system
ExecutionManagerFiles to Change
src/backend/services/execution_queue.py— Integrate with SlotServicesrc/backend/services/slot_service.py— Accept queue-based executionssrc/backend/routers/chat.py— Acquire slot alongside queuesrc/frontend/src/components/CapacityMeter.vue— May need to show queue vs task breakdown