Status: in_progress
Add a backend-selectable comparison between the existing fast-reply dual_agent path and a chat_agent_tools path where ChatAgent receives provider tools directly, while both modes use the same registry, schemas, handlers, event budget, and externally visible tool results.
tool_invocation_mode to DebugRunRequest, defaulting to dual_agent for backward compatibility.dual_agent keeps the existing compact text-event prompt, EventAgent queue, deterministic-first resolution, optional LLM fallback, and summary follow-up.chat_agent_tools sends the enabled registry schemas to ChatAgent, consumes only provider_tool_call, executes those calls through the shared EventKernel with PROVIDER_RESOLVED, and continues with a valid assistant/tool provider transcript.tool_calls followed immediately by matching tool messages before the next ChatAgent request.max_event_loops; after budget exhaustion, send no tools and ignore further provider tool calls.run() and reusable session/turn runtime paths.dual_agent; dual mode must continue to ignore provider tool calls.src/agent_lab/application/contracts.pysrc/agent_lab/application/runtime.pytests/test_debug_runtime.pytests/test_websocket_api.pysrc/agent_lab/application/tools.py only if an enabled-name provider execution facade is needed to avoid Runtime reaching into registry internals.dual_agent, assert ChatAgent receives tools=[], receives compact event instructions, ignores provider_tool_call, and continues through EventAgent summary exactly as before.chat_agent_tools, assert ChatAgent receives exactly the enabled schemas and no compact text-event system block.event output/audit records with full provider arguments.tool_calls.enabled_names; create ordered tool replies with matching IDs, emit tool_result, append them to active history, and continue ChatAgent.assistant(tool_calls) followed by all matching tool replies.tools=[] after max_event_loops is reached.tool_invocation_mode in session config and relevant round/request audit details.Compare both paths against the same fake registry and scenarios. Confirm the architectural difference is limited to model/tool orchestration, not schemas, handlers, results, or event budget.
46.x rows for any post-commit correction.UV_CACHE_DIR=.uv-cache uv run pytest tests/test_debug_runtime.py tests/test_websocket_api.py -qUV_CACHE_DIR=.uv-cache uv run pytestUV_CACHE_DIR=.uv-cache uv run python -c "from agent_lab.main import app; print(app.title)"git diff --check