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).2
curl -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.2
curl 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
1
import anthropic2
import os3
4
client = anthropic.Anthropic(5
base_url="https://api.relayswitch.io/v1",6
api_key=os.environ["RELAYSWITCH_API_KEY"],7
)8
9
try:10
reply = client.messages.create(11
model="claude-haiku-5-5",12
max_tokens=512,13
messages=[{"role": "user", "content": scraped_page_text}],14
)15
except anthropic.BadRequestError as err:16
# 400 guardrail_blocked: no model was asked and nothing was charged17
print(err.message)OpenAI SDK: read a flag
python
1
from openai import OpenAI2
import os3
4
client = OpenAI(5
base_url="https://api.relayswitch.io/v1",6
api_key=os.environ["RELAYSWITCH_API_KEY"],7
)8
9
raw = client.chat.completions.with_raw_response.create(10
model="gpt-6.1-sol",11
messages=[{"role": "user", "content": tool_output}],12
)13
if raw.headers.get("x-uplink-guardrail") == "flagged":14
alert_on_call() # answered as usual, marked for review15
reply = 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.2
const b64url = (bytes) => btoa(String.fromCharCode(...bytes))3
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");4
const verifier = b64url(crypto.getRandomValues(new Uint8Array(32)));5
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));6
const challenge = b64url(new Uint8Array(digest));7
sessionStorage.setItem("pkce_verifier", verifier);8
9
// 2. Send the user to approve a key with a $10 budget.10
location.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.19
const code = new URLSearchParams(location.search).get("code");20
const 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
});29
const { 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.
Agent setup guides
FAQs
Questions
For agent builders.
Put limits on what your agents send
Guardrails on any key, and sign-in that hands each of your users a budgeted key.