This repository is a Python Agent Lab for debugging chat and event agents. The source package lives under src/agent_lab/:
domain/: message and event models shared across the app.application/: runtime orchestration, request/response contracts, and EventAgent tool handling.infrastructure/: OpenAI Chat Completions compatible streaming client and parser integration.presentation/: FastAPI routes, WebSocket endpoint, and static debug UI under presentation/static/.settings.py: pydantic-settings configuration.Tests live in tests/, planning docs in docs/plans/, and the manual WebSocket smoke helper in scripts/ws_smoke.py.
uv sync: install runtime and dev dependencies from pyproject.toml and uv.lock.uv run pytest: run the full test suite.uv run uvicorn agent_lab.main:app --reload: start the FastAPI debug console locally.uv run python scripts/ws_smoke.py --help: inspect the WebSocket smoke-test CLI.uv run python -c "from agent_lab.main import app; print(app.title)": verify app import wiring.Use Python 3.11+ with type hints on public boundaries. Keep DDD layers separate: domain types should not depend on FastAPI or HTTP clients, application code should coordinate use cases, and infrastructure should own provider-specific I/O. Prefer small dataclasses or Pydantic models for exchanged data. Use snake_case for modules, functions, fields, and environment variables.
Use pytest and pytest-asyncio. Add focused tests beside the behavior being changed, using names like test_openai_stream_parser.py or test_websocket_api.py. Runtime and WebSocket tests should use mocked clients unless a task explicitly requires a live LLM smoke.
Configuration comes from Settings in src/agent_lab/settings.py with the AGENT_LAB_ prefix and optional local .env. Do not commit secrets. The app exposes GET /health, GET /, and WebSocket /ws/debug; keep WebSocket payloads aligned with application/contracts.py.
Keep commits scoped to one todo or behavior change. PRs should summarize user-visible behavior, list verification commands, mention config changes, and include screenshots only when UI layout changes.