# Todo 47 Built-in Event Plugins Plan **Status:** done ## Result Added four flat namespaced built-in plugins with injectable session, device, calendar, and search ports plus deterministic in-memory adapters. The default registry preserves the original lab tools and exposes the new definitions to both invocation modes. Final full verification: `313 passed`, one existing warning. ## Review Update The initial plugin implementation remains open pending Todo 47.1 corrections for shared deterministic normalization, strict calendar/query validation, safe volume parsing, and adapter idempotency scope. ## Goal Add four namespaced built-in plugins on the generic event kernel without introducing event-name branches in Runtime or the kernel: - `session.terminate` - `device.volume.adjust` - `calendar.schedule.create` - `knowledge.web.search` ## Architecture - Keep the registry flat. - Each plugin definition owns its name, concise description, JSON Schema, deterministic resolver, fallback policy, handler adapter, result/confirmation/risk policy, idempotency metadata, concurrency/conflict metadata, timeout, and terminal flag. - Put production side effects behind injectable application ports. The lab default uses deterministic in-memory/mock adapters; `mituan-service` integration remains a separate repository task. - `build_default_tool_registry()` includes the four plugins while preserving existing lab mock tools. - Both invocation modes discover and execute the same definitions automatically through the existing registry/kernel. ## Plugin Contracts ### `session.terminate` - Arguments: optional `reason` string. - Deterministic, no LLM fallback required. - Port: dialogue/session termination boundary, keyed by event ID. - Policy: `TERMINATE`, high risk, terminal, serialized against session lifecycle work. - Default adapter returns a normalized terminated result and is idempotent by event ID. ### `device.volume.adjust` - Arguments: - `mode`: `absolute`, `relative`, `mute`, or `unmute`; - `value`: integer `0..100` for absolute; - `delta`: integer `-100..100`, excluding zero, for relative. - JSON Schema enforces mode-specific required/forbidden fields. - Deterministic resolver recognizes clear Chinese/English mute, unmute, absolute, and signed relative requests; incomplete requests remain eligible for EventAgent fallback. - Port: device-action dispatcher boundary, keyed by event ID. - Policy: `SILENT_SUCCESS`, medium risk, device-volume conflict class. - Invalid/out-of-range/ambiguous requests never call the port. ### `calendar.schedule.create` - Arguments: `title`, RFC3339 `start_at`, IANA-style `timezone`, optional `recurrence`, optional non-negative `reminder_minutes`. - Deterministic resolver accepts already structured arguments and explicit ISO/RFC3339 details only; it must not guess relative or ambiguous natural-language times. - Missing/ambiguous fields can use the existing EventAgent LLM fallback in dual mode. - Port: calendar/reminder application boundary with event-ID idempotency. - Policy: `TEMPLATE_FOLLOW_UP`, medium risk, schedule-write concurrency class. - Default adapter deduplicates repeated event IDs and returns normalized confirmation data. ### `knowledge.web.search` - Arguments: focused non-empty `query`, optional `max_results` from `1..5`. - Deterministic resolver derives the latest relevant user request when provider arguments are absent. - Port: external-search adapter returning a stable compact result contract. - Policy: `LLM_FOLLOW_UP`, low risk, read-only concurrency class. - Default adapter returns deterministic mock sources with retrieval metadata; no network or credentials. ## Scope - Add plugin definitions and injectable ports/default adapters. - Register plugins in the default registry and expose them from the existing tools API/catalog. - Add focused schema, resolver, metadata, execution, failure, idempotency, and mode-parity tests. - Preserve existing `handoff_note`, `mock_search`, and `mock_ticket` lab tools. ## Boundaries - Do not implement real MQTT/device commands, calendar storage, session shutdown, or internet search. - Do not add name-specific branches to Runtime, EventAgent, EventKernel, or provider parsers. - Do not implement bounded batch scheduling, terminal barriers, result-policy aggregation, or two-answer runtime behavior here; those are Todo 48. - Do not guess schedule relative times without an explicit clock/timezone context. ## Files - Add: `src/agent_lab/application/events/builtin_plugins.py` - Modify: `src/agent_lab/application/events/__init__.py` - Modify: `src/agent_lab/application/tools.py` - Add: `tests/test_builtin_event_plugins.py` - Modify: `tests/test_websocket_api.py` only for default tools catalog coverage if needed. ## Requirement Execution Loop ### Plan 1. Add RED catalog/metadata tests for all four namespaced plugins. 2. Add RED valid/invalid resolver and schema tests per plugin. 3. Add RED port execution, normalized failure, and idempotency tests. 4. Implement ports, default adapters, and flat definitions without touching generic orchestration. 5. Verify both `dual_agent` and `chat_agent_tools` receive the same schemas/results for the built-ins. 6. Run focused/full verification and independent reviews. ### Observe / Update Record any plugin contract ambiguity as a `47.x` todo. Mark complete only when adding these plugins requires no Runtime/kernel event-name conditionals and all external actions remain behind ports. ## Verification - `UV_CACHE_DIR=.uv-cache uv run pytest tests/test_builtin_event_plugins.py tests/test_event_agent.py tests/test_debug_runtime.py -q` - `UV_CACHE_DIR=.uv-cache uv run pytest` - `UV_CACHE_DIR=.uv-cache uv run python -c "from agent_lab.application.tools import build_default_tool_registry; print([x['name'] for x in build_default_tool_registry().available_tools()])"` - `git diff --check`