feat: Build support for external plugins#172
Draft
patricka3125 wants to merge 14 commits intoawslabs:mainfrom
Draft
feat: Build support for external plugins#172patricka3125 wants to merge 14 commits intoawslabs:mainfrom
patricka3125 wants to merge 14 commits intoawslabs:mainfrom
Conversation
patricka3125
commented
Apr 13, 2026
patricka3125
commented
Apr 15, 2026
patricka3125
commented
Apr 15, 2026
Contributor
Author
|
going to add a example discord plugin, some documentation on plugin integration instructions, and a skill for steering plugin development. |
patricka3125
commented
Apr 15, 2026
| ) -> Dict: | ||
| try: | ||
| success = terminal_service.send_input(terminal_id, message) | ||
| if sender_id is None or orchestration_type is None: |
Contributor
Author
There was a problem hiding this comment.
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.pluginsgroup) and loaded atcao-serverstartup.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, orpost_kill_terminaland react however they choose — full Python power, no new hard dependencies on CAO's side.Key Changes
src/cli_agent_orchestrator/plugins/__init__.pyCaoPlugin,hook,PluginRegistry, and all event dataclassessrc/cli_agent_orchestrator/plugins/base.pyCaoPluginbase class withsetup()/teardown()lifecycle and@hookdecorator for marking async event handlerssrc/cli_agent_orchestrator/plugins/events.pyCaoEventbase +PostSendMessageEvent,PostCreateSessionEvent,PostKillSessionEvent,PostCreateTerminalEvent,PostKillTerminalEvent)src/cli_agent_orchestrator/plugins/registry.pyPluginRegistry— entry-point discovery, instantiation, dispatch table, fire-and-forget async dispatch with error isolation, teardownsrc/cli_agent_orchestrator/api/main.pyPluginRegistryinto the FastAPI lifespan: load on startup, attach toapp.state, teardown on shutdownsrc/cli_agent_orchestrator/services/plugin_dispatch.pysrc/cli_agent_orchestrator/services/session_service.pyPostCreateSessionEvent/PostKillSessionEventafter successful session lifecycle operationssrc/cli_agent_orchestrator/services/terminal_service.pyPostCreateTerminalEvent/PostKillTerminalEventafter successful terminal lifecycle operationssrc/cli_agent_orchestrator/services/inbox_service.pyPostSendMessageEventafter successful inbox delivery, withorchestration_typeset tosend_message,handoff, orassignsrc/cli_agent_orchestrator/mcp_server/server.pyhandoff/assign/send_messageMCP tools into the inbox delivery path so the correctorchestration_typeflows intoPostSendMessageEventsrc/cli_agent_orchestrator/models/inbox.pytest/plugins/test_base.pyCaoPlugindefault lifecycle and@hookdecorator behaviortest/plugins/test_events.pyevent_typeliterals, and UTC timestamp auto-populationtest/plugins/test_registry.pysetup/dispatch/teardown, non-CaoPluginentry points, and empty dispatchtest/plugins/test_package.pycli_agent_orchestrator.pluginstest/api/test_plugin_lifespan.pyPluginRegistryis loaded/torn down by the FastAPI lifespan and exposed onapp.statetest/services/test_plugin_dispatch.pytest/services/test_plugin_event_emission.pytest/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.pyTest Plan
uv run pytest test/plugins/ -vpassesuv run pytest test/api/test_plugin_lifespan.py -vpassesuv run pytest test/services/test_plugin_event_emission.py test/services/test_plugin_dispatch.py -vpassesuv run pytest test/ --ignore=test/e2e --ignore=test/providers/test_q_cli_integration.py -vuv run black src/ test/anduv run isort src/ test/cleanuv run mypy src/passes under strict modecao-serverwith no plugins installed → "No CAO plugins registered" info log appears, server starts cleanlycao.pluginsentry point, startcao-server, trigger a session create / terminal create /send_message/handoff/assign, and verify the plugin's hooks fire with correctly populated events