mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-03 17:11:35 +00:00
* feat(plugins): add read-only session beam * test(plugins): tighten Beam HTTP fixtures * docs(plugins): refresh Beam inventory counts * fix(plugins): keep Beam wire types private * fix(plugins): stabilize Beam transcript paging * fix(plugins): honor Beam Control UI base paths
148 lines
5.4 KiB
Markdown
148 lines
5.4 KiB
Markdown
---
|
|
summary: "Publish redacted local coding sessions into a shared read-only OpenClaw catalog"
|
|
read_when:
|
|
- Sharing a Claude Code or Codex session with trusted Gateway operators
|
|
- Configuring an authenticated session-ingest endpoint without connecting a node
|
|
- Auditing what Beam stores and exposes
|
|
title: "Beam plugin"
|
|
---
|
|
|
|
The bundled `beam` plugin receives a sanitized coding-session snapshot over authenticated HTTP and presents it in the Control UI's existing external-session catalog. The source computer sends text out; OpenClaw never connects back to that computer and receives no filesystem, terminal, tool, or node capability.
|
|
|
|
Beam ships with OpenClaw but is disabled by default. When enabled, it registers:
|
|
|
|
- `POST /api/v1/beam/sessions`
|
|
- the read-only **Beam** session catalog in the Control UI sidebar
|
|
|
|
## Enable
|
|
|
|
```bash
|
|
openclaw plugins enable beam
|
|
openclaw gateway restart
|
|
```
|
|
|
|
Equivalent config:
|
|
|
|
```json5
|
|
{
|
|
plugins: {
|
|
entries: {
|
|
beam: { enabled: true },
|
|
},
|
|
},
|
|
}
|
|
```
|
|
|
|
Disable the plugin when the ingest route is not needed:
|
|
|
|
```bash
|
|
openclaw plugins disable beam
|
|
openclaw gateway restart
|
|
```
|
|
|
|
## Authentication
|
|
|
|
The receiver uses normal Gateway HTTP authentication. It is not an anonymous upload endpoint.
|
|
|
|
- With `gateway.auth.mode: "trusted-proxy"`, send requests through the configured identity-aware proxy. Beam relies on Gateway authentication but does not persist proxy identity headers as uploader attribution.
|
|
- With token or password auth, send `Authorization: Bearer <gateway-token-or-password>`.
|
|
- Do not enable Beam with `gateway.auth.mode: "none"` unless another private ingress fully authenticates every request.
|
|
|
|
A Cloudflare Access-protected deployment can authenticate a local CLI without exposing a GitHub token:
|
|
|
|
```bash
|
|
cloudflared access login https://gateway.example.com
|
|
cloudflared access curl https://gateway.example.com/api/v1/beam/sessions \
|
|
-H 'Content-Type: application/json' \
|
|
--data-binary @sanitized-beam.json
|
|
```
|
|
|
|
The `beam` skill in [openclaw/agent-skills](https://github.com/openclaw/agent-skills) handles local transcript discovery, redaction, Cloudflare Access login, and upload for Claude Code and Codex.
|
|
|
|
## Request
|
|
|
|
```http
|
|
POST /api/v1/beam/sessions
|
|
Content-Type: application/json
|
|
```
|
|
|
|
```json
|
|
{
|
|
"version": 1,
|
|
"beamId": "0123456789abcdef0123456789abcdef",
|
|
"source": "claude",
|
|
"title": "Fix the upload flow",
|
|
"updatedAt": "2026-07-20T12:00:00.000Z",
|
|
"completed": false,
|
|
"items": [
|
|
{ "type": "userMessage", "text": "Fix the upload flow." },
|
|
{ "type": "agentMessage", "text": "Implemented and tested." },
|
|
{ "type": "other", "text": "3 read, 2 write, 1 execute; raw tool outputs dropped: 4" }
|
|
]
|
|
}
|
|
```
|
|
|
|
The schema is closed. Beam rejects unknown fields, invalid item types, empty text, more than 200 items, item text over 6,000 characters, non-JSON requests, and bodies over 56 KiB.
|
|
|
|
A successful upload returns the stable Beam id and a relative Control UI URL:
|
|
|
|
```json
|
|
{
|
|
"ok": true,
|
|
"beamId": "0123456789abcdef0123456789abcdef",
|
|
"url": "/chat?session=catalog%3Abeam%3Agateway%3A0123456789abcdef0123456789abcdef"
|
|
}
|
|
```
|
|
|
|
Uploading the same `beamId` updates the existing catalog row. A completed upload sets the row status to `completed`; earlier updates display as `live`.
|
|
|
|
## Storage and visibility
|
|
|
|
Beam stores sanitized payloads in OpenClaw's shared SQLite-backed plugin state:
|
|
|
|
- at most 500 sessions
|
|
- seven-day retention refreshed by each update
|
|
- oldest-entry eviction when the catalog reaches its bound
|
|
- server receipt time controls catalog ordering; clients cannot move themselves ahead with a forged timestamp
|
|
|
|
The catalog is intentionally shared across the Gateway operator domain. Every client with `operator.read` can view every beamed session, while uploads require `operator.write` or `operator.admin`. Uploader identity is not retained, and any write-authorized operator that knows a Beam id can update that row. OpenClaw operator scopes are not tenant isolation; use a separate Gateway when sessions must be isolated between teams or machines.
|
|
|
|
## Security boundary
|
|
|
|
Beam is passive session publication, not remote control.
|
|
|
|
- It has no `continueSession`, archive, terminal, tool, or node capability.
|
|
- It accepts text-only normalized transcript items, not HTML, scripts, archives, attachments, or server-fetched URLs.
|
|
- The official skill removes raw tool results, reasoning, prompts, local paths, credentials, cookies, and auth material before upload.
|
|
- The receiver still treats every transcript as untrusted text. Copying a beamed transcript into a new agent session is a separate operator action.
|
|
- Requests are rate-limited and concurrency-limited before the body is read.
|
|
|
|
## Troubleshooting
|
|
|
|
`404 Not Found`
|
|
|
|
: The Beam plugin is disabled, the Gateway has not restarted since enablement, or the request is reaching another Gateway.
|
|
|
|
`401 Unauthorized`
|
|
|
|
: The request did not satisfy Gateway HTTP auth. Check the bearer credential or trusted-proxy/Access session.
|
|
|
|
`405 Method Not Allowed`
|
|
|
|
: The receiver accepts only `POST`.
|
|
|
|
`413 Payload Too Large`
|
|
|
|
: The serialized request exceeded 56 KiB. The official skill drops older sanitized messages until the snapshot fits.
|
|
|
|
`429 Too Many Requests`
|
|
|
|
: The authenticated client exceeded the bounded request or concurrency limit. Retry after the current minute window.
|
|
|
|
## Related
|
|
|
|
- [Control UI](/web/control-ui)
|
|
- [Operator scopes](/gateway/operator-scopes)
|
|
- [Trusted proxy auth](/gateway/trusted-proxy-auth)
|
|
- [Plugin management](/plugins/manage-plugins)
|