{
 "slug": "fly",
 "name": "Fly.io",
 "url": "https://fly.io",
 "domain": "fly.io",
 "category": "hosting",
 "category_name": "Hosting and deploys",
 "tested_at": "2026-10-06",
 "run": "20261006T015555Z",
 "draft": false,
 "reviewed": true,
 "owner_verified": null,
 "origin": "editorial",
 "history": [
  {
   "run": "20261006T015555Z",
   "date": "2026-10-06",
   "level": 2,
   "engine": {
    "runner": "omp",
    "model": "claude-opus-5-5",
    "driver": 2,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   }
  }
 ],
 "level": 2,
 "level_name": "Gets in",
 "level_selfhost": null,
 "entry": "self-start",
 "door": {
  "passed": 1,
  "tries": 1,
  "self_start": true
 },
 "badges": [
  "agent-can-leave"
 ],
 "stages": [
  {
   "key": "in",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: sign-up in a browser"
  },
  {
   "key": "work",
   "label": "Use",
   "state": "no",
   "text": "Work done: 30% of the core"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "unreached",
   "text": "Card checkout",
   "value": "not_tried",
   "route": "card_checkout",
   "why": "no_card"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: nothing to cancel, deletes its account",
   "left": "deleted"
  }
 ],
 "outcomes": [
  {
   "key": "find",
   "label": "Find",
   "state": "yes",
   "text": "Docs agents can read: llms.txt, an OpenAPI and an MCP server",
   "have": [
    "llms_txt",
    "openapi",
    "mcp"
   ]
  },
  {
   "key": "access",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: sign-up in a browser",
   "stage": "in"
  },
  {
   "key": "use",
   "label": "Use",
   "state": "no",
   "text": "Work done: 30% of the core",
   "stage": "work"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "unreached",
   "text": "Card checkout",
   "value": "not_tried",
   "route": "card_checkout",
   "why": "no_card",
   "stage": "pay"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: nothing to cancel, deletes its account",
   "left": "deleted",
   "stage": "leave"
  }
 ],
 "access": [
  {
   "key": "browser_signup",
   "label": "Sign-up in a browser",
   "routes": [],
   "minutes": 4.8,
   "core": "3/10"
  }
 ],
 "minutes": 4.8,
 "next": {
  "to": 3,
  "text": "Next: do half of the core work (now 30%)"
 },
 "stop": null,
 "core": "3/10",
 "scores": {
  "coverage": 18,
  "reliability": 100,
  "resilience": null,
  "setup": 100,
  "surface_coverage": null,
  "docs_accuracy": null,
  "docs_completeness": null
 },
 "parts": {
  "holds_up": null,
  "docs_match": null,
  "setup": 100,
  "security": null,
  "standards": [
   {
    "standard": "MCP",
    "state": "behind",
    "behind": 1,
    "value": "2025-11-25"
   },
   {
    "standard": "MCP discovery",
    "state": "behind",
    "behind": null,
    "value": "legacy"
   },
   {
    "standard": "MCP client registration",
    "state": "current",
    "behind": null,
    "value": "cimd"
   },
   {
    "standard": "OpenAPI",
    "state": "behind",
    "behind": 1,
    "value": "3.1.0"
   }
  ]
 },
 "reliability_method": "first-try",
 "resilience": null,
 "stress": [],
 "surface_audit": null,
 "coverage_core": 30,
 "after_wall": null,
 "coverage_source": "computed",
 "driver": {
  "version": 2,
  "model": "claude-opus-5-5",
  "profile": "full",
  "assisted": false,
  "handoff": null,
  "prompt_sha": "59d395064c20",
  "kb_version": "2",
  "identity": null
 },
 "methodology": 15,
 "rules_date": "2026-10-15",
 "engine": {
  "runner": "omp",
  "model": "claude-opus-5-5",
  "driver": 2,
  "signed": true,
  "inbox": [
   "agentdrives.com"
  ],
  "robots": "start"
 },
 "same_level_drives": 1,
 "drives": 1,
 "works_assisted": null,
 "freshness": "fresh",
 "nothing_to_pay": false,
 "core_gated": false,
 "profiles": {},
 "agent_check": null,
 "agent_pass": null,
 "who_gets_in": {
  "server": {
   "state": "in"
  },
  "signed": {
   "state": "page",
   "kind": "signup",
   "at": "2026-10-12"
  },
  "browser": {
   "state": "in",
   "measured": false
  },
  "our_key": "pending",
  "robots": null,
  "tip": false
 },
 "ladder": {
  "docs": {
   "status": "headless",
   "note": "llms.txt (fly.io and docs.fly.io), .md pages and Accept: text/markdown, Machines and Sprites OpenAPI 3.1.0, auth.md for agents."
  },
  "signup": {
   "status": "browser",
   "note": "Web form only (no CAPTCHA); `fly auth signup` needs a TTY and opens the same web page. auth.md: no agentic registration."
  },
  "verify": {
   "status": "browser",
   "note": "Verification mail arrived in under a minute; the link worked only in a signed-in browser session (headless GET redirected to sign-in)."
  },
  "credentials": {
   "status": "browser",
   "note": "flyctl login approved in the browser (one-time code pasted back); then `fly tokens create org --expiry 24h` headless. Sprites token from the dashboard; Sprites MCP via OAuth consent in the browser.",
   "via": ""
  },
  "first_call": {
   "status": "headless",
   "note": "GET api.machines.dev/v1/apps?org_slug=personal 200; GET api.sprites.dev/v1/sprites 200."
  },
  "first_action": {
   "status": "headless",
   "note": "POST /v1/sprites created a Sprite (201) and exec ran in it. Machines API POST /v1/apps answered 422 'We need your payment information to continue!' (account flagged high risk)."
  },
  "pay": {
   "status": "",
   "grade": "P2",
   "rails": [
    "Card form in the dashboard billing page (Stripe.js)",
    "Prepaid credits from the dashboard (min $25 per docs)",
    "Stripe Projects catalog lists 'flyio/app' (listing only, not confirmed)"
   ],
   "rail_ids": [
    "stripe-elements"
   ],
   "first_party": false,
   "rail_scope": "none",
   "trial_path": "no-card trial",
   "note": "No 402/x402/MPP/L402, no x-payment-info, no registry entries. Buying is a card in the dashboard; our flagged account needs a card preauthorization (< $10) to unlock. No card or wallet, so nothing paid; whether 3DS or other human steps follow is unknown."
  },
  "cancel": {
   "status": "n/a",
   "grade": "n/a",
   "note": "Nothing to cancel: our agent started no paid plan.",
   "docs_note": "No plan or payment started; usage billing with nothing recurring on the trial account.",
   "nothing": "no_plan"
  },
  "delete": {
   "status": "browser",
   "note": "Account deletion only in the web UI (/user/deactivate, documented): checklist, Delete, 'Yes, delete it'. Verified: sign-in 'Invalid email or password', Sprites token 401. Sprites deleted via API (204) and org token revoked via `fly tokens revoke` first.",
   "left": "deleted",
   "account": true
  }
 },
 "routes": [],
 "checkout": null,
 "docs": null,
 "claims": null,
 "pay_options": {
  "checked": "2026-10-06",
  "source": "drive",
  "options": [
   {
    "id": "stripe-elements",
    "name": "Stripe card form",
    "kind": "checkout",
    "first_party": false,
    "lead": false,
    "networks": [],
    "testnet": false
   }
  ],
  "agentic": [],
  "paid": null,
  "exercised": null,
  "detected_grade": null,
  "trial": {
   "no_card": true,
   "card_required": null,
   "free_plan": null
  },
  "owner_fixes": [
   {
    "title": "Accept x402 or MPP on your API",
    "how": "Answer an unpaid call with 402 and a payment challenge, so an agent pays per call or buys credits without an account or a card."
   },
   {
    "title": "List your plans on Stripe Projects",
    "how": "Agents buy a plan with `stripe projects add`, paid with a token under a spend cap the owner sets (projects.dev)."
   }
  ]
 },
 "surfaces": {
  "api": true,
  "openapi": true,
  "cli": true,
  "sdk": true,
  "mcp": "official",
  "llms_txt": true,
  "webhooks": false,
  "sandbox": false
 },
 "surface_notes": {
  "api": "Machines REST (70 paths) and Sprites REST",
  "openapi": "3.1.0 for both, no x-payment-info",
  "mcp": "official: Sprites remote (OAuth, 27 tools, the 25 Nov 2025 spec) and flyctl stdio (60 tools, the 28 Jul 2026 spec)",
  "cli": "flyctl 0.4.112; login needs a PTY and a browser",
  "llms_txt": "fly.io/llms.txt and docs.fly.io/llms.txt + llms-full.txt; robots.txt carries Cloudflare-style 'Content-Signal: search=yes, ai-input=yes, ai-train=yes' (not aipref)"
 },
 "can_do": [
  "Create a Sprite (Linux VM for an agent) and run commands in it over REST or MCP",
  "Checkpoint a Sprite's disk and restore it",
  "Run a web service in a Sprite and publish it on its own HTTPS URL",
  "Create, scope and revoke expiring Fly.io access tokens headless once signed in",
  "Delete Sprites and revoke tokens headless"
 ],
 "cannot_do": [
  {
   "what": "Create an app, Machine or deploy",
   "why": "New account flagged high risk: 422 'We need your payment information to continue!' until a card is preauthorized"
  },
  {
   "what": "Create Managed Postgres",
   "why": "'Your account has been flagged as high risk and cannot create Postgres clusters'"
  },
  {
   "what": "Sign up, verify or get a first credential without a browser",
   "why": "Web form and browser approval only; no agent registration or device flow"
  },
  {
   "what": "Delete the account headless",
   "why": "Only in the web UI"
  }
 ],
 "blockers": [
  "Risk check locks new accounts out of Machines and Postgres until a card preauthorization",
  "Sign-up, verification and login need a browser"
 ],
 "tips_for_owner": [
  "Let flagged trial accounts verify without cards",
  "Offer agent registration or device-flow login",
  "Make email verification work without session",
  "Serve MCP (the 28 Jul 2026 spec) on sprites.dev/mcp",
  "Fix Sprites MCP file and exec schemas",
  "Add a billing API to buy credits",
  "Add account deletion to flyctl"
 ],
 "tips_for_agents": [
  "Start with Sprites: REST with a dashboard token worked on an account locked for Machines.",
  "POST /v1/sprites/{name}/exec?cmd=bash&cmd=-c&cmd=… returns plain output over HTTP, no WebSocket needed.",
  "The Sprites MCP consent defaults to a restricted token with name prefix 'mcp-'; name Sprites to match.",
  "flyctl login needs a PTY: it prints a URL, then accepts a pasted one-time code.",
  "Read https://fly.io/auth.md; create narrow tokens with --expiry instead of using the session.",
  "A 422 on POST /v1/apps means the org needs a card; it will not clear by retrying."
 ],
 "selfhost": null,
 "summary": "On Fly.io an agent can drive Sprites end to end over the documented REST API and the official Sprites MCP: create, exec, checkpoint/restore and a public URL. The Machines side stopped right after sign-up: Fly's risk check flagged the new account and every app, Machine and Postgres action asked for a card, although the docs promise a no-card trial. Sign-up, verification and credentials need a browser; the agent-facing docs (llms.txt, Markdown, OpenAPI 3.1, auth.md) are excellent.",
 "wall": "Risk flag demands card preauth for Machines",
 "plan_scope": "no-card trial (account flagged high risk: Machines and Postgres locked until a card is preauthorized)",
 "robots_stop": null,
 "robots": null,
 "plain": {
  "summary": "Fly.io lets agents run and manage 'Sprites' (small cloud computers) on their own through its documented API, but the bigger Fly product (Machines, app deployment, and databases) needs a credit card. A brand-new account got flagged as suspicious right after sign-up and was locked out of those features until a card was added, even though the free trial is advertised as card-free.",
  "can_do": [
   "Create a cloud sandbox (Sprite) and run commands in it, using the official tools, with no browser needed after sign-up.",
   "Save and restore a snapshot of that sandbox's files.",
   "Put a small web app on a public internet address from inside the sandbox.",
   "Create and cancel access keys without a browser once signed in.",
   "Delete the whole account and its data, though only through the website, not a command."
  ],
  "cannot_do": [
   {
    "what": "Create a virtual server (Machine), deploy an app, or set up a database",
    "why": "The account was flagged as risky and locked until a credit card is added, despite the no-card trial promise."
   },
   {
    "what": "Sign up, confirm the email, or get login credentials without opening a browser",
    "why": "Fly.io only offers a web sign-up form and browser-based login approval; no automated path exists."
   },
   {
    "what": "Delete the account without using the website",
    "why": "There is no command-line or API way to delete an account, only a web page."
   }
  ]
 },
 "plan_gated": [
  {
   "capability": "Reserve a stable egress IP for outbound traffic from a Machine",
   "plan": "paid",
   "evidence": "Capability map plan paid; billing page 'Account Status: Requires a credit card'"
  },
  {
   "capability": "Autoscale Machine count based on a custom metric",
   "plan": "paid",
   "evidence": "Capability map plan paid; billing page 'Account Status: Requires a credit card'"
  },
  {
   "capability": "Purchase a discounted Machine reservation block (compute credit) for a region",
   "plan": "paid",
   "evidence": "Capability map plan paid; billing page 'Account Status: Requires a credit card'"
  },
  {
   "capability": "Set up unified billing across linked organizations",
   "plan": "paid",
   "evidence": "Capability map plan paid; billing page 'Account Status: Requires a credit card'"
  },
  {
   "capability": "Open a support request with the Fly.io engineering support team",
   "plan": "paid",
   "evidence": "Capability map plan paid; billing page 'Account Status: Requires a credit card'"
  }
 ],
 "reply": null,
 "capabilities": [
  {
   "id": "cap-01",
   "group": "Compute",
   "capability": "Create and run a Fly Machine from a container image",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v1/apps/{app_name}/machines",
    "mcp": "fly machines run (via flyctl mcp server)",
    "cli": "fly machine run / fly launch",
    "ui": "Dashboard > App > Machines"
   },
   "check": "GET /v1/apps/{app}/machines/{id} returns state 'started'",
   "source": "https://docs.fly.io/machines/api/machines-resource.md; https://fly.io/machines.md"
  },
  {
   "id": "cap-02",
   "group": "Compute",
   "capability": "Stop, start, restart or delete a Machine",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v1/apps/{app_name}/machines/{id}/stop|start; DELETE .../{id}",
    "mcp": null,
    "cli": "fly machine stop|start|restart|destroy",
    "ui": "Dashboard > App > Machines"
   },
   "check": "GET /v1/apps/{app}/machines/{id} shows updated state (stopped/started) or 404 after delete",
   "source": "https://docs.fly.io/machines/api/machines-resource.md"
  },
  {
   "id": "cap-03",
   "group": "Compute",
   "capability": "Deploy an app from source/Dockerfile across multiple regions",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": "fly launch (deploy-with)",
    "cli": "fly launch / fly deploy",
    "ui": "Dashboard > Launch"
   },
   "check": "fly status shows app with Machines running in the requested regions",
   "source": "https://docs.fly.io/launch/index.md; https://docs.fly.io/getting-started/launch.md"
  },
  {
   "id": "cap-04",
   "group": "Compute",
   "capability": "Scale app by changing Machine count and CPU/RAM size",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v1/apps/{app}/machines/{id} (update config.guest)",
    "mcp": null,
    "cli": "fly scale count / fly scale vm",
    "ui": "Dashboard > App > Scale"
   },
   "check": "fly status / GET machine shows new guest.cpus/memory_mb or machine count",
   "source": "https://docs.fly.io/launch/scale-machine.md; https://docs.fly.io/launch/scale-count.md"
  },
  {
   "id": "cap-05",
   "group": "Agent sandboxes",
   "capability": "Create a persistent Sprite (full Linux computer for an agent) and execute commands in it",
   "weight": "core",
   "plan": "trial",
   "surfaces": {
    "api": "PUT https://api.sprites.dev/v1/sprites/{name}; POST .../exec",
    "mcp": "sprites MCP server (sprite create/exec, per docs.sprites.dev)",
    "cli": "sprite create / sprite exec / sprite console",
    "ui": "Dashboard > Sprites"
   },
   "check": "sprite exec returns command stdout; GET /v1/sprites/{name} shows it running",
   "source": "https://fly.io/sprites.md"
  },
  {
   "id": "cap-06",
   "group": "Agent sandboxes",
   "capability": "Checkpoint a Sprite's filesystem and restore to a prior checkpoint",
   "weight": "core",
   "plan": "trial",
   "surfaces": {
    "api": "Sprites management API (checkpoint endpoints)",
    "mcp": null,
    "cli": "sprite-env (inside Sprite)",
    "ui": "Dashboard > Sprites > checkpoints"
   },
   "check": "After restore, files modified post-checkpoint are reverted (read back via sprite exec cat)",
   "source": "https://fly.io/sprites.md"
  },
  {
   "id": "cap-07",
   "group": "Agent sandboxes",
   "capability": "Expose a Sprite on its own public/private HTTPS URL",
   "weight": "core",
   "plan": "trial",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "sprite config (URL visibility setting)",
    "ui": "Dashboard > Sprites > URL settings"
   },
   "check": "curl to the Sprite's HTTPS URL returns the app's response and wakes the Sprite",
   "source": "https://fly.io/sprites.md"
  },
  {
   "id": "cap-08",
   "group": "Database",
   "capability": "Create a Managed Postgres cluster",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly mpg create",
    "ui": "Dashboard > Create > Managed Postgres"
   },
   "check": "fly mpg list / dashboard shows the new cluster with status running",
   "source": "https://fly.io/mpg.md"
  },
  {
   "id": "cap-09",
   "group": "Database",
   "capability": "Attach a Postgres cluster to an app (sets DATABASE_URL secret)",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly mpg attach",
    "ui": "Dashboard > App > Postgres"
   },
   "check": "fly secrets list on the app shows DATABASE_URL set, app connects successfully",
   "source": "https://fly.io/mpg.md"
  },
  {
   "id": "cap-10",
   "group": "Database",
   "capability": "Connect to Postgres via psql or local proxy",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly mpg connect / fly mpg proxy",
    "ui": null
   },
   "check": "psql session opens and SELECT 1 returns a row",
   "source": "https://fly.io/mpg.md"
  },
  {
   "id": "cap-11",
   "group": "Database",
   "capability": "Restore Postgres cluster from backup or point-in-time",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly mpg restore",
    "ui": "Dashboard > Postgres > Backups"
   },
   "check": "New cluster appears with data matching the chosen backup/point in time",
   "source": "https://fly.io/mpg.md"
  },
  {
   "id": "cap-12",
   "group": "Database",
   "capability": "Manage additional databases, schemas and users on a Postgres cluster",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly mpg databases / fly mpg users",
    "ui": "Dashboard > Postgres > Databases"
   },
   "check": "fly mpg databases list shows the newly created database",
   "source": "https://fly.io/mpg.md"
  },
  {
   "id": "cap-13",
   "group": "Database",
   "capability": "Enable Postgres extensions (pgvector, PostGIS, etc.)",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly mpg",
    "ui": "Dashboard > Postgres > Extensions"
   },
   "check": "psql \\dx shows the extension installed",
   "source": "https://fly.io/mpg.md"
  },
  {
   "id": "cap-14",
   "group": "Storage",
   "capability": "Create and attach a persistent Volume to a Machine",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v1/apps/{app}/volumes",
    "mcp": null,
    "cli": "fly volumes create",
    "ui": "Dashboard > App > Volumes"
   },
   "check": "fly volumes list shows volume attached to the Machine; data written persists across restart",
   "source": "https://docs.fly.io/volumes/overview.md"
  },
  {
   "id": "cap-15",
   "group": "Storage",
   "capability": "Snapshot and restore a Volume, or fork it into a new copy",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly volumes snapshot / fly volumes fork",
    "ui": "Dashboard > App > Volumes"
   },
   "check": "fly volumes list shows a new volume created from the snapshot/fork with the source data",
   "source": "https://docs.fly.io/volumes/overview.md"
  },
  {
   "id": "cap-16",
   "group": "Storage",
   "capability": "Extend a Volume's size",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly volumes extend",
    "ui": "Dashboard > App > Volumes"
   },
   "check": "fly volumes list / df -h inside Machine shows increased size",
   "source": "https://docs.fly.io/volumes/overview.md"
  },
  {
   "id": "cap-17",
   "group": "Secrets & config",
   "capability": "Set and manage app secrets (environment variables)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly secrets set/unset/list",
    "ui": "Dashboard > App > Secrets"
   },
   "check": "fly secrets list shows the secret name (value hidden); app env has it after redeploy",
   "source": "https://docs.fly.io/apps/secrets.md; https://docs.fly.io/flyctl/index.md"
  },
  {
   "id": "cap-18",
   "group": "Networking",
   "capability": "Allocate a public IP address / custom domain with TLS certificate for an app",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "Certificates resource API",
    "mcp": null,
    "cli": "fly ips allocate / fly certs create",
    "ui": "Dashboard > App > Certificates"
   },
   "check": "fly certs show <domain> reports certificate issued and verified",
   "source": "https://docs.fly.io/flyctl/index.md; https://docs.fly.io/networking/custom-domain.md"
  },
  {
   "id": "cap-19",
   "group": "Networking",
   "capability": "Connect to apps privately over WireGuard / 6PN private network",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly wireguard create",
    "ui": "Dashboard > Org > WireGuard"
   },
   "check": "wg0 tunnel established; private .internal DNS name resolves and is reachable",
   "source": "https://docs.fly.io/networking/private-networking.md; https://docs.fly.io/networking/index.md"
  },
  {
   "id": "cap-20",
   "group": "Networking",
   "capability": "Route private-only services through Flycast instead of the public internet",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly config (flycast service)",
    "ui": null
   },
   "check": "App reachable via its Flycast 6PN address but not from the public internet",
   "source": "https://docs.fly.io/networking/flycast.md"
  },
  {
   "id": "cap-21",
   "group": "Networking",
   "capability": "Reserve a stable egress IP for outbound traffic from a Machine",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly ips allocate (egress)",
    "ui": null
   },
   "check": "Outbound request from the Machine shows the reserved IP at a remote echo endpoint",
   "source": "https://docs.fly.io/networking/egress-ips.md"
  },
  {
   "id": "cap-22",
   "group": "Networking",
   "capability": "Run UDP/TCP services with custom port handlers",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly.toml [[services]] config",
    "ui": null
   },
   "check": "nc/udp client against the app's port receives a response",
   "source": "https://docs.fly.io/networking/udp-and-tcp.md"
  },
  {
   "id": "cap-23",
   "group": "Scaling behavior",
   "capability": "Configure autostop/autostart of Machines based on traffic",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly.toml auto_stop_machines/auto_start_machines",
    "ui": "Dashboard > App > Settings"
   },
   "check": "Machine transitions to 'stopped' after idle period, then 'started' on next request (fly status)",
   "source": "https://docs.fly.io/launch/autostop-autostart.md"
  },
  {
   "id": "cap-24",
   "group": "Scaling behavior",
   "capability": "Autoscale Machine count based on a custom metric",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly autoscale (blueprint-based)",
    "ui": null
   },
   "check": "fly status shows Machine count changing in response to the configured metric threshold",
   "source": "https://docs.fly.io/launch/autoscale-by-metric.md; https://docs.fly.io/blueprints/autoscale-machines.md"
  },
  {
   "id": "cap-25",
   "group": "Observability",
   "capability": "View app logs",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly logs",
    "ui": "Dashboard > App > Logs"
   },
   "check": "fly logs streams output matching a request just made against the app",
   "source": "https://docs.fly.io/flyctl/index.md"
  },
  {
   "id": "cap-26",
   "group": "Observability",
   "capability": "View deployment status and release history",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly status / fly releases",
    "ui": "Dashboard > App > Activity"
   },
   "check": "fly releases lists the deploy just performed with its version and timestamp",
   "source": "https://docs.fly.io/flyctl/index.md"
  },
  {
   "id": "cap-27",
   "group": "Observability",
   "capability": "View Postgres performance metrics and logs",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Dashboard > Postgres > Metrics"
   },
   "check": "Dashboard metrics page shows CPU/connection graphs updating over time",
   "source": "https://docs.fly.io/postgres/metrics.md; https://fly.io/mpg.md"
  },
  {
   "id": "cap-28",
   "group": "Agent connectivity",
   "capability": "Connect a Sprite to an external service (GitHub, Slack, OpenRouter, any HTTP API) via a Connector without exposing the credential",
   "weight": "secondary",
   "plan": "trial",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Dashboard > Sprites > Connectors"
   },
   "check": "Sprite call through the connector succeeds; sprite filesystem/env never contains the provider token",
   "source": "https://fly.io/sprites.md"
  },
  {
   "id": "cap-29",
   "group": "Agent connectivity",
   "capability": "Deploy and expose a Model Context Protocol (MCP) server on Fly.io",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly mcp launch",
    "ui": null
   },
   "check": "MCP client tools/list against the deployed URL returns the server's tool list",
   "source": "https://docs.fly.io/model-context-protocol/index.md; https://docs.fly.io/model-context-protocol/launch.md"
  },
  {
   "id": "cap-30",
   "group": "Compute",
   "capability": "Run multi-container Machines (sidecar processes in one Machine)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "config.containers in Machine config",
    "mcp": null,
    "cli": "fly.toml [[containers]]",
    "ui": null
   },
   "check": "GET machine config shows multiple entries under containers, each reporting running",
   "source": "https://docs.fly.io/machines/guides-examples/multi-container-machines.md"
  },
  {
   "id": "cap-31",
   "group": "Compute",
   "capability": "Run one-off commands/consoles inside a Machine",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly ssh console / fly machine exec",
    "ui": "Dashboard > App > Console"
   },
   "check": "fly ssh console returns a live shell session in the target Machine",
   "source": "https://docs.fly.io/apps/overview.md; https://docs.fly.io/flyctl/index.md"
  },
  {
   "id": "cap-32",
   "group": "App lifecycle",
   "capability": "Move an app between organizations",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": "fly apps move",
    "ui": "Dashboard > App > Settings"
   },
   "check": "fly apps list under the destination org shows the app",
   "source": "https://docs.fly.io/apps/move-app-org.md"
  },
  {
   "id": "cap-33",
   "group": "App lifecycle",
   "capability": "Delete an app",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "DELETE app via Apps resource",
    "mcp": null,
    "cli": "fly apps destroy",
    "ui": "Dashboard > App > Settings"
   },
   "check": "fly apps list no longer shows the app",
   "source": "https://docs.fly.io/apps/delete.md"
  },
  {
   "id": "cap-34",
   "group": "Billing",
   "capability": "Purchase a discounted Machine reservation block (compute credit) for a region",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Dashboard > Billing > Reservations"
   },
   "check": "Dashboard billing page lists the active reservation block and its monthly credit",
   "source": "https://docs.fly.io/about/pricing.md"
  },
  {
   "id": "cap-35",
   "group": "Billing",
   "capability": "Set up unified billing across linked organizations",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "Dashboard > Billing"
   },
   "check": "Dashboard shows linked org's usage rolling up onto the parent billing org's invoice",
   "source": "https://docs.fly.io/about/billing.md"
  },
  {
   "id": "cap-36",
   "group": "Support",
   "capability": "Open a support request with the Fly.io engineering support team",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "fly.io/support or Dashboard > Support"
   },
   "check": "Support ticket appears in the account's support ticket history with a response",
   "source": "https://fly.io/support/; https://fly.io/sprites.md"
  }
 ],
 "attempts": [
  {
   "t": "00:18",
   "cap": "discovery",
   "capability": "robots.txt / aipref",
   "task": "Read robots.txt for agent rules and AI preferences",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "https://fly.io/robots.txt 200: 'User-agent: *', 'Content-Signal: search=yes, ai-input=yes, ai-train=yes', 'Allow: /', 'Disallow: /dashboard'. No aipref Content-Usage line; no Content-Usage header seen.",
   "notes": "Cloudflare Content Signals syntax (yes/no values, parses), not IETF aipref. Response Link header points to /.well-known/api-catalog, /.well-known/ard.json, /.well-known/ai-catalog.json, /llms.txt."
  },
  {
   "t": "00:18",
   "cap": "discovery",
   "capability": "llms.txt",
   "task": "Fetch llms.txt",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "https://fly.io/llms.txt 200 text/plain, H1 '# Fly.io', links .md pages, SDKs, OpenAPI specs, Sprites MCP; https://docs.fly.io/llms.txt and llms-full.txt 200.",
   "notes": "Asks agents to send an AI-Agent request header."
  },
  {
   "t": "00:25",
   "cap": "discovery",
   "capability": "AI catalog / API catalog / agent card",
   "task": "Probe well-known discovery files",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "/.well-known/ai-catalog.json 200 application/json (Sprites MCP server card + Machines OpenAPI entries); /.well-known/api-catalog 200 application/linkset+json (RFC 9727); /.well-known/mcp/server-card.json 200 application/json; /.well-known/agent-card.json and /.well-known/agent.json 404; /.well-known/ucp 404; /.well-known/oauth-protected-resource and oauth-authorization-server on fly.io 404; /SKILL.md 404; /auth.md 200 text/markdown; /.well-known/agent-skills/index.json 200 application/json.",
   "notes": "No A2A card."
  },
  {
   "t": "00:26",
   "cap": "discovery",
   "capability": "auth.md",
   "task": "Read fly.io/auth.md for an agent sign-up path",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "auth.md: 'Fly.io does not support agentic registration. There is no anonymous identity endpoint, no claim ceremony, and no agent_auth block'. Every credential starts with a human signed in; flyctl session, scoped macaroon tokens, Sprites MCP over OAuth.",
   "notes": "Clear, automated agent auth guide."
  },
  {
   "t": "01:20",
   "cap": "docs",
   "capability": "docs",
   "task": "Find docs, API reference, CLI, auth guide",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "docs.fly.io (Mintlify) with llms.txt, .md pages, Machines + Sprites OpenAPI 3.1, auth.md for agents."
  },
  {
   "t": "01:50",
   "cap": "signup",
   "capability": "signup",
   "task": "Sign up with `fly auth signup` headless",
   "route": "cli",
   "documented": true,
   "result": "failed",
   "verified": false,
   "evidence": "Without a TTY: 'Error: fly auth login requires an interactive terminal. In headless environments, set FLY_API_TOKEN'. With a PTY it prints https://fly.io/app/auth/cli/<id> to open in a browser.",
   "notes": "Sign-up itself is a web form (email/password or GitHub/Google).",
   "quality": {
    "error_legibility": "clear",
    "recoverable": "yes"
   }
  },
  {
   "t": "02:20",
   "cap": "signup",
   "capability": "signup",
   "task": "Sign up through the web form from the CLI link",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "https://fly.io/app/sign-up: 'Sign up with email' -> Preferred Name/Email/Password -> 'Create My Account' -> /welcome survey. No CAPTCHA shown (pw captcha signals all false).",
   "notes": "Session cookie did not persist across our pw calls, so later steps signed in again."
  },
  {
   "t": "02:50",
   "cap": "verify",
   "capability": "verify",
   "task": "Open the verification link from our inbox",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Mail 'Activate your Fly.io account' from support@fly.io arrived in under a minute. opened while signed in in the browser -> dashboard.",
   "notes": "Headless GET without a session only redirected to sign-in; verification needed the browser session."
  },
  {
   "t": "03:30",
   "cap": "signup",
   "capability": "account risk check",
   "task": "Use the new account",
   "route": "browser",
   "documented": true,
   "result": "blocked",
   "verified": true,
   "evidence": "Dashboard banner: 'Add a payment method to keep using our platform. We think you're a human, but our system does not. Click here and add a payment method to unlock your account'. /high-risk-unlock: 'We need to setup a credit card and perform a preauthorization transaction for under $10 to unlock your account.' Machines limit 0/0.",
   "notes": "Fly's own risk scoring flagged the fresh account (signal not stated). Docs say the free trial needs no card (docs.fly.io/about/free-trial)."
  },
  {
   "t": "04:40",
   "cap": "credentials",
   "capability": "credentials",
   "task": "Complete flyctl login (PKCE code from CLI sign-in page) and create a scoped token",
   "route": "cli",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Browser CLI sign-in page showed a one-time code, pasted into `fly auth signup` -> exit 0; `fly auth whoami` -> the agent's inbox; `fly tokens create org -o personal --expiry 24h` printed a 'FlyV1 fm2_' token; GET https://api.machines.dev/v1/apps?org_slug=personal with it -> 200 {\"total_apps\":0,\"apps\":[]}.",
   "notes": "Login approval is a browser step by design; token creation after that is headless."
  },
  {
   "t": "04:50",
   "cap": "first_call",
   "capability": "The first call",
   "task": "First authenticated Machines API call",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET /v1/apps?org_slug=personal -> 200 {\"total_apps\":0,\"apps\":[]}"
  },
  {
   "t": "05:00",
   "cap": "cap-01",
   "capability": "Create and run a Fly Machine from a container image",
   "task": "Create an app to hold a Machine (Machines API), then run nginx",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": true,
   "evidence": "POST /v1/apps -> 422 payment information required; `fly apps create` -> same error. No app means no Machine.",
   "notes": "Account flagged high risk; card preauthorization required. We never enter a card.",
   "quality": {
    "error_legibility": "clear",
    "recoverable": "no"
   }
  },
  {
   "t": "05:20",
   "cap": "discovery",
   "capability": "MCP server/discover (Sprites remote)",
   "task": "server/discover on https://sprites.dev/mcp",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Unauthenticated: 401 WWW-Authenticate: Bearer resource_metadata=\"https://sprites.dev/.well-known/oauth-protected-resource\", scope=\"sprites:read sprites:write\". PRM 200 JSON; AS metadata 200 with client_id_metadata_document_supported: true, registration_endpoint, S256 only. With OAuth token: server/discover -> HTTP 400 JSON-RPC -32601 Method not found (legacy). initialize offering 2026-07-28 -> protocolVersion 2025-11-25, serverInfo sprites 1.0.0, SSE reply, no Mcp-Session-Id. Server card at https://sprites.dev/mcp/server-card (application/mcp-server-card+json) lists supportedProtocolVersions [2025-11-25].",
   "notes": "Legacy server, streamable HTTP, 27 tools."
  },
  {
   "t": "05:30",
   "cap": "discovery",
   "capability": "MCP server/discover (flyctl stdio)",
   "task": "server/discover on `fly mcp server` (stdio, official, experimental)",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "server/discover -> result supportedVersions [2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05], serverInfo 'FlyMCP' 0.4.112; tools/list 60 tools (fly-apps-create, fly-machine-run, fly-volumes-*, fly-secrets-*, ...). initialize offering 2026-07-28 answered protocolVersion 2025-11-25.",
   "notes": "Stateless tools/call with 2026-07-28 _meta works (fly-orgs-list returned personal org)."
  },
  {
   "t": "05:40",
   "cap": "cap-01",
   "capability": "Create and run a Fly Machine from a container image",
   "task": "Same via flyctl MCP server tool fly-apps-create",
   "route": "mcp",
   "documented": true,
   "result": "blocked",
   "verified": true,
   "evidence": "tools/call fly-apps-create {org: personal} -> error -32603 'Error: We need your payment information to continue! Add a credit card or buy credit'",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "07:40",
   "cap": "cap-05",
   "capability": "Create a persistent Sprite (full Linux computer for an agent) and execute commands in it",
   "task": "Create a Sprite via REST and run a command",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST https://api.sprites.dev/v1/sprites {name: ad-an inbox} -> 201 status cold, url https://ad-an inbox-b33cw.sprites.app; GET /v1/sprites/ad-an inbox -> status warm; POST /exec?cmd=bash&cmd=-c&cmd=... -> 200 'Linux ad-an inbox 6.12.105-fly ... hello-agentdrives'.",
   "notes": "Sprites token came from the dashboard (browser); Sprites worked without a card despite the account risk flag.",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "08:00",
   "cap": "cap-06",
   "capability": "Checkpoint a Sprite's filesystem and restore to a prior checkpoint",
   "task": "Checkpoint, change a file, restore, read it back",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "POST /checkpoint -> NDJSON 'Checkpoint v2 created successfully'; GET /checkpoints lists v2; file changed to CHANGED; POST /checkpoints/v2/restore -> 'Restore from v2 complete'; exec cat -> 'hello-agentdrives' (original).",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "08:25",
   "cap": "cap-07",
   "capability": "Expose a Sprite on its own public/private HTTPS URL",
   "task": "Run a web service on 8080 and make the URL public",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "PUT /services/web {cmd: python3 -m http.server 8080, http_port 8080} -> started; PUT /v1/sprites/ad-an inbox {url_settings:{auth:public}} -> 200; GET https://ad-an inbox-b33cw.sprites.app/note.txt -> 200 'hello-agentdrives'.",
   "notes": "Capability map lists api: null; the Sprites OpenAPI has url_settings on PUT /v1/sprites/{name}.",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "09:20",
   "cap": "discovery",
   "capability": "markdown docs",
   "task": "Check Accept: text/markdown and .md URLs",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "docs.fly.io/about/pricing with Accept: text/markdown -> 200 content-type text/markdown, vary includes Accept; docs.fly.io/about/pricing.md -> 200 text/markdown; fly.io/pricing.md 200.",
   "notes": "both"
  },
  {
   "t": "09:30",
   "cap": "discovery",
   "capability": "OpenAPI",
   "task": "Fetch Machines and Sprites OpenAPI",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "https://docs.machines.dev/openapi.json openapi 3.1.0, 70 paths; https://api.sprites.dev/openapi.json openapi 3.1.0. No x-payment-info / x-service-info."
  },
  {
   "t": "10:00",
   "cap": "pay",
   "capability": "pay",
   "task": "Probe agent payment rails and the purchase path",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "Unauthenticated api.machines.dev -> 401 (WWW-Authenticate: Basic), api.sprites.dev -> 401 JSON; no 402, no PAYMENT-REQUIRED, no WWW-Authenticate: Payment/L402. x402./mpp./agents.fly.io do not resolve. No x-payment-info in either OpenAPI. /.well-known/ucp 404. llms-full.txt has 0 hits for x402, MPP, 402, Shared Payment Token, Stripe Projects, USDC. mpp.dev/api/services and the x402 Bazaar: no fly.io/sprites.dev/machines.dev entries. projects.dev page lists provider 'flyio/app' (Stripe Projects listing, not confirmed). Purchase path: dashboard Billing 'Add credit card' (Stripe.js frames) or prepaid credits (min $25 per docs); high-risk unlock needs a card preauthorization under $10.",
   "notes": "No wallet/card: nothing paid. No billing API in flyctl."
  },
  {
   "t": "11:40",
   "cap": "cap-05",
   "capability": "Create a persistent Sprite (full Linux computer for an agent) and execute commands in it",
   "task": "Same through the Sprites MCP server (OAuth)",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "DCR POST /oauth/register 201; browser consent ('Create a restricted token' default, prefix mcp-); token exchange 200. create_sprite 'ad-an inbox-mcp' -> isError \"sprite name must start with 'mcp-'\"; create_sprite mcp-ad091 -> sprite object; exec cmd=uname -> 'Linux' (with stream framing bytes); get_sprite_info confirms it.",
   "notes": "exec cmd takes one string (shell quoting broke); file_read/file_write demanded an undocumented workingDir param.",
   "quality": {
    "error_legibility": "clear",
    "recoverable": "yes"
   }
  },
  {
   "t": "13:10",
   "cap": "cap-03",
   "capability": "Deploy an app from source/Dockerfile across multiple regions",
   "task": "fly launch a Dockerfile app (nginx) in fra",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": true,
   "evidence": "`fly launch --no-deploy` -> 'Error: failed to determine region: failed to get placements: requested machine count exceeds organization limit' (Machines limit 0/0 on the locked account).",
   "quality": {
    "error_legibility": "vague",
    "recoverable": "no"
   }
  },
  {
   "t": "13:12",
   "cap": "cap-08",
   "capability": "Create a Managed Postgres cluster",
   "task": "fly mpg create basic in fra",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": true,
   "evidence": "'Error: failed creating managed postgres cluster: ... Your account has been flagged as high risk and cannot create Postgres clusters'",
   "notes": "MPG is a paid product anyway (capability map plan: paid); here the risk flag is what answered.",
   "quality": {
    "error_legibility": "clear",
    "recoverable": "no"
   }
  },
  {
   "t": "13:20",
   "cap": "cap-02",
   "capability": "Stop, start, restart or delete a Machine",
   "task": "Needs a Machine",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No Machine could be created: app creation returns 422 'We need your payment information to continue!' (see )."
  },
  {
   "t": "13:20",
   "cap": "cap-04",
   "capability": "Scale app by changing Machine count and CPU/RAM size",
   "task": "Needs a Machine",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No Machine could be created: app creation returns 422 'We need your payment information to continue!' (see )."
  },
  {
   "t": "13:20",
   "cap": "cap-09",
   "capability": "Attach a Postgres cluster to an app (sets DATABASE_URL secret)",
   "task": "Needs a Postgres cluster",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Needs a Managed Postgres cluster; `fly mpg create` was refused: 'Your account has been flagged as high risk and cannot create Postgres clusters'."
  },
  {
   "t": "13:20",
   "cap": "cap-10",
   "capability": "Connect to Postgres via psql or local proxy",
   "task": "Needs a Postgres cluster",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Needs a Managed Postgres cluster; `fly mpg create` was refused: 'Your account has been flagged as high risk and cannot create Postgres clusters'."
  },
  {
   "t": "14:00",
   "cap": "cap-19",
   "capability": "Connect to apps privately over WireGuard / 6PN private network",
   "task": "Create a WireGuard peer for the org",
   "route": "cli",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "`fly wireguard create personal fra ad091peer` created the peer ('fly wireguard list' shows ad091peer fra fdaa:cf:af13:...); writing the config failed because our target folder did not exist (our mistake), and there was no app to reach over 6PN.",
   "notes": "Peer removed afterwards with `fly wireguard remove`."
  },
  {
   "t": "14:05",
   "cap": "cap-28",
   "capability": "Connect a Sprite to an external service (GitHub, Slack, OpenRouter, any HTTP API) via a Connector without exposing the credential",
   "task": "List and create a Connector",
   "route": "api",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "GET /v1/oauth/connections -> 200 {\"connections\":[]}. Creating one needs a real provider API key (OpenRouter, Upstash...) or an OAuth grant at a third party; our identity has none."
  },
  {
   "t": "14:10",
   "cap": "cap-14",
   "capability": "Create and attach a persistent Volume to a Machine",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-15",
   "capability": "Snapshot and restore a Volume, or fork it into a new copy",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-16",
   "capability": "Extend a Volume's size",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-17",
   "capability": "Set and manage app secrets (environment variables)",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-18",
   "capability": "Allocate a public IP address / custom domain with TLS certificate for an app",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-20",
   "capability": "Route private-only services through Flycast instead of the public internet",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-22",
   "capability": "Run UDP/TCP services with custom port handlers",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-23",
   "capability": "Configure autostop/autostart of Machines based on traffic",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-25",
   "capability": "View app logs",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-26",
   "capability": "View deployment status and release history",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-29",
   "capability": "Deploy and expose a Model Context Protocol (MCP) server on Fly.io",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-30",
   "capability": "Run multi-container Machines (sidecar processes in one Machine)",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-31",
   "capability": "Run one-off commands/consoles inside a Machine",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-32",
   "capability": "Move an app between organizations",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-33",
   "capability": "Delete an app",
   "task": "Needs a Fly app / Machine",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Every Machines-side resource hangs off an app; app creation returned 422 'We need your payment information to continue!' on the risk-flagged account (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-11",
   "capability": "Restore Postgres cluster from backup or point-in-time",
   "task": "Needs a Managed Postgres cluster",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Cluster creation refused: 'flagged as high risk' (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-12",
   "capability": "Manage additional databases, schemas and users on a Postgres cluster",
   "task": "Needs a Managed Postgres cluster",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Cluster creation refused: 'flagged as high risk' (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-13",
   "capability": "Enable Postgres extensions (pgvector, PostGIS, etc.)",
   "task": "Needs a Managed Postgres cluster",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Cluster creation refused: 'flagged as high risk' (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-27",
   "capability": "View Postgres performance metrics and logs",
   "task": "Needs a Managed Postgres cluster",
   "route": "cli",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "Cluster creation refused: 'flagged as high risk' (see )."
  },
  {
   "t": "14:10",
   "cap": "cap-21",
   "capability": "Reserve a stable egress IP for outbound traffic from a Machine",
   "task": "Paid feature",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "Capability map: plan paid; billing page: 'Account Status: Requires a credit card'. Not attempted."
  },
  {
   "t": "14:10",
   "cap": "cap-24",
   "capability": "Autoscale Machine count based on a custom metric",
   "task": "Paid feature",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "Capability map: plan paid; billing page: 'Account Status: Requires a credit card'. Not attempted."
  },
  {
   "t": "14:10",
   "cap": "cap-34",
   "capability": "Purchase a discounted Machine reservation block (compute credit) for a region",
   "task": "Paid feature",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "Capability map: plan paid; billing page: 'Account Status: Requires a credit card'. Not attempted."
  },
  {
   "t": "14:10",
   "cap": "cap-35",
   "capability": "Set up unified billing across linked organizations",
   "task": "Paid feature",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "Capability map: plan paid; billing page: 'Account Status: Requires a credit card'. Not attempted."
  },
  {
   "t": "14:10",
   "cap": "cap-36",
   "capability": "Open a support request with the Fly.io engineering support team",
   "task": "Paid feature",
   "route": "none",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "Capability map: plan paid; billing page: 'Account Status: Requires a credit card'. Not attempted."
  },
  {
   "t": "16:00",
   "cap": "cancel",
   "capability": "cancel",
   "task": "Cancel a plan",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "No plan or card was started; Fly bills pay-as-you-go with no subscription to cancel on a trial account."
  },
  {
   "t": "16:40",
   "cap": "delete",
   "capability": "delete",
   "task": "Delete the account and its data",
   "route": "browser",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "Docs: 'go to Account > Settings > Delete Account (https://fly.io/user/deactivate)'. Page showed a checklist (Organizations/Apps/Certificates/Extensions/Managed Postgres: No issues) -> Delete -> 'Yes, delete it' -> redirected to fly.io. Sign-in afterwards: 'Invalid email or password'; Sprites token -> 401; flyctl whoami -> not authenticated.",
   "notes": "No CLI/API route for account deletion. Before that: Sprites deleted via DELETE /v1/sprites/{name} -> 204 (list empty), org token revoked with `fly tokens revoke` (API then 401 'root banned')."
  }
 ],
 "stale": false,
 "icon": "/logos/fly.png",
 "monitored": false,
 "verdict": "Gets in on its own: L2 · Gets in. Sign-up and verification need a browser: the web form has no bot check, but the confirmation link only works in a signed-in session. Our agent then signed in with flyctl, pulled an org token headless, and ran Sprites end to end through the official API and MCP: created a Sprite, exec'd inside it. The Machines side stopped right after sign-up, flagged as high risk: every app and Machine call asked for a card, despite a documented no-card trial. Nothing was bought, so nothing to cancel. Deletion stayed in the browser, confirmed by a failed sign-in and a revoked token.",
 "page": "https://agentdrives.com/tools/fly?via=api"
}