Skip to content

feat: Build support for external plugins#172

Draft
patricka3125 wants to merge 14 commits intoawslabs:mainfrom
patricka3125:feat/cao-plugin
Draft

feat: Build support for external plugins#172
patricka3125 wants to merge 14 commits intoawslabs:mainfrom
patricka3125:feat/cao-plugin

Conversation

@patricka3125
Copy link
Copy Markdown
Contributor

@patricka3125 patricka3125 commented Apr 13, 2026

Overview

Adds a plugin and hook system to CAO that lets external packages attach arbitrary async code to CAO lifecycle events — session/terminal state changes and multi-agent communication — without modifying CAO internals. Plugins are discovered via Python entry points (cao.plugins group) and loaded at cao-server startup.

Addresses #171.

Motivation

Users need to integrate CAO with external tools (chat apps, dashboards, alerting, observability) and monitor multi-agent workflow health, but today there is no supported extension point. This change introduces a first-class plugin surface so third-party packages can subscribe to events like post_send_message, post_create_session, or post_kill_terminal and react however they choose — full Python power, no new hard dependencies on CAO's side.

Key Changes

File Change
src/cli_agent_orchestrator/plugins/__init__.py New package public API — exports CaoPlugin, hook, PluginRegistry, and all event dataclasses
src/cli_agent_orchestrator/plugins/base.py New CaoPlugin base class with setup()/teardown() lifecycle and @hook decorator for marking async event handlers
src/cli_agent_orchestrator/plugins/events.py New typed event dataclasses (CaoEvent base + PostSendMessageEvent, PostCreateSessionEvent, PostKillSessionEvent, PostCreateTerminalEvent, PostKillTerminalEvent)
src/cli_agent_orchestrator/plugins/registry.py New PluginRegistry — entry-point discovery, instantiation, dispatch table, fire-and-forget async dispatch with error isolation, teardown
src/cli_agent_orchestrator/api/main.py Wire PluginRegistry into the FastAPI lifespan: load on startup, attach to app.state, teardown on shutdown
src/cli_agent_orchestrator/services/plugin_dispatch.py New dispatch adapter used by services to emit events without hard-coupling to the registry
src/cli_agent_orchestrator/services/session_service.py Emit PostCreateSessionEvent / PostKillSessionEvent after successful session lifecycle operations
src/cli_agent_orchestrator/services/terminal_service.py Emit PostCreateTerminalEvent / PostKillTerminalEvent after successful terminal lifecycle operations
src/cli_agent_orchestrator/services/inbox_service.py Emit PostSendMessageEvent after successful inbox delivery, with orchestration_type set to send_message, handoff, or assign
src/cli_agent_orchestrator/mcp_server/server.py Thread orchestration type from handoff / assign / send_message MCP tools into the inbox delivery path so the correct orchestration_type flows into PostSendMessageEvent
src/cli_agent_orchestrator/models/inbox.py Add fields needed to carry sender/orchestration context through to event emission
test/plugins/test_base.py Unit tests for CaoPlugin default lifecycle and @hook decorator behavior
test/plugins/test_events.py Unit tests for event dataclass defaults, event_type literals, and UTC timestamp auto-population
test/plugins/test_registry.py Unit tests covering registry discovery, dispatch, multi-plugin fan-out, error isolation in setup/dispatch/teardown, non-CaoPlugin entry points, and empty dispatch
test/plugins/test_package.py Smoke test asserting all public API symbols are importable from cli_agent_orchestrator.plugins
test/api/test_plugin_lifespan.py Integration tests asserting PluginRegistry is loaded/torn down by the FastAPI lifespan and exposed on app.state
test/services/test_plugin_dispatch.py Unit tests for the service-layer dispatch adapter
test/services/test_plugin_event_emission.py Unit tests asserting session/terminal/inbox services dispatch the correct event types and fields on success, and do NOT dispatch on failure paths
test/api/test_api_endpoints.py, test/api/test_terminals.py, test/api/conftest.py, test/mcp_server/test_assign.py, test/mcp_server/test_handoff.py, test/services/test_inbox_service.py Updates to accommodate the new registry dependency and orchestration-type threading

Test Plan

  • uv run pytest test/plugins/ -v passes
  • uv run pytest test/api/test_plugin_lifespan.py -v passes
  • uv run pytest test/services/test_plugin_event_emission.py test/services/test_plugin_dispatch.py -v passes
  • Full unit suite green: uv run pytest test/ --ignore=test/e2e --ignore=test/providers/test_q_cli_integration.py -v
  • uv run black src/ test/ and uv run isort src/ test/ clean
  • uv run mypy src/ passes under strict mode
  • Manual: start cao-server with no plugins installed → "No CAO plugins registered" info log appears, server starts cleanly
  • Manual: install a sample plugin declaring a cao.plugins entry point, start cao-server, trigger a session create / terminal create / send_message / handoff / assign, and verify the plugin's hooks fire with correctly populated events

@patricka3125 patricka3125 marked this pull request as draft April 13, 2026 12:25
@haofeif haofeif added the enhancement New feature or request label Apr 14, 2026
@patricka3125
Copy link
Copy Markdown
Contributor Author

going to add a example discord plugin, some documentation on plugin integration instructions, and a skill for steering plugin development.

) -> Dict:
try:
success = terminal_service.send_input(terminal_id, message)
if sender_id is None or orchestration_type is None:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this guard is redundant

* Add Discord plugin scaffold

* Tidy Discord plugin scaffold artifacts

* Add Discord plugin lifecycle config

* Broaden development report ignore pattern

* Complete Discord plugin webhook forwarding

* gitignore

* remove mention of design in readme
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants