SynthTunnel, Deploy & Harbor, Event Fixes
Friday product updates for January 29, 2026.
This week we shipped SynthTunnel, cloud-hosted task apps via Deploy & Harbor, and fixed a critical reward parsing bug in the event pipeline.
SynthTunnel
Local task apps now connect through Synth's own relay servers instead of requiring cloudflared. Traffic flows outbound over WebSocket, so no inbound ports or external binaries are needed.
from synth_ai.core.tunnels import TunneledLocalAPI
tunnel = await TunneledLocalAPI.create(local_port=8001, api_key="sk_live_...")
print(tunnel.url) # https://st.usesynth.ai/s/rt_...
print(tunnel.worker_token) # pass to job configUse with GEPA or MIPRO jobs:
job = PromptLearningJob.from_dict(
config,
task_app_url=tunnel.url,
task_app_worker_token=tunnel.worker_token,
)Cloudflare tunnels still work—use TunnelBackend.CloudflareQuickTunnel for anonymous testing or CloudflareManagedLease for stable subdomains.
128 Concurrent In-Flight Requests
The relay now supports 128 concurrent in-flight requests per connection (up from 16), configurable up to 1024 via lease capabilities. A dynamic memory budget (512 MB) automatically reduces concurrency when payloads are large, so lightweight workloads like GEPA rollouts get full throughput without risking memory on large-payload jobs.
Per-Lease Concurrency Overrides
Leases can request a custom max_inflight limit at creation time. The relay clamps it to [1, 1024] and returns the effective limit in the lease response. This lets high-throughput jobs (like GEPA with 30+ seeds) run at full concurrency without affecting the default for other users.
Unified Eval Endpoint
POST /api/jobs/eval now works as a canonical endpoint alongside the existing POST /api/v1/offline/jobs. The SDK and TUI can create eval jobs from either path.
Deploy & Harbor: Cloud-Hosted Task Apps
You can now deploy your LocalAPI to Harbor—Synth's hosted cloud infrastructure—instead of running it locally with a tunnel. One command gives you a persistent URL for GEPA, MiPRO, and eval jobs.
synth localapi deploy \
--name my-banking77 \
--app my_localapi:app \
--dockerfile ./Dockerfile \
--context . \
--waitDeploy packages your Dockerfile, uploads it to Harbor, builds a container snapshot, and returns a stable task_app_url. No tunnel, no local server to keep running.
job = PromptLearningJob.from_dict(
config,
task_app_url="https://api.usesynth.ai/api/harbor/deployments/my-banking77",
task_app_api_key=os.environ["SYNTH_API_KEY"],
)Use tunnels for local dev. Use deploy for production, CI/CD, and sharing task apps across your team.
Reward Event Parsing Fix
Fixed a serialization mismatch between the Python SDK and the Rust backend that caused all rollout rewards to silently read as 0.0. The Python SDK was serializing the reward_info field as "metrics" (a Pydantic alias), but the Rust backend expected "reward_info". Every GEPA candidate showed mean_reward = 0.00 regardless of actual performance.
The fix:
- Python SDK now serializes as
"reward_info"(changedaliastovalidation_aliasso input still accepts both names) - Rust backend now accepts both
"reward_info"and"metrics"via#[serde(alias = "metrics")] - Added
enumconstraint to Banking77 demo tool schema to prevent free-text intent predictions
Other Fixes
make buildtarget for reliable Rust extension rebuilds (fixes stale.soissues withmaturin develop)- Tunnel documentation rewritten with SynthTunnel vs Cloudflare comparison across SDK docs, GEPA, and MIPRO pages
- Deploy & Harbor documentation added to repo (
docs/deploy_and_harbor.md) with CLI reference and connectivity comparison table