Skip to main content
synth-ai scan discovers and performs health checks on running task applications deployed locally or via Cloudflare tunnels. It provides structured output in both human-readable table format and machine-readable JSON format, making it suitable for terminal use and programmatic consumption by CLI agents and automation tools.

Quick Start

# Scan default port range (8000-8100) and show table
uvx synth-ai scan

# Get JSON output for programmatic use
uvx synth-ai scan --json

# Scan specific port range with verbose output
uvx synth-ai scan --port-range 8000:9000 --verbose

# Use custom API key and timeout
uvx synth-ai scan --api-key YOUR_KEY --timeout 5.0

Discovery Methods

The scan command uses multiple discovery methods to find active task apps:
  • Port Scanning: Scans specified port ranges for local HTTP servers
  • Service Records: Reads deployed local services from persistent records (~/.synth-ai/services.json)
  • Tunnel Records: Reads deployed Cloudflare tunnels from persistent records
  • Process Scanning: Inspects running cloudflared processes for tunnel URLs
  • Backend API: Queries backend for managed tunnel information
  • Registry: Checks task app registry for registered apps

Health Checks

For each discovered app, the command performs health checks by:
  • Making HTTP GET requests to /health endpoints
  • Extracting metadata from /info endpoints (app_id, version, task_name, etc.)
  • Supporting API key authentication via X-API-Key header
Health status is determined as follows:
  • healthy: HTTP 200 with valid JSON response containing "status": "healthy" or "healthy": true
  • unhealthy: HTTP error status (4xx, 5xx), Cloudflare tunnel errors (530, 502), or HTML responses
  • unknown: Request timeout, connection errors, or other exceptions

Output Formats

Table Format (Default)

The table format provides a human-readable view with columns for:
  • Name: App identifier (from /info endpoint or fallback)
  • Port: Local port number
  • Status: Health status with icon (✅ healthy, ⚠️ unhealthy, ❓ unknown)
  • Type: Deployment type (local or cloudflare)
  • App ID: Task app identifier
  • Version: App version
  • Discovered Via: Discovery method used
Example output:
Found 3 active task apps:

Name                                             Port  Status     Type       App ID              Version Discovered Via
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
banking77                                        8000  ✅ healthy  local      banking77           1.0.0   service_records
banking77                                        8001  ✅ healthy  cloudflare banking77           1.0.0   tunnel_records
localhost:8002                                   8002  ⚠️  unhealthy local      -                   -       port_scan

JSON Format (--json)

The JSON format provides machine-readable output with:
  • apps: Array of app objects with full metadata
  • scan_summary: Aggregated statistics (total_found, healthy, unhealthy, local_count, cloudflare_count)
Each app object includes:
  • Basic info: name, url, type, health_status, port
  • Tunnel info: tunnel_mode, tunnel_hostname (for Cloudflare apps)
  • App metadata: app_id, task_name, dataset_id, version
  • Discovery: discovered_via
  • Full metadata: metadata dictionary with complete /info response and deployment details
Example JSON output:
{
  "apps": [
    {
      "name": "banking77",
      "url": "http://127.0.0.1:8000",
      "type": "local",
      "health_status": "healthy",
      "port": 8000,
      "tunnel_mode": null,
      "tunnel_hostname": null,
      "app_id": "banking77",
      "task_name": "Banking77 Intent Classification",
      "dataset_id": null,
      "version": "1.0.0",
      "metadata": {
        "service": {
          "task": {
            "id": "banking77",
            "name": "Banking77 Intent Classification",
            "version": "1.0.0"
          }
        }
      },
      "discovered_via": "service_records"
    }
  ],
  "scan_summary": {
    "total_found": 1,
    "healthy": 1,
    "unhealthy": 0,
    "local_count": 1,
    "cloudflare_count": 0
  }
}

Options

  • --port-range START:END — Port range to scan (default: 8000:8100)
  • --timeout SECONDS — Health check timeout in seconds (default: 2.0)
  • --api-key KEY — API key for health checks (default: from ENVIRONMENT_API_KEY env var)
  • --json — Output results as JSON instead of table
  • --verbose — Show detailed scanning progress

Integration with Deploy Command

The scan command works seamlessly with the deploy command:
  1. Deploy a local service:
    synth-ai deploy --runtime local --task-app examples/task_apps/banking77/banking77_task_app.py --port 8000 --env .env
    
  2. Scan discovers it:
    synth-ai scan
    # Shows the deployed service with health status
    
  3. Deploy a tunnel:
    synth-ai deploy --runtime tunnel --task-app examples/task_apps/banking77/banking77_task_app.py --port 8001 --env .env --tunnel-mode quick
    
  4. Scan discovers it:
    synth-ai scan --json
    # Shows both local service and tunnel
    

Use Cases

For Developers

  • Quickly see what task apps are running locally
  • Verify deployments are healthy
  • Debug connectivity issues
  • Monitor multiple services

For CI/CD and Automation

  • Programmatically discover deployed services
  • Health check endpoints for monitoring
  • Integration with deployment pipelines
  • Service discovery for testing

For AI Agents

  • Structured JSON output for programmatic consumption
  • Reliable discovery of available services
  • Health status for service selection
  • Metadata for service configuration

Troubleshooting

No apps found

  • Check that services are actually running
  • Verify port range includes the ports your apps use
  • Check that apps have /health endpoints
  • Ensure API key is set if apps require authentication

Apps showing as “unknown”

  • Check network connectivity
  • Verify apps are responding on expected ports
  • Increase timeout with --timeout option
  • Check firewall settings

Tunnel apps not discovered

  • Verify cloudflared processes are running
  • Check tunnel records file exists (~/.synth-ai/services.json)
  • Ensure tunnels were deployed via synth-ai deploy
  • Try --verbose to see discovery progress