Skip to content

[OMEGA-161][OMEGA-205] Add plugin API to universally load any kind of plugins, add existing communication channels and LLM providers as plugins#222

Merged
vsbogd merged 26 commits into
asi-alliance:mainfrom
vsbogd:plugin-api
Jul 16, 2026
Merged

[OMEGA-161][OMEGA-205] Add plugin API to universally load any kind of plugins, add existing communication channels and LLM providers as plugins#222
vsbogd merged 26 commits into
asi-alliance:mainfrom
vsbogd:plugin-api

Conversation

@vsbogd

@vsbogd vsbogd commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Description

Plugin API is introduced to allow writing any kind of plugins which are uniformly loaded and registered inside OmegaClaw agent. This PR replaces #169

The API can be found inside src/pluginapi.py. At the moment it contains communication channel and LLM provider APIs. Skills to be added later in a separate PR. Supporting both MeTTa and Python plugins are planned but this PR implements only Python API because all of the plugins we already have are written in Python.

Python plugins can be loaded as a single Python path anywhere in the file-system or any Python module within the PYTHONPATH. To uniformly load them the config/plugins.yaml file is introduced because Python modules cannot be found in specific locations and should be listed explicitly. It can be overridden by the user in the specific deployments. The only required exported function in the plugin is loadOmegaClawPlugin() which should use src/pluginapi.py to register all necessary callbacks.

All existing communication channels and LLM providers are represented as plugins and listed in the config/plugins.yaml. Both communication channel and LLM provider plugins gets the list of OmegaClaw command line parameters on configuration step in order to extract necessary information from them.

New model parameter is added to LLM providers which allows user overriding the model used by specifying model=<model-name> command line parameter. New openaiapi_url command line parameter is added to allow specifying the URL of the LLM API endpoint. This makes Ollama-local provider unnecessary and it is replaced by universal OpenAIAPI provider.

How Has This Been Tested?

Run docker using each communication channel.
Run docker using each LLM provider.
Run docker using OpenAIAPI LLM provider specifying claude-opus-4-8 as a model and https://api.anthropic.com/v1/ as openaiapi_url.
Ask What is the distance to the Sun? in each run.

Checklist

  • The code generated by LLM is reviewed by the PR creator
  • Self-review completed
  • Test scenarios above are passed with the version of the code from PR

@vsbogd vsbogd changed the title [OMEGA-161][OMEGA-205] Add plugin API to universally load any kind of plugins, add existing communication channels and LLM providers as plugins [WIP][OMEGA-161][OMEGA-205] Add plugin API to universally load any kind of plugins, add existing communication channels and LLM providers as plugins Jul 1, 2026
@vsbogd
vsbogd marked this pull request as ready for review July 1, 2026 13:17
@vsbogd
vsbogd requested review from blackhammer116, jazzbox35 and patham9 and removed request for patham9 July 1, 2026 13:17
@vsbogd vsbogd changed the title [WIP][OMEGA-161][OMEGA-205] Add plugin API to universally load any kind of plugins, add existing communication channels and LLM providers as plugins [OMEGA-161][OMEGA-205] Add plugin API to universally load any kind of plugins, add existing communication channels and LLM providers as plugins Jul 1, 2026

@blackhammer116 blackhammer116 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Its a fairly nice implementation overall, but I highly recommend to move the plugin code from src to another dir like config. The src directory should only contain code that is directly related to the core functionality of OmegaClaw like the main loop, memory management, channels interface... and not a plugin config script

@vsbogd

vsbogd commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

The src directory should only contain code that is directly related to the core functionality of OmegaClaw like the main loop, memory management, channels interface... and not a plugin config script

Being able loading and calling plugins is a core OmegaClaw functionality as all LLM and communication channel integrations are implemented via this mechanism. Thus I don't understand why it should be moved into a separate directory.

@TossSky

TossSky commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Tested OMEGA-161.

What I checked (works):

  • plugins load from config on start, all channels and providers register
  • a new channel/provider can be added via plugins.yaml + a plugin file, no core changes
  • broken / duplicate / incomplete plugin config fails start with a clear error
  • channels work: IRC, test, Slack, websocket and Telegram
  • providers invoked through the plugin path; model and endpoint overrides work

Blocking:

  • CI Phase 1 (run_mandatory) is red on mock_websocket/test_wschat_unit.py: ModuleNotFoundError: No module named 'pluginapi'

These unit tests import channels/wschat.py directly (in-process, no container). This PR adds a module-level import pluginapi as plugin (wschat.py:64), so importing the module now needs pluginapi on the path, which run_mandatory doesn't provide. The tests existed and passed on main before the plugin refactor. Guarding the import fixes it with no test changes (the 6 unit tests pass again). Inline suggestion on line 64.

Not merge-ready until run_mandatory is green.

Comment thread channels/wschat.py Outdated
@vsbogd

vsbogd commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

Not merge-ready until run_mandatory is green.

Thanks @TossSky I applied the change you suggested. I think we should find a proper way to run unit tests with using production like environment.

Comment thread src/plugin.py
print(f"_initPythonPlugin: loading {name} plugin from {location} using Python module loader")
spec = importlib.util.spec_from_file_location(name, location)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@vsbogd
Sorry, the wschat quickfix wasn't enough, CI is still red, on a different failure now. After the recent main merges the channels also import auth (channels/auth.py) and the plugin loader doesn't put the plugin's directory or the repo root on sys.path, so plugins that import a sibling or Autotests.mock.* fail at startup and the agent never becomes ready (ModuleNotFoundError: No module named 'auth').

Adding the plugin dir and repo root to sys.path in _initPythonPlugin before exec_module fixes it.

Verified: agent starts and run_mandatory is green (49 passed).

Suggested change
spec.loader.exec_module(mod)
import sys
for _extra in (str(location.parent), str(_REPO)):
if _extra not in sys.path:
sys.path.insert(0, _extra)
spec.loader.exec_module(mod)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Import of the Python module in PeTTa changes the sys.path. Thus moving websearch.py from channels to src changed the sys.path contents which led to the plugin code unable importing the module from `channels.

It would be logical to add plugin location into the sys.path thus I implemented it as a fix in 1823c3f

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

After rebase this fix is included into the first commit.

@vsbogd

vsbogd commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

Have to rebase it because of conflicts in lib_llm_ext.py which was difficult to merge otherwise.

vsbogd added 10 commits July 10, 2026 19:27
Any extension is module which implements loadOmegaClawPlugin function
and uses pluginapi module to register callbacks and intervene to the
agents working loop. In this commit IRC plugin is added which registers
IRC communication channel callbacks which are used by the agent to
communicate via IRC.
The plugin adds integration with Anthropic, ASICloud, Ollama-local and
any other endpoint which is reachable via OpenAI API and doesn't
requires specific processing.
"model" parameter can be used to override OpenRouter provider model.
vsbogd and others added 2 commits July 10, 2026 19:27
Unit test imports wschat in environment which doesn't include the pluginapi module. This commit is a quickfix for the issue.

Co-authored-by: TossSky <v.totski@etorn.ee>
Comment thread channels/irc.py Outdated
Comment thread providers/asione.py
Comment thread providers/openaiapi.py
@vsbogd

vsbogd commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Fixed incorrect logger imports (thanks @besSveta) 35da8f9
Fixed OpenAIAPI Nginx forwarding URL (thanks @mvpeterson) e068e53

@vsbogd
vsbogd requested a review from blackhammer116 July 14, 2026 10:38
@blackhammer116

Copy link
Copy Markdown
Collaborator

The src directory should only contain code that is directly related to the core functionality of OmegaClaw like the main loop, memory management, channels interface... and not a plugin config script

Being able loading and calling plugins is a core OmegaClaw functionality as all LLM and communication channel integrations are implemented via this mechanism. Thus I don't understand why it should be moved into a separate directory.

Well, before, the channel adapters were in a separate dir (as well as the LLM handler) because they where, in a way, configs. and since the plugin is doing the same, but in a more modular and optimal way, that's why I suggested moving it out of the dir. But it's not a hard blocker the code can be cleaned once functionality has been achived

@vsbogd

vsbogd commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator Author

the channel adapters were in a separate dir (as well as the LLM handler) because they where, in a way, configs. and since the plugin is doing the same, but in a more modular and optimal way, that's why I suggested moving it out of the dir

If you are talking about plugin.metta and pluginapi.metta files they are not configs. They are the part of the OmegaClaw-Core which allows adding new functionality. To continue your analogy:

  • the channels and providers are out of src because they are loaded dynamically, and they still out of `src.
  • but configure function which manages the configuration is part of src because it is a function which allows configuring OmegaClaw. Without it OmegaClaw is not configurable; the same with plugin.metta and pluginapi.metta without them OmegaClaw cannot be extended

blackhammer116
blackhammer116 previously approved these changes Jul 15, 2026
@vsbogd

vsbogd commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author

@blackhammer116 @TossSky I have found that asking for a model after selecting provider in the scripts/omegaclaw contradicts to the previous flow habits when key was pasted just after selecting provider. If user is used to the previous flow the he pastes key instead of selecting model.

If you don't mind, I will change the order. It should be one-liner which should not trigger the full retesting of code I believe. What do you think?

@TossSky

TossSky commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

@vsbogd
Fine by me. It only touches the interactive config wizard, not the -p/-t/-m/-u
flags I tested through, so it won't invalidate the results. Just run
scripts/omegaclaw config once after to confirm provider/model/openaiapi_url/token
still land in the right keys. No full retest needed.

The plugin refactor never ported the WebSocket channel, so -t websocket
crashed at startup with "Communication channel plugin websocket is not
registered".

- channels/wschat.py: add WSChannel(CommChannel) and loadOmegaClawPlugin()
  registering it as "websocket"; config() passes WS_URL/WS_TOKEN into the
  existing start_websocket.
- config/plugins.yaml: list wschat so the loader imports it.
- import pluginapi by its bare name so the registration lands in the registry
  the loader reads, with src.pluginapi as fallback for the in-process unit test.
@TossSky

TossSky commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Tested OMEGA-161. One failure:

  • -t websocket crashes at startup:
    RuntimeError: commChannelConfig: Communication channel plugin websocket is not registered
    wschat was never ported to the plugin API and is not listed in plugins.yaml,
    while the help and the launch script still offer the channel. It worked before
    the refactor.

Fix: vsbogd#6
Tested with the fix applied: test_wschat_unit.py 6 passed, -t websocket starts and
registers the channel, mock_websocket e2e 7 passed, run_mandatory 49 passed.

Everything else passed.
@vsbogd

[OMEGA-161] Register websocket channel as a plugin
@vsbogd

vsbogd commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author
  • -t websocket crashes at startup:

Thanks applied your fix, looks like my implementation was lost during rebase.

It only touches the interactive config wizard, not the -p/-t/-m/-u
flags I tested through, so it won't invalidate the results. Just run

Thanks for the fast response, I will do this then.

Return order of actions which is more aligned with previous user
experience.
@vsbogd

vsbogd commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author

@TossSky I have tested interactive part of the ./scripts/omegaclaw the command line parameters flow is not changed.

@TossSky

TossSky commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Retested. All passed.

@vsbogd
vsbogd merged commit 4a1439c into asi-alliance:main Jul 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants