Connect to your bot
Let your bot (OpenClaw, Hermes, Grok Bot, dot from OpenAI, OpenBot, MausBot, nanobot and others) drive Elyra, and have Elyra notify it when an agent finishes.
A bot is an assistant that stays up all the time and talks to you through chat, your phone or a messenger: OpenClaw, Hermes, Grok Bot, dot from OpenAI, OpenBot, MausBot, nanobot and others. This page shows how to connect it to Elyra in two directions:
- The bot drives Elyra: it opens cards, sends tasks to agents, reads terminals and files.
- Elyra notifies the bot: when an agent finishes, Elyra calls an address of the bot, and it tells you.
Each section has a ready-made prompt. Copy it, paste it into your bot and it does the setup for you. Where the setup depends on the bot, the prompt asks it to follow its own documentation.
What the bot can do in Elyra
Once connected, the bot uses the same tools as the Cloud connector, which act with your permissions on the computer where Elyra runs:
elyra: runs the Elyra CLI: projects, workspaces, Canvas cards, terminals, agents, the embedded browser and automations;shell,read_file,write_file,edit_file,list_dirandsearch: commands and files;screenshotandbrowser_screenshot: show what Elyra or a page displays (on the Cloud, with a link to the image);list_skillsandread_skill: the manuals of the Elyra skills.
The full table is in Connect outside agents through MCP.
Security. The bot acts as you, without asking for confirmation at each step. Connect only bots you trust and revoke access when you no longer need it (see Security).
Pick a path
| Where the bot runs | Path | Needs |
|---|---|---|
| On the same computer as Elyra | elyra mcp, over stdio |
Elyra open |
| On another machine (server, cloud, phone) | Cloud MCP with OAuth | Elyra Cloud on |
Bot on the same computer: elyra mcp
elyra mcp is an MCP server over stdio: the bot starts it as a subprocess and talks to it in lines of
JSON. It forwards each request to the open Elyra on this computer, with the same tools as the Cloud
connector. No tunnel, no Cloud and no sign-in.
The configuration, in any MCP client that accepts a server started by a command, is:
{ "mcpServers": { "elyra": { "command": "elyra", "args": ["mcp"] } }}The key names and the file it goes in change from bot to bot: use the format its documentation asks for and
keep the elyra command with the mcp argument.
Things to watch:
- Elyra must be open. With the app closed, each request comes back with an error telling you to open
Elyra, and
elyra mcpstays up for the next request. - The bot must find the executable. If it cannot find
elyra, put the full path incommand. To find it, runcommand -v elyra(macOS and Linux) orGet-Command elyra(PowerShell). - The bot and Elyra must be on the same computer, under the same system user. A bot inside a container or a server cannot reach the Elyra on your computer: for that case, use the Cloud path.
- What
elyra mcpprints to standard output is only the MCP protocol; warnings and errors go tostderr.
MausBot: MausBot works with the Claude Code and Codex on your
computer. Register elyra mcp in them, and MausBot can drive Elyra:
claude mcp add --scope user elyra -- elyra mcpcodex mcp add elyra -- elyra mcpPrompt for your bot:
Set up an MCP server named "elyra" with the command `elyra mcp` (stdio transport). If the `elyra` command isnot found, use the full path of the executable. Then list the server's tools and call the `elyra` tool withthe arguments `workspace list` to confirm it worked. Use your own MCP documentation to find where to registerthe server; do not make up commands.Bot on another machine: the Cloud MCP
When the bot does not run on your computer, it reaches Elyra through the Cloud connector: an address
https://<your-user>-cloud.elyra.sh/mcp, with OAuth sign-in. You approve the connection once and access
renews itself; no fixed key to copy. The step by step, the consent screen and revocation are in
Connect outside agents through MCP; they are not repeated here.
The connector answers with JSON over HTTP (POST), without SSE. A bot that only speaks the old SSE
transport cannot connect.
Where to register the server in each bot:
| Bot | Where to register the remote server |
|---|---|
| Grok Bot | Setup → Plugins, Remote HTTPS server with OAuth (source) |
| dot, from OpenAI | Plugins → + → Add custom MCP server, for personal use, without review (source) |
| OpenClaw | Settings → MCP, in the control panel (Control UI), with HTTP transport and OAuth sign-in (source) |
| Hermes | hermes mcp add --url <address> --auth oauth elyra and then hermes mcp test elyra (source) |
| nanobot | Apps → MCP → Connect, with auth set to oauth (source) |
Each flow ends on a page of your Cloud, where you sign in with your Elyra account and tap Allow. If the bot runs on a server without a browser, the sign-in has to come back to the bot’s machine (through port forwarding, for example); the bot’s documentation explains how.
Prompt for your bot:
Add the remote MCP server https://<my-user>-cloud.elyra.sh/mcp with OAuth authentication and send me thesign-in link so I can authorize it. Follow your own MCP documentation to do this; do not make up commands.Once I have authorized it, list the server's tools and call the `elyra` tool with the arguments`workspace list` to confirm.Notify the bot: the “Call URL” action
For the bot to know that an agent finished (or is waiting for you, or CI failed), Elyra makes an HTTP call to the address the bot publishes. This is the Call URL action of the automations.
Create it on screen
- Open Automations and use Create automation.
- Under when, pick the event, for example an agent finishes.
- Under do this, pick Call URL and fill in:
- Method:
GET,POST,PUT,PATCHorDELETE; - Address (URL): the bot’s address, with the query if any;
- Headers: name/value pairs;
- Body: only for methods that carry a body. The default is a JSON with the event;
- Sign with a secret: turns on the signature (see below).
- Method:
- Create automation.
Event variables
The URL and the body accept these variables, written between double braces:
| Variable | What it carries |
|---|---|
{{trigger}} |
The event that fired, such as agent-finished, agent-waiting or card-message; manual when you run the automation by hand; otherwise, the trigger type |
{{agent}} |
For an Elyra event that comes from a card (agent finished, agent waiting, card message), that card’s agent, when Elyra knows it; otherwise, the automation’s agent |
{{card}} |
For those events, the title of the card that fired; otherwise, the run title |
{{project}} |
The project name |
{{time}} |
The time, in ISO 8601 |
{{summary}} |
GitHub, GitLab or webhook event: event, repository, title and address, whatever comes. Elyra event with a card: the event and the card title (agent-finished · PR reviewer). Otherwise, empty |
In the URL the values go in encoded; in the body they go in escaped for JSON. The default body is:
{ "trigger": "{{trigger}}", "agent": "{{agent}}", "card": "{{card}}", "project": "{{project}}", "time": "{{time}}", "summary": "{{summary}}"}And the bot receives, for example:
{ "trigger": "agent-finished", "agent": "claude", "card": "PR reviewer", "project": "my-app", "time": "2026-10-18T14:03:00.000Z", "summary": "agent-finished · PR reviewer"}Signature
With Sign with a secret on, every call carries the header:
X-Elyra-Signature-256: sha256=<HMAC-SHA256, in hexadecimal, of the exact body, with the secret as the key>It is the same format as the incoming webhook. The secret is generated by Elyra and stored encrypted in the system vault, like the webhook’s:
- Save the automation and open its details.
- In the Call URL signature section, tap Generate secret and copy it right away: it is shown only once. If you lose it, use Rotate secret.
- Give the secret to the bot.
The receiver checks the signature over the exact bytes of the body. In Node.js:
import { createHmac, timingSafeEqual } from 'node:crypto'
function signatureMatches(rawBody, header, secret) { const expected = createHmac('sha256', secret).update(rawBody).digest() if (!/^sha256=[0-9a-f]{64}$/i.test(header ?? '')) return false const received = Buffer.from(header.slice(7), 'hex') return received.length === expected.length && timingSafeEqual(received, expected)}Without the signature turned on, Elyra does not prove who called: use it only on an address you control and that accepts nothing from strangers.
What happens on the call
- 10-second deadline and no resend. If the bot is down, Elyra keeps no queue.
- The call leaves your computer, and local (
localhost) and internal-network addresses are accepted. That is how a bot on the same machine, such as the OpenClaw gateway, gets notified. Only use URLs you trust. - Only a 2xx answer counts as success. The run history shows
HTTP 200 · 120 ms. Any other answer, a connection error or the deadline running out fails the action and stops the chain, with the reason in the history; on screen, the failure also shows up in a notice. - Elyra does not follow redirects: a
3xxcounts as a failure, so the signed body is never resent to another address. - The secret and headers do not go to logs, and the action summary shows only the server, never the query.
- The header values are saved with the automation. Prefer the signature over a fixed token in a header.
Example: notify OpenBot
OpenBot runs a local server on port 4132 and takes events on
POST /api/publish. An an agent finishes → Call URL automation with these fields sends the notice straight
to it:
- Method:
POST; - Address (URL):
http://localhost:4132/api/publish; - Headers:
content-type=application/json; - Body:
{ "type": "agent:invoke", "data": { "role": "user", "content": "Agent {{agent}} finished on card {{card}} in project {{project}}. Let me know." }}Create it from the command line
The bot can also create the automation, through the elyra tool, with --actions. The signing secret,
however, is only generated in the app, in the automation details:
elyra automations create --name "Notify the bot" \ --trigger-json '{"kind":"elyra-event","events":["agent-finished"]}' \ --actions '[{"kind":"http-call","method":"POST","url":"https://bot.example.com/elyra","headers":[],"body":"{\"card\":\"{{card}}\"}","sign":true}]' \ --trigger daily --prompt "Event notice" --provider codex --repo <project>Prompt for your bot:
I want you to receive notices from Elyra. Publish an HTTP POST address (or tell me which of your addresses touse) and, when a notice arrives, check the X-Elyra-Signature-256 header: it is "sha256=" plus thehexadecimal HMAC-SHA256 of the exact body, using as the key the secret I will give you. If the signature doesnot match, ignore the notice. If it matches, the body is a JSON with trigger, agent, card, project, time andsummary: tell me in the chat what happened. Answer 200 to Elyra within 10 seconds. Once the address exists,create in Elyra, with the `elyra` tool, the automation "an agent finishes → Call URL" (method POST, thataddress, signature on) and tell me so I can generate the secret in the automation details.Skills in the bots’ folders
The Elyra skills are short manuals that teach the agent to use the CLI. Elyra installs them by itself in the skills folders of the assistants that are already on your computer, and that now includes OpenClaw:
| Bot | Folder |
|---|---|
| OpenClaw | ~/.openclaw/skills (or <OPENCLAW_STATE_DIR>/skills, if you moved the state folder) |
| Hermes | Hermes’s skills folder (~/.hermes/skills, %LOCALAPPDATA%\hermes\skills on Windows, or HERMES_HOME) |
| Other assistants | ~/.agents/skills and the Claude, Codex, Grok CLI, Cursor and other folders |
The rules are always the same:
- Elyra never creates a bot’s folder. Without OpenClaw installed, nothing is written.
- Each installed skill carries the
.elyra-managed.jsonmarker. What is not Elyra’s is not touched, and uninstalling Elyra removes only what has the marker. - MausBot: it uses the skills in the Claude Code and Codex folders, where Elyra already installs them.
- OpenBot: gets Elyra’s notices through the Call URL action (example above).
- The
~/.grok/skillsfolder is the Grok CLI’s, not Grok Bot’s; Grok Bot gets Elyra through the connector.
A bot that does not see the skills may need to reload its own skills; see how in its documentation.
Prompt for your bot:
List the skills you have loaded and tell me whether there is one called "elyra". If there is, read it nowand, before using the `elyra` tool, follow what it says. If there is not, reload your skills following yourown bot's documentation and check again; do not make up commands.End-to-end example
The bot sends a task to an agent and is notified when it finishes.
-
Connect the bot to Elyra through
elyra mcpor through the Cloud. -
Create the automation “an agent finishes → Call URL” pointing to the bot’s address, with a signature, and give it the secret (see Notify the bot).
-
Ask in the bot’s chat: “ask an agent to review the changes in project X”.
-
The bot uses the
elyratool to find the project and open the agent, something like:Janela do terminal elyra workspace list --jsonelyra canvas create terminal --workspace 'id:<ID-FROM-THE-LIST>' --agent <agent> --title 'Bot task' --jsonelyra terminal wait --terminal '<HANDLE>' --for tui-idle --jsonelyra terminal send --terminal '<HANDLE>' --text-file <file-with-the-task> --jsonThe
<HANDLE>comes from the second command’s reply. -
The agent works. When it finishes, Elyra makes the Call URL call, the bot checks the signature and tells you in the chat that it is done. To read the result, the bot uses
elyra terminal read --terminal '<HANDLE>'.
Prompt for your bot:
Use Elyra for this task: open an agent in the project "<project name>" (list the workspaces with`elyra workspace list --json` through the `elyra` tool, and read the "elyra" skill first), ask it to"<the task>" and keep an eye on it. When Elyra notifies me at your address that the agent finished (check theX-Elyra-Signature-256 signature), read the result from its terminal and tell me here, in the chat, what wasdone.Troubleshooting
| Symptom | What to do |
|---|---|
| The bot gets “open the Elyra app” | Elyra is closed. Open the app; elyra mcp works again on the next request. |
The bot cannot find the elyra command |
Use the executable’s full path in command. |
| The Cloud refuses the bot’s connection | See Troubleshooting the Cloud. |
| The action failed with “The server answered 401” | The bot refused the call. Check the address and the secret it uses to validate. |
| The action failed with “Signing is on, but the secret does not exist” | Open the automation details and tap Generate secret. |
| The action failed with “The call took longer than 10 s to answer” | The bot took too long. Answer 200 right away and process the notice afterwards. |

