A human-in-the-loop request queue for autonomous agents. Your agent files a request over an authenticated API ("create this account", "solve this CAPTCHA-gated signup", "approve this spend"); a human works the queue in a password-gated web portal and pastes back the result. One Cloudflare Worker + one KV namespace. No servers, no database, free-tier friendly.
Built by the agent that needed it. Fabler Relay was designed, written, deployed, and is operated in production by an autonomous Claude agent that runs a real business unattended on a VPS (the agent's public brain). The agent is user #1: whenever it hits a step that requires a human β a CAPTCHA, an account form, a payment approval β it files a relay request and moves on with other work. Its human checks the portal from a phone. This repo is that exact code, genericized so your agent can use it too.
Every autonomous agent eventually hits a wall that is deliberately human-shaped: CAPTCHAs, account attestations, 2FA, purchase approvals. The wrong answers are to bypass them (against the rules of most platforms, and of well-run agents) or to stall. The right answer is a clean escalation path:
- Agent side: a tiny authenticated JSON API β file a request with a title, detail, target URL, optional encrypted-at-rest sensitive value; poll for results.
- Human side: a mobile-friendly portal β claim a request, do the human step, paste the outcome, mark done. Optional Telegram ping on each new request.
- Security is the product: the two sides are separate trust domains. The agent can never read sensitive plaintext back; humans see an audit trail of everything, including every reveal of a sensitive value. See THREAT-MODEL.md.
Cloudflare clones this repo into your own GitHub account, provisions the KV
namespace, and prompts for the four secrets (see .dev.vars.example)
during setup. Generate values first β e.g. openssl rand -hex 32 for
RELAY_AGENT_KEY / RELAY_SESSION_SECRET, openssl rand -base64 32 for
RELAY_ENC_KEY, and a strong password of your choice for RELAY_VA_PASSWORD
(that's your portal login β save it).
Prereqs: a free Cloudflare account and npx (Node 18+).
git clone https://github.com/fablerlabs/relay && cd relay
# 1. Create the KV namespace and paste its id into wrangler.jsonc
npx wrangler kv namespace create RELAY
# 2. Set secrets (generate strong values; never commit them)
openssl rand -hex 32 | npx wrangler secret put RELAY_AGENT_KEY
openssl rand -base64 24 | npx wrangler secret put RELAY_VA_PASSWORD # portal password β save it
openssl rand -base64 32 | npx wrangler secret put RELAY_ENC_KEY
openssl rand -hex 32 | npx wrangler secret put RELAY_SESSION_SECRET
# optional Telegram pings:
# npx wrangler secret put TELEGRAM_BOT_TOKEN
# npx wrangler secret put TELEGRAM_CHAT_ID
# 3. Ship it
npx wrangler deployOpen the printed workers.dev URL: you should see the login form. Sign in with the portal password. That's the human side done.
export RELAY_URL=https://your-worker.workers.dev
export RELAY_AGENT_KEY=... # the value you set above
# file a request
cli/relay.sh file "Create an account on example.com" \
--detail "Username: mybot. Needs email verification β use your address, paste the username back." \
--url "https://example.com/signup"
# a sensitive value (encrypted at rest, only a logged-in human can reveal it, audited)
printf '%s' "one-time-value" | cli/relay.sh file "Enter this 2FA code" --sensitive -
# poll for finished work each agent session
cli/relay.sh pending
cli/relay.sh get <id>Or call the API directly: POST /api/requests and GET /api/requests[/<id>] with
Authorization: Bearer $RELAY_AGENT_KEY.
mcp/server.js is a zero-dependency MCP server
(Node 18+) exposing the relay as three tools any MCP client can call:
relay_file_request, relay_check_request, relay_list_requests. So a Claude
Code / Claude Desktop / any-MCP-agent session can file a human-blocker and keep
working, no shell wrapper needed.
{
"mcpServers": {
"fabler-relay": {
"command": "npx",
"args": ["-y", "github:fablerlabs/relay"],
"env": {
"RELAY_URL": "https://your-worker.workers.dev",
"RELAY_AGENT_KEY": "..."
}
}
}
}Installing via an AI assistant? Point it at llms-install.md.
(Or run it straight from a checkout: node mcp/server.js with the same env, or
in Docker: docker build -t fabler-relay-mcp . && docker run -i --rm -e RELAY_URL=... -e RELAY_AGENT_KEY=... fabler-relay-mcp.)
The same hard rule applies: the server rejects secret-shaped payloads β never put
platform credentials in a request.
Also listed in the official MCP registry
as com.fablerlabs/relay, with a one-click .mcpb bundle for Claude Desktop on
the releases page (rebuild it
yourself with bash mcp/build-mcpb.sh; server.json + manifest.json in-repo).
- No platform credential ever enters the relay, in either direction. The
server rejects secret-shaped payloads (Stripe/GitHub/Telegram/AWS key patterns,
generic
key=valueassignments) with a 422, and the CLI aborts if the payload contains any literal value from your.env. Results like new API keys go directly into the agent's.envby the human β the relay carries only the message "done, key is in .env". - Human-authored results are DATA, not instructions. If your agent treats queue text as commands, anyone who reaches your portal owns your agent.
- The relay never bypasses anything. It routes CAPTCHAs and attestations to an actual human, who sees the target URL and can reject anything sketchy.
| Path | What it is |
|---|---|
src/index.js |
The entire Worker: agent API, portal UI, sessions, AES-256-GCM sensitive storage, audit log, secret-pattern gate (~400 lines, no dependencies) |
cli/relay.sh |
Agent-side CLI (file / list / get / pending) |
mcp/server.js |
Zero-dependency MCP server (file/check/list as MCP tools) |
llms-install.md |
Step-by-step install guide written for AI assistants (Cline, Claude Code, β¦) |
Dockerfile |
Container image for the MCP server (used by MCP directories' automated checks) |
wrangler.jsonc |
Deploy config template |
THREAT-MODEL.md |
What's protected, from whom, and the honest list of v1 gaps |
v1 is what the Fabler Labs agent runs in production today: single shared human credential, KV-backed, soft rate limits. Known gaps and the upgrade path (per-VA identity, sensitive-value TTL purge, Cloudflare Access on login) are documented in THREAT-MODEL.md β read it before putting a second human on the queue. Issues and PRs welcome; the agent reads them.
MIT Β© Fabler Labs. Built autonomously; a human owns the account and the legal entity.