Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ jobs:
run: |
sleep 15
for i in $(seq 1 10); do
RESP=$(curl -s -D /tmp/mcp-headers -X POST 'https://api.relaycast.dev/mcp' \
RESP=$(curl -s -D /tmp/mcp-headers -X POST 'https://cast.agentrelay.com/mcp' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
--max-time 10 \
Expand All @@ -120,14 +120,14 @@ jobs:

SESSION_ID=$(grep -i 'mcp-session-id' /tmp/mcp-headers | tr -d '\r' | awk '{print $2}')
if [ -n "$SESSION_ID" ]; then
curl -s -X POST 'https://api.relaycast.dev/mcp' \
curl -s -X POST 'https://cast.agentrelay.com/mcp' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H "Mcp-Session-Id: $SESSION_ID" \
--max-time 5 \
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}' 2>/dev/null > /dev/null

TOOLS_RESP=$(curl -s -X POST 'https://api.relaycast.dev/mcp' \
TOOLS_RESP=$(curl -s -X POST 'https://cast.agentrelay.com/mcp' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H "Mcp-Session-Id: $SESSION_ID" \
Expand All @@ -146,7 +146,7 @@ jobs:
for attempt in 1 2 3 4 5; do
echo "=== Attempt $attempt of 5 ==="
OUTPUT=$(npx @smithery/cli@3 publish \
-u https://api.relaycast.dev/mcp \
-u https://cast.agentrelay.com/mcp \
-n "relaycast/relay" \
-k "$SMITHERY_API_KEY" \
--config-schema packages/mcp/smithery-config-schema.json 2>&1) || true
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Relaycast is headless Slack for agents: channels, threads, DMs, reactions, files
- `openapi.yaml` for HTTP API schema.
- Root `package.json` for scripts and workspace configuration.
- `packages/engine` for API behavior — the canonical, portable server that powers the hosted gateway
(`gateway.relaycast.dev`) and self-hosting.
(`cast.agentrelay.com`) and self-hosting.
- `packages/sdk-typescript` for TypeScript SDK surface.


Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ const { token: systemToken } = await relay.system({ name: 'System' });

Hosted vs self-hosted:

By default, Relaycast SDKs connect to the hosted engine at `https://gateway.relaycast.dev`. To
By default, Relaycast SDKs connect to the hosted engine at `https://cast.agentrelay.com`. To
keep traffic and state on your own infrastructure, self-host the engine (`@relaycast/engine`) and
point the SDK at it with `baseUrl`:

Expand Down Expand Up @@ -226,7 +226,7 @@ print(me.inbox())

Self-hosting:

By default the Python SDK talks to the hosted engine at `https://gateway.relaycast.dev`.
By default the Python SDK talks to the hosted engine at `https://cast.agentrelay.com`.
To self-host, run the engine (`npx @relaycast/engine`, default port 8787) and point `base_url` at it:

```python
Expand Down Expand Up @@ -268,7 +268,7 @@ Local stdio config:
"command": "npx",
"args": ["@relaycast/mcp"],
"env": {
"RELAY_BASE_URL": "https://gateway.relaycast.dev"
"RELAY_BASE_URL": "https://cast.agentrelay.com"
}
}
}
Expand Down Expand Up @@ -318,20 +318,20 @@ The CLI command names are the MCP tool names. Run `relaycast tools` for the live
# Create workspace
# Workspace names are not globally unique.
# Reusing the same name with the same Authorization bearer workspace key returns the existing workspace.
curl -X POST https://gateway.relaycast.dev/v1/workspaces \
curl -X POST https://cast.agentrelay.com/v1/workspaces \
-H "Content-Type: application/json" \
-d '{"name": "my-project"}'

# Register agent
curl -X POST https://gateway.relaycast.dev/v1/agents \
curl -X POST https://cast.agentrelay.com/v1/agents \
-H "Authorization: Bearer rk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "type": "agent"}'
```

## API Reference

Base URL: `https://gateway.relaycast.dev/v1` (the hosted engine). Self-hosters use their own engine
Base URL: `https://cast.agentrelay.com/v1` (the hosted engine). Self-hosters use their own engine

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update OpenAPI servers to the new hosted origin

Root AGENTS.md requires README.md and openapi.yaml to be updated together when API behavior changes. This line moves the documented hosted API to cast.agentrelay.com, but openapi.yaml still advertises https://gateway.relaycast.dev/v1 in servers[0] (and its root-level A2A server entries), so consumers/generated clients that rely on the schema keep using the old production origin while the SDKs and README use the new one. Please update the OpenAPI server URLs in the same change.

Useful? React with 👍 / 👎.

origin (e.g. `http://localhost:8787/v1`).

Authentication header:
Expand Down Expand Up @@ -450,7 +450,7 @@ Full schema: [`openapi.yaml`](./openapi.yaml)

## Self-Hosting

Relaycast's hosted gateway (`https://gateway.relaycast.dev`) runs the `@relaycast/engine` package.
Relaycast's hosted gateway (`https://cast.agentrelay.com`) runs the `@relaycast/engine` package.
You can run the same engine yourself — it's portable (Node + SQLite) and has no Cloudflare dependency.

Run it directly:
Expand Down Expand Up @@ -490,7 +490,7 @@ E2E smoke test:
```bash
npm run e2e # against the engine dev server (http://localhost:8787)
npm run e2e -- http://localhost:8787 --ci
npm run e2e -- https://gateway.relaycast.dev --ci
npm run e2e -- https://cast.agentrelay.com --ci
```

Observer dashboard:
Expand Down
4 changes: 2 additions & 2 deletions docs/sdk-setup-client-acceptance.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ packages/sdk-typescript/src/
**`RelaycastSetupOptions`**
```ts
{
baseUrl?: string // overrides the hosted default (https://gateway.relaycast.dev)
baseUrl?: string // overrides the hosted default (https://cast.agentrelay.com)
apiKey?: string | (() => string | Promise<string>)
requestTimeoutMs?: number // default 30_000, applied via AbortSignal.timeout
retry?: { maxRetries: number; baseDelayMs: number } // default { 3, 500 }
Expand Down Expand Up @@ -177,7 +177,7 @@ Each bullet is a single test case. **All must pass before this step is COMPLETE.
16. `relayCast()` — returns `RelayCast` configured with workspace `apiKey` and `baseUrl`.
17. `getAgentToken('Alice')` after register — returns the stored token; unknown name returns `undefined`.
18. `listRegisteredAgents()` — returns all registered records in registration order.
19. Default base URL — `new RelaycastSetup()` produces `baseUrl === 'https://gateway.relaycast.dev'`.
19. Default base URL — `new RelaycastSetup()` produces `baseUrl === 'https://cast.agentrelay.com'`.
20. Explicit `baseUrl` (e.g. a self-hosted engine) overrides the default.
21. `apiKey` as function — invoked once per request (or memoized; assert behavior the impl chooses) and bearer header reflects the resolved value.
22. Origin headers — every direct fetch carries `X-SDK-Version`, `X-Relaycast-Origin-Surface/Client/Version`.
Expand Down
6 changes: 3 additions & 3 deletions docs/sdk-setup-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ This spec does **not** cover: self-hosted server setup, Python SDK changes, or c
└────────────────────┬─────────────────────────────────┘
┌────────────────────▼─────────────────────────────────┐
│ Relaycast API (gateway.relaycast.dev / :8787) │
│ Relaycast API (cast.agentrelay.com / :8787) │
│ /v1/workspaces, /v1/agents, /v1/channels, etc. │
└──────────────────────────────────────────────────────┘
```

### Cloud API base URL

`RelaycastSetup` defaults to `https://gateway.relaycast.dev` (the hosted engine). This is overridable via the `baseUrl` constructor option for staging/dev environments or for a self-hosted engine (`http://localhost:8787`).
`RelaycastSetup` defaults to `https://cast.agentrelay.com` (the hosted engine). This is overridable via the `baseUrl` constructor option for staging/dev environments or for a self-hosted engine (`http://localhost:8787`).

---

Expand All @@ -106,7 +106,7 @@ The entry point. Stateless — creates workspaces and returns handles.
export interface RelaycastSetupOptions {
/**
* Base URL for the Relaycast API.
* @default "https://gateway.relaycast.dev"
* @default "https://cast.agentrelay.com"
*/
baseUrl?: string

Expand Down
8 changes: 4 additions & 4 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ info:
name: Apache 2.0

servers:
- url: https://gateway.relaycast.dev/v1
- url: https://cast.agentrelay.com/v1
description: Hosted engine gateway (production)
- url: http://localhost:8787/v1
description: Self-hosted engine (@relaycast/engine)
Expand Down Expand Up @@ -3452,7 +3452,7 @@ paths:
# ── A2A ──────────────────────────────────────────────────────────────
/.well-known/agent-card.json:
servers:
- url: https://gateway.relaycast.dev
- url: https://cast.agentrelay.com
description: Production server (root, no /v1 prefix)
- url: http://localhost:8787
description: Local development server
Expand Down Expand Up @@ -3529,7 +3529,7 @@ paths:

/a2a/rpc:
servers:
- url: https://gateway.relaycast.dev
- url: https://cast.agentrelay.com
description: Production server (root, no /v1 prefix)
- url: http://localhost:8787
description: Local development server
Expand All @@ -3546,7 +3546,7 @@ paths:

/a2a/webhook/{workspace_id}/{name}:
servers:
- url: https://gateway.relaycast.dev
- url: https://cast.agentrelay.com
description: Production server (root, no /v1 prefix)
- url: http://localhost:8787
description: Local development server
Expand Down
2 changes: 1 addition & 1 deletion packages/engine/src/lib/__tests__/origin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function req(
query?: string;
} = {},
): Request {
const url = new URL("https://gateway.relaycast.dev/v1/activity");
const url = new URL("https://cast.agentrelay.com/v1/activity");
if (init.query !== undefined) url.searchParams.set("origin_actor", init.query);
if (init.agentRelayDistinctQuery !== undefined) {
url.searchParams.set("agent_relay_distinct_id", init.agentRelayDistinctQuery);
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp/mcp-server.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"command": "npx",
"args": ["-y", "@relaycast/mcp"],
"env": {
"RELAY_BASE_URL": "https://gateway.relaycast.dev"
"RELAY_BASE_URL": "https://cast.agentrelay.com"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp/smithery-config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"type": "string",
"title": "API Base URL",
"description": "Override API base URL for self-hosted Relaycast deployments.",
"default": "https://gateway.relaycast.dev",
"default": "https://cast.agentrelay.com",
"x-from": { "query": "baseUrl" }
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp/src/smithery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const configSchema = z.object({
.string()
.optional()
.describe(
'Override API base URL for self-hosted Relaycast deployments (defaults to https://gateway.relaycast.dev).',
'Override API base URL for self-hosted Relaycast deployments (defaults to https://cast.agentrelay.com).',
),
});

Expand Down
2 changes: 1 addition & 1 deletion packages/mcp/src/tools/programmability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export function registerProgrammabilityTools(

server.registerTool('integration.action.register', {
title: 'Register Action',
description: 'Register an action (async agent-to-agent RPC) that a specific agent handles. Other agents invoke the action; the handler agent receives an `action.invoked` event and reports the result. Replaces the legacy command API. Requires the hosted engine (gateway.relaycast.dev) or a self-hosted engine.',
description: 'Register an action (async agent-to-agent RPC) that a specific agent handles. Other agents invoke the action; the handler agent receives an `action.invoked` event and reports the result. Replaces the legacy command API. Requires the hosted engine (cast.agentrelay.com) or a self-hosted engine.',
inputSchema: {
name: z.string().describe('Action name (e.g. "deploy", "review")'),
description: z.string().describe('Human-readable description of what the action does'),
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp/src/tools/registration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface CreateWorkspaceResponse {
apiKey?: string;
}

const DEFAULT_BASE_URL = 'https://gateway.relaycast.dev';
const DEFAULT_BASE_URL = 'https://cast.agentrelay.com';

/** Passthrough object schema for dynamic API responses. */
const jsonResult = z.object({}).passthrough();
Expand Down
42 changes: 24 additions & 18 deletions packages/observer-dashboard/src/lib/relay-server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@ describe('relay server resolution', () => {
vi.restoreAllMocks();
});

it('tries gateway before legacy api for hosted observer', () => {
it('resolves the hosted engine for the production observer', () => {
expect(resolveRelayServerCandidatesFromHost('observer.relaycast.dev')).toEqual([
'https://gateway.relaycast.dev',
'https://api.relaycast.dev',
'https://cast.agentrelay.com',
]);
});

it('resolves the per-environment gateway/api candidates for preview observers', () => {
expect(resolveRelayServerCandidatesFromHost('pr23-observer.relaycast.dev')).toEqual([
'https://pr23-gateway.relaycast.dev',
'https://pr23-api.relaycast.dev',
]);
});

Expand All @@ -53,12 +59,12 @@ describe('relay server resolution', () => {

it('only accepts remembered engines from the current host candidates', () => {
const candidates = [
'https://gateway.relaycast.dev',
'https://api.relaycast.dev',
'https://pr23-gateway.relaycast.dev',
'https://pr23-api.relaycast.dev',
];

expect(pickRememberedEngine('https://api.relaycast.dev', candidates)).toBe(
'https://api.relaycast.dev'
expect(pickRememberedEngine('https://pr23-api.relaycast.dev', candidates)).toBe(
'https://pr23-api.relaycast.dev'
);
expect(
pickRememberedEngine('https://attacker.example.com', candidates)
Expand All @@ -68,10 +74,10 @@ describe('relay server resolution', () => {
it('orders remembered engine first without duplicating candidates', () => {
expect(
orderByRemembered(
['https://gateway.relaycast.dev', 'https://api.relaycast.dev'],
'https://api.relaycast.dev'
['https://pr23-gateway.relaycast.dev', 'https://pr23-api.relaycast.dev'],
'https://pr23-api.relaycast.dev'
)
).toEqual(['https://api.relaycast.dev', 'https://gateway.relaycast.dev']);
).toEqual(['https://pr23-api.relaycast.dev', 'https://pr23-gateway.relaycast.dev']);
});
});

Expand All @@ -80,32 +86,32 @@ describe('selectEngineForKey', () => {
vi.unstubAllGlobals();
});

it('falls back to the legacy api engine when gateway rejects the key', async () => {
it('falls back to the -api engine when the gateway rejects the key', async () => {
const fetchMock = mockFetch(
new Response(null, { status: 401 }),
new Response(null, { status: 200 })
);

await expect(
selectEngineForKey(
['https://gateway.relaycast.dev', 'https://api.relaycast.dev'],
['https://pr23-gateway.relaycast.dev', 'https://pr23-api.relaycast.dev'],
'rk_live_test'
)
).resolves.toEqual({
baseUrl: 'https://api.relaycast.dev',
baseUrl: 'https://pr23-api.relaycast.dev',
reachedAny: true,
rejectedAny: true,
inconclusiveAny: false,
});

expect(fetchMock).toHaveBeenNthCalledWith(
1,
'https://gateway.relaycast.dev/v1/workspace',
'https://pr23-gateway.relaycast.dev/v1/workspace',
expect.objectContaining({ cache: 'no-store' })
);
expect(fetchMock).toHaveBeenNthCalledWith(
2,
'https://api.relaycast.dev/v1/workspace',
'https://pr23-api.relaycast.dev/v1/workspace',
expect.objectContaining({ cache: 'no-store' })
);
});
Expand All @@ -118,7 +124,7 @@ describe('selectEngineForKey', () => {

await expect(
selectEngineForKey(
['https://gateway.relaycast.dev', 'https://api.relaycast.dev'],
['https://pr23-gateway.relaycast.dev', 'https://pr23-api.relaycast.dev'],
'rk_live_test'
)
).resolves.toEqual({
Expand All @@ -137,7 +143,7 @@ describe('selectEngineForKey', () => {

await expect(
selectEngineForKey(
['https://gateway.relaycast.dev', 'https://api.relaycast.dev'],
['https://pr23-gateway.relaycast.dev', 'https://pr23-api.relaycast.dev'],
'rk_live_test'
)
).resolves.toEqual({
Expand All @@ -153,7 +159,7 @@ describe('selectEngineForKey', () => {

await expect(
selectEngineForKey(
['https://gateway.relaycast.dev', 'https://api.relaycast.dev'],
['https://pr23-gateway.relaycast.dev', 'https://pr23-api.relaycast.dev'],
'rk_live_test'
)
).resolves.toEqual({
Expand Down
Loading
Loading