← Back to Plugins
Channels

Onepilot Channel

sofiane8910 By sofiane8910 👁 10 views ▲ 0 votes

OpenClaw plugin: bridges Onepilot messages to OpenClaw agents

GitHub

Install

openclaw plugins install <dir>

README

# openclaw-onepilot-channel

OpenClaw plugin that bridges the Onepilot app to the agent runtime. Two responsibilities, both running inside the OpenClaw gateway process on the agent host:

1. **Inbound** โ€” opens a durable channel to the Onepilot backend, listens for new user-message events, dispatches them into the agent loop via the gateway's local `/v1/chat/completions` endpoint, and POSTs the assistant reply back to the Onepilot backend so the app receives it via push. Survives mobile force-quits because the agent loop never depends on the app staying alive.
2. **Outbound channel** โ€” registers `onepilot` as a real OpenClaw channel (`api.registerChannel`). This is what makes cron jobs (and any other agent-driven outbound delivery) work โ€” without a registered channel, OpenClaw's delivery resolver throws `"channel is required"` at fire-time. The channel's `sendText` reuses the same backend message endpoint the inbound reply flow uses.

## Repository layout

```
openclaw-onepilot-channel/
โ”œโ”€โ”€ README.md            โ† you are here
โ”œโ”€โ”€ TESTING.md           โ† end-to-end test sheet (foreground, force-quit, push, etc.)
โ”œโ”€โ”€ package.json         โ† npm metadata; `version` is the source of truth for releases
โ”œโ”€โ”€ openclaw.plugin.json โ† plugin manifest read by OpenClaw at install time
โ””โ”€โ”€ src/
    โ”œโ”€โ”€ index.js         โ† register() hook: wires channel subscription + registers outbound
    โ”œโ”€โ”€ stream.js        โ† inbound channel client over our raw WS (see ws-raw.js)
    โ”œโ”€โ”€ messaging.js     โ† inbound dispatch: user message โ†’ agent loop โ†’ reply POST
    โ”œโ”€โ”€ outbound.js      โ† outbound channel handler: cron / agent reply โ†’ backend
    โ”œโ”€โ”€ env.js           โ† isolated runtime env reader (scanner-safe)
    โ”œโ”€โ”€ constants.js     โ† shared user-agent string
    โ””โ”€โ”€ ws-raw.js        โ† node:https-based WebSocket (built-in WebSocket is broken
                            inside the gateway process โ€” see file header)
```

## Credential model

Each deployed agent holds its own **durable API key** (`agentKey`, prefix `oak_`). The app provisions one at pair time, the backend stores only an argon2id hash, and the raw key lives forever until the app revokes it. The plugin uses the key to:

- Exchange it on demand for a short-lived channel auth token (1h TTL). No rotation chain, no shared session state โ€” each exchange is independent.
- Authenticate outbound message POSTs directly (the backend binds the key to `(userId, agentProfileId)` server-side).

Because nothing rotates and nothing is shared across agents, two gateways on the same user account can never collide on credentials. A key wedge is impossible.

## Configuring an account

Provisioned automatically by the app's deploy flow. Manual form:

```sh
openclaw --profile <agent-id> config set 'plugins.entries.onepilot.config.accounts.default' '{
  "enabled": true,
  "backendUrl": "https://api.onepilotapp.com",
  "streamUrl": "wss://api.onepilotapp.com",
  "publishableKey": "<publishable key>",
  "agentKey": "oak_...",
  "userId": "<uuid>",
  "agentProfileId": "<uuid>",
  "sessionKey": "main"
}'
```

## Distribution flow

We **do not** embed plugin source in the mobile binary. Plugin updates ship independently of App Store review.

```
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  GitHub Release        โ”‚      โ”‚  plugin_manifest     โ”‚      โ”‚  Mobile app         โ”‚
โ”‚  sofiane8910/          โ”‚โ—€โ”€โ”€โ”€โ”€โ”€โ”‚  (channel='stable')  โ”‚โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚  PluginManifest     โ”‚
โ”‚  onepilotapp/releases  โ”‚      โ”‚  โ†’ version           โ”‚      โ”‚  Fetcher.fetch()    โ”‚
โ”‚                        โ”‚      โ”‚  โ†’ tarball_url       โ”‚      โ”‚                     โ”‚
โ”‚  onepilot-channel-     โ”‚      โ”‚  โ†’ sha256            โ”‚      โ”‚  ssh-installs over  โ”‚
โ”‚  v0.X.Y.tgz            โ”‚      โ”‚                      โ”‚      โ”‚  curl + sha256      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”‚  + tar -xzf         โ”‚
                                                              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
```

1. Tag a release on `sofiane8910/onepilotapp` and attach the tgz tarball.
2. `UPDATE` the `plugin_manifest` row to point `tarball_url` and `sha256` at the new release.
3. On next agent deploy, the app reads the manifest, SSH-runs an install script on the agent host that `curl`s the tarball, verifies the sha256 inline (mismatch โ†’ abort, no files written), and `tar -xzf` into `~/.openclaw-<agentId>/plugins/openclaw-onepilot-channel/`, then runs `openclaw plugins install <dir> --link`.
4. The manifest row is the version pin โ€” bump it whenever you want a new build to roll out.

The mobile-side reader is `ios/Sources/Onepilot/Models/Agent/Adapters/PluginManifestFetcher.swift`. The install flow lives in `OpenClawAdapter.swift` (`deployOnepilotChannelPlugin` โ†’ `installPluginFromRelease` โ†’ `buildUnixInstallScript` / `buildWindowsInstallScript`).

## Cutting a new version

See `CLAUDE.md` in this directory (gitignored) for the release pipeline โ€” the published tarball is built from a separate repo, and forgetting the sync step is a known footgun.

## Rollback

If a release misbehaves, revert the `plugin_manifest` row to a known-good version and (optionally) yank the bad release. Existing agents won't downgrade automatically (the install script is a no-op when the installed version matches the manifest), but new deploys and reinstalls will pick up the rollback.

## See also

- `TESTING.md` โ€” end-to-end test plan (foreground chat, force-quit, push dedup, multi-host).
- `/openclaw/` (in this monorepo) โ€” upstream OpenClaw source. **Do not modify.**
- `ios/Sources/Onepilot/Models/Agent/Adapters/OpenClawAdapter.swift` โ€” the deploy/install code.
- `ios/Sources/Onepilot/Models/Agent/Adapters/PluginManifestFetcher.swift` โ€” manifest reader.
channels

Comments

Sign in to leave a comment

Loading comments...