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
- Add RED catalog/metadata tests for all four namespaced plugins.
- Add RED valid/invalid resolver and schema tests per plugin.
- Add RED port execution, normalized failure, and idempotency tests.
- Implement ports, default adapters, and flat definitions without touching generic orchestration.
- Verify both
dual_agent and chat_agent_tools receive the same schemas/results for the built-ins.
- 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