Skip to main content
Synth’s training infrastructure needs to reach your task app over HTTPS. Tunnels expose your local server to the internet without port forwarding or firewall changes. Two tunnel backends are available:
SynthTunnel (default)Cloudflare
SetupZero config, no binaryRequires cloudflared
Concurrency128 in-flight, dynamic memory budgetCloudflare limits
Authworker_tokentask_app_api_key
URL lifetimePer-lease (session-lived)Managed = stable subdomain
Best forSDK jobs, GEPA, MIPROLong-lived production apps
Relay-based HTTPS tunnel through Synth’s servers. No external binary needed. Traffic flows outbound over WebSocket — no inbound ports required.
from synth_ai.core.tunnels import TunneledLocalAPI

tunnel = await TunneledLocalAPI.create(
    local_port=8001,
    api_key="sk_live_...",
)
print(f"URL: {tunnel.url}")              # https://st.usesynth.ai/s/rt_...
print(f"Token: {tunnel.worker_token}")   # for job auth
Use with optimization jobs:
job = PromptLearningJob.from_dict(
    config,
    task_app_url=tunnel.url,
    task_app_worker_token=tunnel.worker_token,
)

How it works

Synth backend ──HTTP──▶ relay (st.usesynth.ai) ──WS──▶ local agent ──HTTP──▶ localhost:8001
  1. TunneledLocalAPI.create() provisions a lease on the Synth relay
  2. A local WebSocket agent connects outbound to the relay
  3. Incoming requests are forwarded to your local task app
  4. Responses stream back through the relay to the caller

Concurrency

SynthTunnel supports up to 128 concurrent in-flight requests per connection (configurable up to 1024 via lease capabilities). A dynamic memory budget (512 MB) automatically reduces effective concurrency when request/response payloads are large, protecting memory without penalizing lightweight workloads like GEPA rollouts.

Cleanup

# Explicit cleanup
tunnel.close()

# Or use as context manager
with tunnel:
    run_optimization(tunnel.url)
# tunnel is closed automatically

Cloudflare Quick Tunnels

Free, ephemeral tunnels via Cloudflare’s public service. No API key required. Subject to Cloudflare rate limits.
from synth_ai.core.tunnels import TunneledLocalAPI, TunnelBackend

tunnel = await TunneledLocalAPI.create(
    local_port=8001,
    backend=TunnelBackend.CloudflareQuickTunnel,
)
print(f"URL: {tunnel.url}")  # https://random-words.trycloudflare.com
Use with optimization jobs:
job = PromptLearningJob.from_dict(
    config,
    task_app_url=tunnel.url,
    task_app_api_key=env_api_key,  # not worker_token
)
Or manually via CLI:
# Terminal 1: start task app
uvicorn my_task_app:app --host 127.0.0.1 --port 8001

# Terminal 2: create tunnel
cloudflared tunnel --config /dev/null --url http://127.0.0.1:8001

Cloudflare Managed Tunnels

Stable subdomains that persist across sessions. Requires API key.
tunnel = await TunneledLocalAPI.create(
    local_port=8001,
    backend=TunnelBackend.CloudflareManagedLease,
    api_key="sk_live_...",
)

Convenience: Tunnel a FastAPI App

If you have a FastAPI app object, create_for_app handles server startup, health check, and tunnel creation:
from synth_ai.core.tunnels import TunneledLocalAPI

tunnel = await TunneledLocalAPI.create_for_app(
    app=my_fastapi_app,
    progress=True,
)
print(f"App exposed at: {tunnel.url}")

Installing cloudflared

Only needed for Cloudflare backends — SynthTunnel does not require it.
# macOS
brew install cloudflared

# Linux (Debian/Ubuntu)
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb

# Windows
winget install Cloudflare.cloudflared

Troubleshooting

SynthTunnel: AttributeError: module 'synth_ai_py' has no attribute 'synth_tunnel_start'

The compiled Rust extension is stale. Rebuild it:
make build   # from the synth-ai repo root

Cloudflare: 404 or Error 1033

Server not running or config file interference:
cloudflared tunnel --config /dev/null --url http://127.0.0.1:8001
curl http://localhost:8001/health

Cloudflare: Rate limited (quick tunnels)

Cloudflare limits quick tunnel creation. Wait 5-10 minutes or switch to SynthTunnel (no rate limits).

Port in use

from synth_ai.core.tunnels import kill_port
kill_port(8001)