-
Notifications
You must be signed in to change notification settings - Fork 0
docs: self-hosting guide #140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,4 +2,4 @@ | |
| "version": 1, | ||
| "lastUpdated": "2026-05-29T15:00:49.465Z", | ||
| "trajectories": {} | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,255 @@ | ||||||||||||||||||||||||||||||||||||||||
| # Self-hosting Relaycast | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Run your own Relaycast server — channels, threads, DMs, presence, actions, files, | ||||||||||||||||||||||||||||||||||||||||
| real-time WebSocket events, and the MCP endpoint — as a single **Node + SQLite** | ||||||||||||||||||||||||||||||||||||||||
| process. No Cloudflare account, no external services. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| This is the open-core engine (`@relaycast/engine`). It's the same engine that | ||||||||||||||||||||||||||||||||||||||||
| powers the hosted product; self-host swaps the Cloudflare/Durable-Object backends | ||||||||||||||||||||||||||||||||||||||||
| for in-process ones and uses built-in API-key auth instead of hosted accounts. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| > **Single-tenant, single-process.** Self-host is designed for one server holding | ||||||||||||||||||||||||||||||||||||||||
| > its own state. It is **not** horizontally scalable as shipped — see | ||||||||||||||||||||||||||||||||||||||||
| > [Limitations](#8-limitations) before you depend on it for scale. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 1. Prerequisites | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| - **Node.js ≥ 20** (`node -v`). | ||||||||||||||||||||||||||||||||||||||||
| - A C toolchain for the native `better-sqlite3` build — preinstalled on most | ||||||||||||||||||||||||||||||||||||||||
| systems; on bare Linux: `apt-get install -y build-essential python3`. | ||||||||||||||||||||||||||||||||||||||||
| - A writable directory for the SQLite file and uploaded files. | ||||||||||||||||||||||||||||||||||||||||
| - An open TCP port (default `8787`). | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| No database server, no message broker, no object store — SQLite and the local | ||||||||||||||||||||||||||||||||||||||||
| filesystem are all you need. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 2. Install & run | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ### Quick start (npx) | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||
| npx @relaycast/engine --db ./relaycast.db --port 8787 | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ### Global install | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||
| npm install -g @relaycast/engine | ||||||||||||||||||||||||||||||||||||||||
| relaycast-engine --db ./relaycast.db --port 8787 | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| On start it migrates the database (idempotent), then serves on the port and prints | ||||||||||||||||||||||||||||||||||||||||
| a hint for creating your first workspace: | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
| Relaycast self-host listening on http://localhost:8787 (db: ./relaycast.db) | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| `Ctrl-C` shuts down cleanly. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 3. Configuration | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Flags take precedence over environment variables. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| | Flag | Env var | Default | Purpose | | ||||||||||||||||||||||||||||||||||||||||
| |---|---|---|---| | ||||||||||||||||||||||||||||||||||||||||
| | `--db <path>` | `RELAYCAST_DB_PATH` | `./relaycast.db` | SQLite database file (created if absent). Use `:memory:` for throwaway runs. | | ||||||||||||||||||||||||||||||||||||||||
| | `--port <n>` | `PORT` | `8787` | HTTP/WebSocket listen port. | | ||||||||||||||||||||||||||||||||||||||||
| | `--base-url <url>` | — | `http://localhost:<port>` | Public origin. **Set this in production** — it's embedded in signed file-upload/download URLs, so it must be the address clients actually reach. | | ||||||||||||||||||||||||||||||||||||||||
| | `--env <name>` | `RELAYCAST_ENV` | `production` | Environment label used in logs. | | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| **Telemetry is off by default** — self-host ships a no-op telemetry sink, so | ||||||||||||||||||||||||||||||||||||||||
| nothing is sent anywhere. (There is no PostHog/analytics in self-host.) | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Migrations run automatically on every boot and are tracked in an internal | ||||||||||||||||||||||||||||||||||||||||
| `_engine_migrations` table, so restarts and upgrades are safe. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 4. Create your first workspace | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| There's no separate bootstrap command — create a workspace through the API. It | ||||||||||||||||||||||||||||||||||||||||
| returns a **workspace key** (`rk_live_…`), shown **once**: | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||
| curl -s -XPOST http://localhost:8787/v1/workspaces \ | ||||||||||||||||||||||||||||||||||||||||
| -H 'content-type: application/json' \ | ||||||||||||||||||||||||||||||||||||||||
| -d '{"name":"my-team"}' | ||||||||||||||||||||||||||||||||||||||||
| # → { "ok": true, "data": { "workspace_id": "…", "api_key": "rk_live_…", … } } | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Store the `api_key` securely — it's the admin credential for the workspace and | ||||||||||||||||||||||||||||||||||||||||
| can't be recovered (only rotated). Creating a workspace also seeds a default | ||||||||||||||||||||||||||||||||||||||||
| `general` channel. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Register agents with the workspace key to get per-agent tokens (`at_live_…`): | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||
| curl -s -XPOST http://localhost:8787/v1/agents \ | ||||||||||||||||||||||||||||||||||||||||
| -H "authorization: Bearer rk_live_…" -H 'content-type: application/json' \ | ||||||||||||||||||||||||||||||||||||||||
| -d '{"name":"alice"}' | ||||||||||||||||||||||||||||||||||||||||
| # → { "ok": true, "data": { "id": "…", "token": "at_live_…", … } } | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 5. Connecting clients | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Point any Relaycast client at your base URL with a key. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| - **SDK** (`@relaycast/sdk`): pass `baseUrl: "http://your-host:8787"` and the | ||||||||||||||||||||||||||||||||||||||||
| workspace key or agent token. See the SDK docs. | ||||||||||||||||||||||||||||||||||||||||
| - **Real-time WebSocket**: `ws://your-host:8787/v1/ws?token=<at_live_...>` streams | ||||||||||||||||||||||||||||||||||||||||
| that agent's events. Workspace-key streams are off by default in self-host; enable | ||||||||||||||||||||||||||||||||||||||||
| them first if you need an admin-wide stream: | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||
| curl -s -XPUT http://localhost:8787/v1/workspace/stream \ | ||||||||||||||||||||||||||||||||||||||||
| -H "authorization: Bearer rk_live_…" -H 'content-type: application/json' \ | ||||||||||||||||||||||||||||||||||||||||
| -d '{"enabled":true}' | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Then connect with `ws://your-host:8787/v1/ws?token=<rk_live_...>`. | ||||||||||||||||||||||||||||||||||||||||
| - **MCP**: point an MCP client at `http://your-host:8787/mcp`, passing the | ||||||||||||||||||||||||||||||||||||||||
| workspace key via the `x-relay-api-key` header. | ||||||||||||||||||||||||||||||||||||||||
| - **CLI** (`relaycast`): set `RELAY_BASE_URL=http://your-host:8787` and | ||||||||||||||||||||||||||||||||||||||||
| `RELAY_API_KEY=rk_live_…`. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ### Files | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Self-host stores uploaded files on the local filesystem (default: | ||||||||||||||||||||||||||||||||||||||||
| `<cwd>/relaycast-files`) and serves them through the engine itself via short-lived | ||||||||||||||||||||||||||||||||||||||||
| **HMAC-signed URLs** at `/_relayfiles`. The upload/download flow is identical to | ||||||||||||||||||||||||||||||||||||||||
| the hosted (presigned-R2) experience — clients `PUT`/`GET` the signed URL the API | ||||||||||||||||||||||||||||||||||||||||
| returns. Make sure `--base-url` is the public address so those URLs resolve. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 6. Running in production | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Self-host speaks plain HTTP/WS. Put a TLS-terminating reverse proxy in front and | ||||||||||||||||||||||||||||||||||||||||
| **make sure it forwards WebSocket upgrades**. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| **Caddy** (automatic HTTPS): | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```caddyfile | ||||||||||||||||||||||||||||||||||||||||
| relay.example.com { | ||||||||||||||||||||||||||||||||||||||||
| reverse_proxy localhost:8787 | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| **nginx** (WebSocket upgrade headers are required): | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```nginx | ||||||||||||||||||||||||||||||||||||||||
| location / { | ||||||||||||||||||||||||||||||||||||||||
| proxy_pass http://127.0.0.1:8787; | ||||||||||||||||||||||||||||||||||||||||
| proxy_http_version 1.1; | ||||||||||||||||||||||||||||||||||||||||
| proxy_set_header Upgrade $http_upgrade; | ||||||||||||||||||||||||||||||||||||||||
| proxy_set_header Connection "upgrade"; | ||||||||||||||||||||||||||||||||||||||||
| proxy_set_header Host $host; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Then run with the public origin: | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||
| relaycast-engine --db /var/lib/relaycast/relaycast.db --port 8787 \ | ||||||||||||||||||||||||||||||||||||||||
| --base-url https://relay.example.com | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| **systemd** (`/etc/systemd/system/relaycast.service`): | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```ini | ||||||||||||||||||||||||||||||||||||||||
| [Service] | ||||||||||||||||||||||||||||||||||||||||
| ExecStart=/usr/local/bin/relaycast-engine --db /var/lib/relaycast/relaycast.db --port 8787 --base-url https://relay.example.com | ||||||||||||||||||||||||||||||||||||||||
| Restart=always | ||||||||||||||||||||||||||||||||||||||||
| User=relaycast | ||||||||||||||||||||||||||||||||||||||||
| WorkingDirectory=/var/lib/relaycast | ||||||||||||||||||||||||||||||||||||||||
| [Install] | ||||||||||||||||||||||||||||||||||||||||
| WantedBy=multi-user.target | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| **Docker** (build your own image — no official image is published yet): | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```dockerfile | ||||||||||||||||||||||||||||||||||||||||
| FROM node:20-bookworm-slim | ||||||||||||||||||||||||||||||||||||||||
| RUN apt-get update && apt-get install -y --no-install-recommends build-essential python3 \ | ||||||||||||||||||||||||||||||||||||||||
| && rm -rf /var/lib/apt/lists/* | ||||||||||||||||||||||||||||||||||||||||
| RUN npm install -g @relaycast/engine | ||||||||||||||||||||||||||||||||||||||||
| VOLUME /data | ||||||||||||||||||||||||||||||||||||||||
| WORKDIR /data | ||||||||||||||||||||||||||||||||||||||||
| EXPOSE 8787 | ||||||||||||||||||||||||||||||||||||||||
| ENV RELAYCAST_DB_PATH=/data/relaycast.db PORT=8787 | ||||||||||||||||||||||||||||||||||||||||
|
cubic-dev-ai[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||
| ENTRYPOINT ["relaycast-engine"] | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+181
to
+189
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current Dockerfile installs build dependencies ( Using a multi-stage build allows you to compile the dependencies in a builder stage and copy only the compiled node modules and binary to a clean runtime stage, keeping the final production image slim and secure.
Suggested change
Comment on lines
+185
to
+189
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
With this Dockerfile/run command, only Useful? React with 👍 / 👎. |
||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||||
| docker build -t relaycast . | ||||||||||||||||||||||||||||||||||||||||
| docker run -p 8787:8787 -v "$PWD/data:/data" relaycast --base-url https://relay.example.com | ||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 7. Upgrades & backups | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| - **Back up the SQLite file** (and the files directory) before upgrading. With the | ||||||||||||||||||||||||||||||||||||||||
| server stopped, copy `relaycast.db` (and `-wal`/`-shm` if present). | ||||||||||||||||||||||||||||||||||||||||
| - **Upgrade**: `npm install -g @relaycast/engine@latest` (or bump the Docker base), | ||||||||||||||||||||||||||||||||||||||||
| then restart. New migrations apply automatically on boot; already-applied ones | ||||||||||||||||||||||||||||||||||||||||
| are skipped. | ||||||||||||||||||||||||||||||||||||||||
| - Versioning is lockstep across `@relaycast/*`, so a single version bump covers the | ||||||||||||||||||||||||||||||||||||||||
| engine, CLI, and SDKs. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 8. Limitations | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Be honest with yourself about what self-host is and isn't: | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| - **Single process only — no horizontal scale-out.** Sequence counters, the | ||||||||||||||||||||||||||||||||||||||||
| WebSocket connection set, presence, the workspace-stream override, the resync | ||||||||||||||||||||||||||||||||||||||||
| ring, and rate-limit buckets all live in this process's memory. Two | ||||||||||||||||||||||||||||||||||||||||
| `relaycast-engine` processes would each have independent state and disjoint | ||||||||||||||||||||||||||||||||||||||||
| sockets. A multi-node deployment needs a shared realtime/persistence backend | ||||||||||||||||||||||||||||||||||||||||
| (Redis pub/sub for fanout, Postgres for storage) plugged in behind the same | ||||||||||||||||||||||||||||||||||||||||
| engine ports — **that adapter is a future extension, not shipped today.** | ||||||||||||||||||||||||||||||||||||||||
| - **In-process background work.** The webhook/notification "queue" and the periodic | ||||||||||||||||||||||||||||||||||||||||
| A2A health sweep run as in-process timers — they don't survive a restart mid-flight. | ||||||||||||||||||||||||||||||||||||||||
| - **Counters reset on restart.** Idempotency windows and usage counters are | ||||||||||||||||||||||||||||||||||||||||
| in-memory (best-effort), so they reset when the process restarts. | ||||||||||||||||||||||||||||||||||||||||
| - **Workspace-stream overrides reset on restart.** If you enable the workspace-key | ||||||||||||||||||||||||||||||||||||||||
| WebSocket stream with `PUT /v1/workspace/stream`, repeat that call after restart. | ||||||||||||||||||||||||||||||||||||||||
| - **Restart resets live realtime sequences.** A restart loses in-memory | ||||||||||||||||||||||||||||||||||||||||
| `agent_seq`/socket state; reconnecting clients resync from the database. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ### What you DON'T get vs the hosted product | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| | | Self-host | Hosted | | ||||||||||||||||||||||||||||||||||||||||
| |---|---|---| | ||||||||||||||||||||||||||||||||||||||||
| | Billing / plan entitlements | static, effectively unlimited single tier | Stripe-backed per-workspace | | ||||||||||||||||||||||||||||||||||||||||
| | Multi-tenant admin / org management | — | yes | | ||||||||||||||||||||||||||||||||||||||||
| | Horizontal scaling / multi-region | single process | Durable Objects + edge | | ||||||||||||||||||||||||||||||||||||||||
| | Managed backups & SLA | you operate the SQLite file + process | managed | | ||||||||||||||||||||||||||||||||||||||||
| | Product analytics (PostHog) | none (no-op sink) | yes | | ||||||||||||||||||||||||||||||||||||||||
| | Auth | built-in API keys (`rk_live_`/`at_live_`) | hosted accounts/billing | | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| You *can* front self-host with your own SSO/proxy, but the shipped default is plain | ||||||||||||||||||||||||||||||||||||||||
| API keys. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| ## 9. Troubleshooting | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| - **`better-sqlite3` fails to install** — install a C toolchain | ||||||||||||||||||||||||||||||||||||||||
| (`build-essential python3`) and reinstall; it compiles a native module. | ||||||||||||||||||||||||||||||||||||||||
| - **WebSocket won't connect through a proxy** — your reverse proxy isn't forwarding | ||||||||||||||||||||||||||||||||||||||||
| the `Upgrade`/`Connection` headers (see nginx example above). | ||||||||||||||||||||||||||||||||||||||||
| - **File download URLs 404 or point at `localhost`** — set `--base-url` to the | ||||||||||||||||||||||||||||||||||||||||
| public origin. | ||||||||||||||||||||||||||||||||||||||||
| - **Port already in use** — change `--port` / `PORT`. | ||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,6 @@ | ||
| import { Hono } from 'hono'; | ||
| import type { ContentfulStatusCode } from 'hono/utils/http-status'; | ||
| import { z } from 'zod'; | ||
| import { AgentTypeSchema } from '@relaycast/types'; | ||
| import type { AppEnv } from '../env.js'; | ||
| import { requireWorkspaceKey, requireAuth } from '../middleware/auth.js'; | ||
| import { rateLimit } from '../middleware/rateLimit.js'; | ||
|
|
@@ -23,10 +22,11 @@ const skillSchema = z.object({ | |
| }); | ||
|
|
||
| const capabilitiesSchema = z.record(z.string(), z.unknown()); | ||
| const agentTypeSchema = z.enum(['agent', 'human', 'system']); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: Reuse the shared Prompt for AI agents |
||
|
|
||
| const registerAgentSchema = z.object({ | ||
| name: z.string().min(1), | ||
| type: AgentTypeSchema.optional(), | ||
| type: agentTypeSchema.optional(), | ||
| persona: z.string().optional(), | ||
| metadata: z.record(z.string(), z.unknown()).optional(), | ||
| skills: z.array(skillSchema).optional(), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a language identifier to the fenced block.
The code fence at Line 48 has no language, which trips markdown linting (MD040). Use
text(orbashif you want it treated as command output).Suggested patch
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 48-48: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents