Guardrails and sign-in

Rules an agent cannot talk its way past.

Block patterns, catch prompt injection in tool results and decide which tools a key may call, before any model sees the request. For apps, Sign in with RelaySwitch gives each user their own budgeted key.

Live
A blocked request
$0.00
Blocked patterns per policy
up to 50
Prompt-injection check
off, flag or block
Sign-in code lifetime
10 minutes
Claude Haiku 5.5, per M tokens
$0.06 in / $0.15 out

What it does for an agent

Blocked patterns
Regular expressions checked against system, user and tool text. block stops the request; flag marks it.
Prompt-injection check
Override phrasings, role markers and hidden Unicode in tool output, caught locally with no model call.
Tool allow and deny lists
Function tools, server tools and MCP tools by name, with prefix wildcards. Denied tools never reach the model.
Per key or org-wide
An organization default plus each key’s own rules, combined stricter-wins.
Blocked costs nothing
A request stopped by a guardrail never reaches a model and is never billed.
Sign in with RelaySwitch
OAuth with PKCE: your app gets a key per user, funded by that user, capped at the limit they approved.

Copy, paste, run

curl: organization default
bash
1# The organization's default, layered under every key (admin key).
2curl -X PATCH https://api.relayswitch.io/v1/guardrails \
3 -H "Authorization: Bearer $ADMIN_KEY" -H "Content-Type: application/json" \
4 -d '{"guardrails": {
5 "blocked_patterns": [
6 {"pattern": "rm -rf /", "name": "rm-root"},
7 {"pattern": "(drop|truncate) table", "action": "flag", "name": "sql-ddl"}
8 ],
9 "prompt_injection": "block",
10 "tool_policy": {"deny": ["web_fetch", "github__delete_*"]}
11 }}'
Key API: one agent’s rules
bash
1# A support agent that may only call two tools and flags injection attempts.
2curl https://api.relayswitch.io/v1/keys \
3 -H "Authorization: Bearer $ADMIN_KEY" -H "Content-Type: application/json" \
4 -d '{"name": "support-bot", "budget_usd": 20,
5 "guardrails": {"prompt_injection": "flag",
6 "tool_policy": {"allow": ["lookup_order", "web_search"]}}}'
Anthropic SDK: handle a block
python
1import anthropic
2import os
3
4client = anthropic.Anthropic(
5 base_url="https://api.relayswitch.io/v1",
6 api_key=os.environ["RELAYSWITCH_API_KEY"],
7)
8
9try:
10 reply = client.messages.create(
11 model="claude-haiku-5-5",
12 max_tokens=512,
13 messages=[{"role": "user", "content": scraped_page_text}],
14 )
15except anthropic.BadRequestError as err:
16 # 400 guardrail_blocked: no model was asked and nothing was charged
17 print(err.message)
OpenAI SDK: read a flag
python
1from openai import OpenAI
2import os
3
4client = OpenAI(
5 base_url="https://api.relayswitch.io/v1",
6 api_key=os.environ["RELAYSWITCH_API_KEY"],
7)
8
9raw = client.chat.completions.with_raw_response.create(
10 model="gpt-6.1-sol",
11 messages=[{"role": "user", "content": tool_output}],
12)
13if raw.headers.get("x-uplink-guardrail") == "flagged":
14 alert_on_call() # answered as usual, marked for review
15reply = raw.parse()

Sign in with RelaySwitch

Three steps in the browser: make a PKCE pair, send the user to https://app.relayswitch.io/auth, trade the code at POST /v1/auth/keys. No key needed for the exchange, any origin.

javascript
1// 1. A verifier and its S256 challenge, in the browser.
2const b64url = (bytes) => btoa(String.fromCharCode(...bytes))
3 .replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
4const verifier = b64url(crypto.getRandomValues(new Uint8Array(32)));
5const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
6const challenge = b64url(new Uint8Array(digest));
7sessionStorage.setItem("pkce_verifier", verifier);
8
9// 2. Send the user to approve a key with a $10 budget.
10location.href = "https://app.relayswitch.io/auth?" + new URLSearchParams({
11 callback_url: "https://yourapp.example/callback",
12 code_challenge: challenge,
13 code_challenge_method: "S256",
14 key_label: "YourApp",
15 limit: "10",
16});
17
18// 3. On the callback page, trade ?code= for the user's key.
19const code = new URLSearchParams(location.search).get("code");
20const res = await fetch("https://api.relayswitch.io/v1/auth/keys", {
21 method: "POST",
22 headers: { "content-type": "application/json" },
23 body: JSON.stringify({
24 code,
25 code_verifier: sessionStorage.getItem("pkce_verifier"),
26 code_challenge_method: "S256",
27 }),
28});
29const { key, key_id, limit_usd } = await res.json(); // key: sk-relay-live-...

The callback must be https, or http on localhost, 127.0.0.1 or [::1]. The answer carries key, key_id, name and limit_usd; send the key as Authorization: Bearer on that user’s requests, and each one bills the user’s balance.

FAQs

Questions

For agent builders.

Open the console

A key in under a minute

Get a key

Or email hello@relayswitch.io

Put limits on what your agents send

Guardrails on any key, and sign-in that hands each of your users a budgeted key.