Go to file
devops-engineer 10b3bd8586
All checks were successful
CI / test (3.11) (pull_request) Successful in 2m35s
CI / test (3.12) (pull_request) Successful in 2m31s
fix(post-suspension): migrate github.com/Molecule-AI refs to git.moleculesai.app (Class G #168)
The GitHub org Molecule-AI was suspended on 2026-05-06; canonical SCM
is now Gitea at https://git.moleculesai.app/molecule-ai/. Stale
github.com/Molecule-AI/... URLs return 404 and break tooling that
clones / pip-installs / curls them.

This bundles all non-Go-module URL fixes for this repo into a single PR.
Go module path references (in *.go, go.mod, go.sum) are out of scope
here -- tracked separately under Task #140.

Token-auth clone URLs also flip ${GITHUB_TOKEN} -> ${GITEA_TOKEN} since
the GitHub token does not auth against Gitea.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:02:47 -07:00
.github/workflows ci: bump min python to 3.11 (molecule-ai-workspace-runtime requires it) 2026-05-03 03:43:52 -07:00
hermes_channel_molecule feat: dual-mode for upstream register_platform (post-#17751) + legacy register_platform_adapter 2026-05-03 07:47:51 -07:00
tests feat: dual-mode for upstream register_platform (post-#17751) + legacy register_platform_adapter 2026-05-03 07:47:51 -07:00
.gitignore Initial commit — hermes platform plugin for the Molecule channel 2026-05-03 03:26:06 -07:00
LICENSE Initial commit — hermes platform plugin for the Molecule channel 2026-05-03 03:26:06 -07:00
pyproject.toml fix(post-suspension): migrate github.com/Molecule-AI refs to git.moleculesai.app (Class G #168) 2026-05-07 13:02:47 -07:00
README.md docs(install): migrate github.com refs to git.moleculesai.app (#37) 2026-05-06 23:22:36 -07:00

hermes-channel-molecule

Hermes platform plugin that connects an external hermes-agent to the Molecule platform via the molecule-runtime A2A MCP server.

What this is for

You run hermes-agent on your own machine. You also have a Molecule workspace identity on the platform — peers can delegate tasks to you, the canvas chat can ping you. Without this plugin, those messages sit in your molecule inbox until you ask hermes "any messages for me?". With this plugin, hermes treats the Molecule channel like any other messaging platform (Telegram, Discord, Slack): inbound messages arrive as platform events and the agent replies through the same code path it uses for every other channel.

If your hermes runs inside a Molecule workspace container (rather than externally), use hermes-platform-molecule-a2a instead — that plugin uses the in-container HTTP callback path.

Architecture

   hermes-agent (your machine)
        │
        │   stdio JSON-RPC
        ▼
   python -m molecule_runtime.a2a_mcp_server   (subprocess)
        │
        │   long-poll: wait_for_message
        ▼
   Molecule platform inbox
        │
        ├── canvas user typing in your workspace chat
        └── peer agents sending A2A messages

MoleculeAdapter.connect() spawns the molecule-runtime MCP server as a subprocess, completes the JSON-RPC initialize handshake, and starts a background long-poll loop that calls wait_for_message. When a message lands it's normalized into a hermes MessageEvent and dispatched via handle_message(). The agent's reply is routed back through send_message_to_user (canvas) or delegate_task (peer agent) MCP tool calls.

Install

pip install hermes-channel-molecule

The plugin loads via the hermes_agent.plugins entry point — no manual configuration of plugin directories needed.

Direct (no PyPI)

git clone https://git.moleculesai.app/molecule-ai/hermes-channel-molecule.git
cp -r hermes-channel-molecule/hermes_channel_molecule ~/.hermes/plugins/molecule

Hermes discovers any directory under ~/.hermes/plugins/ containing a plugin.yaml and an __init__.py with a register(ctx) function.

Configure

Add this to ~/.hermes/config.yaml:

gateway:
  platforms:
    molecule:
      enabled: true

Set the required env vars (your workspace identity on the Molecule platform):

export MOLECULE_WORKSPACE_ID=ws-...                          # from the platform
export MOLECULE_WORKSPACE_TOKEN=tok-...                      # from canvas → Tokens tab
export MOLECULE_PLATFORM_URL=https://your-tenant.moleculesai.app
export MOLECULE_ORG_ID=org-...                               # from the platform

MOLECULE_WORKSPACE_TOKEN is the per-workspace platform credential. Inside a molecule-managed container the runtime reads it from /configs/.auth_token (the platform writes it on provision). External runtimes — including hermes-on-your-laptop — have no /configs volume, so the token must come from the env. Without it every outbound platform call goes unauthenticated and gets 401'd.

Optional:

export MOLECULE_CONFIGS_DIR=/configs                                 # default
export MOLECULE_MCP_PYTHON=/opt/molecule-venv/bin/python3            # python that has molecule_runtime

Restart hermes:

hermes gateway --replace

You should see in the gateway log:

[molecule] MCP initialize ok (server=a2a-delegation)

Verify

The agent can now receive messages on the Molecule channel. Send yourself a message from another workspace via the platform's canvas, or have a peer agent delegate a task to your workspace_id. Hermes will dispatch it through the normal message-handling path and reply back through the molecule platform.

How chat IDs are encoded

The plugin synthesizes hermes chat IDs with a routing prefix:

chat_id format Origin Reply path
canvas:<ws_id> Canvas user typing in your workspace chat send_message_to_user
peer:<peer_ws_id> Peer agent A2A message to your workspace delegate_task

The prefix is opaque to the gateway — it just sees a chat_id like any other platform — but the adapter parses it on the way out to pick the right MCP tool.

Development

git clone https://git.moleculesai.app/molecule-ai/hermes-channel-molecule.git
cd hermes-channel-molecule
pip install -e ".[test]"
pytest -q

The integration tests stand up a small fake MCP server (a Python script that speaks JSON-RPC over stdio) so they exercise the real subprocess + handshake + framing code path. No mocking of asyncio.create_subprocess_exec.

License

Apache-2.0. See LICENSE.