Tunnels
a2a-exposed uses Cloudflare Tunnel in two places. They are easy to mix up.
A local wake webhook
OpenClaw (untested) binds its gateway to 127.0.0.1:18789. Hermes (untested) often listens on port 8644. tunnel create publishes the wake path so the Worker can reach it:
- a named tunnel
- a proxied DNS name
wake-<random>.<your-zone> - an Access application that admits one service token
- the Worker sends that token as
CF-Access-Client-IdandCF-Access-Client-Secreton every wake, next to the preset's own auth
npx -y a2a-exposed@latest tunnel create
You need Cloudflare Zero Trust (the free plan is enough) and a zone somewhere on the account. The Worker itself can stay on workers.dev. With several zones, pass --tunnel. Run cloudflared on the agent's machine with the command it prints. The token file is mode 600.
tunnel status checks that a request without the service token is blocked and that the connector is up. tunnel rm deletes the DNS record, the tunnel, the Access app and the wake secrets.
A polling setup can add the tunnel later, on the same database. Grok Bot is tested end to end. Other agents are on compatibility.
Outbound port 7844 (TCP and UDP) has to be allowed or the connector never connects. Symptom: Cloudflare error 1033 / HTTP 530. See troubleshooting.
The public-front hop
That is a different tunnel: your A2A agent is the origin, and the Worker forwards peer calls to the tunnel hostname. You pass that hostname as --upstream. A Tailnet URL is refused. Access plus UPSTREAM_TOKEN are the two locks. See public front.
tunnel create is the wake helper. The public-front tunnel is one you create for the agent (the setup skill has the recipe) and then name with --upstream.