todo-9-explicit-runtime-queues.md 3.1 KB

Todo 9 Explicit Runtime Queues Plan

Status: done

Result

Implemented by subagent and committed as b2bba51 Add explicit runtime queues.

Main-session verification:

uv run pytest tests/test_debug_runtime.py
uv run pytest

Results:

  • runtime queue tests: 5 passed in 0.06s
  • full suite: 19 passed, 1 warning in 0.25s

Goal

Refactor the runtime internals to use explicit input, output, and event queues while preserving the existing WebSocket stream contract.

Why

The MVP works, but the original requirement describes three data-exchange channels:

  • input queue: WebSocket/user input and EventAgent replies feed ChatAgent;
  • output queue: ChatAgent stream output feeds WebSocket downlink;
  • event queue: ChatAgent events feed EventAgent.

The current DebugRuntime.run() performs these steps directly. This todo introduces the queue structure now, without changing HTTP/WebSocket payloads.

Scope

This todo covers:

  • Runtime-local asyncio.Queue objects for input, output, and events.
  • A small queue/session abstraction in the application layer.
  • Tests proving queue ownership and order.
  • Keeping DebugRuntime.run() as the public async generator consumed by FastAPI.

This todo does not cover:

  • Redis/NATS/external queues.
  • Multiple concurrent browser sessions beyond one runtime instance per WebSocket request.
  • Tool registry changes.
  • UI changes.

Files

  • Create: src/agent_lab/application/queues.py
  • Modify: src/agent_lab/application/runtime.py
  • Modify/add tests, preferably tests/test_debug_runtime.py.
  • Do not modify: docs/plans/todos.md.

Design

Add a RuntimeQueues dataclass:

@dataclass
class RuntimeQueues:
    input: asyncio.Queue[ChatMessage]
    output: asyncio.Queue[dict[str, Any]]
    events: asyncio.Queue[ToolCallEvent]

DebugRuntime.run() should:

  1. Build initial conversation from system prompts and pre-messages.
  2. Put the current user message on input.
  3. Drain input into conversation before each ChatAgent call.
  4. Stream ChatAgent items into output.
  5. Put tool-call events on events.
  6. Let EventAgent consume events and put tool replies back on input.
  7. Yield only from output so the WebSocket contract stays unchanged.

Keep the implementation single-process and deterministic. Use sentinel-free sequential draining for this MVP; do not introduce background tasks unless needed by the tests.

Steps

  1. Add failing tests for:
    • runtime exposes or injects RuntimeQueues;
    • tool-call events are put on the event queue before EventAgent replies return to the input queue;
    • yielded output message order remains unchanged from current tests.
  2. Implement RuntimeQueues.
  3. Refactor DebugRuntime.run() to use the queues internally.
  4. Run:

    uv run pytest tests/test_debug_runtime.py
    uv run pytest
    
  5. Evaluate whether Todo 10 still starts with tool registry management or should be adjusted based on the queue abstraction.

Verification

Expected result:

  • Existing WebSocket/runtime behavior remains compatible.
  • Tests prove all three queues are part of the runtime flow.
  • Full suite passes.