Skyvern Documentation Audit
Skyvern ships a large, broadly competent docs surface — 186 URLs, an llms.txt index, SDK guides for two languages, MCP wiring for four assistants, and a per-block self-host story. But underneath the surface there are two parallel doc trees that disagree with each other, a pricing/credits model whose numbers don't reconcile across three pages, contradictory "default engine" and "install command" guidance, and several advertised resources that 404. For an agent-first developer platform, the inconsistency is the headline issue: an LLM consuming these docs will encounter the same fact stated two or three different ways depending on which subtree it crawled.
1. Two parallel doc trees serve overlapping, contradictory content (critical)
Location: /docs/cloud/getting-started/*, /docs/developers/getting-started/*, and shortcut paths like /docs/getting-started/quickstart
Problem: The sitemap exposes a /docs/cloud/... tree and a /docs/developers/... tree that cover the same topics (introduction, core-concepts, quickstart, mcp, ai-agents-quickstart, run-from-code, browser-sessions). Shortcut paths like /docs/getting-started/quickstart and /docs/getting-started/introduction ALSO resolve, returning content that doesn't match either subtree exactly. The two quickstart pages disagree on the local-setup command (skyvern quickstart vs skyvern init); the features/optimization pages on Browser Sessions are near-duplicates listing parameters twice. The MCP guide lives at three URLs: /docs/getting-started/mcp, /docs/cloud/getting-started/mcp, and /docs/developers/getting-started/mcp.
Consequence: Agents indexing the docs see the same fact two or three times with conflicting details and have no signal which is canonical. Developers searching Google can land on any of the three quickstart URLs and run a setup command that doesn't exist on the other page. SEO is also fragmented across duplicates with no canonical link signaled.
The fix: Pick one canonical path per concept. Either (a) collapse /docs/cloud/... and /docs/developers/... into a single tree with audience tabs inside each page, or (b) keep both but make every duplicate page a hard redirect to one canonical URL. Add <link rel="canonical"> to every duplicate. Remove the bare /docs/getting-started/* shortcut routes or 301 them.
2. skyvern quickstart vs skyvern init — two different bootstrap commands for the same flow (critical)
Location: /docs/getting-started/quickstart vs /docs/developers/getting-started/quickstart
Problem: The first page tells local users to run skyvern quickstart for interactive setup. The developer quickstart, covering the same local-setup step, tells them to run skyvern init. The GitHub README also says skyvern quickstart. The MCP guide additionally recommends skyvern quickstart to generate SKYVERN_BASE_URL and SKYVERN_API_KEY.
Consequence: Whichever command isn't real will fail with "unknown command" and the developer has no way to know which page is current. If both exist, the docs never explain how they differ. An agent that copies the developer quickstart verbatim will hit an error on a clean install.
The fix: Pick one. State it once. If both commands exist (e.g., init is a subset of quickstart), document both on a single page with a clear "when to use which" line, and update all four cross-references (two quickstarts, README, MCP local mode) in lockstep.
3. Credits math doesn't reconcile across pricing, billing, and cost-control pages — and the implied ratio isn't even constant (critical)
Location: /pricing, /docs/cloud/account-settings/billing-usage, /docs/developers/optimization/cost-control
Problem: Three pages describe the same plan tiers with three different units that don't multiply out:
- Billing-usage and pricing: Free = 1,000 credits, Hobby = 30,000, Pro = 150,000.
- Cost-control: Free ≈ 170 actions, Hobby ≈ 1,200, Pro ≈ 6,200.
- Billing-usage states "Skyvern charges per browser action" and gives examples ("login flow ~3 credits, form fill ~11 credits"), implying credits ≈ actions.
If credits and actions are interchangeable, the cost-control numbers are wrong. But the implied credit-to-action ratio drifts across plans: Free is 1,000/170 ≈ 5.9×, Hobby is 30,000/1,200 = 25×, Pro is 150,000/6,200 ≈ 24×. There is no defined relationship — even the conversion factor isn't constant.
Consequence: A developer trying to estimate monthly cost — the single most important pricing question — gets answers that vary by an order of magnitude depending on which page they read and which plan they're on. Procurement conversations and ROI calculations will be wrong.
The fix: Define one unit ("credit" or "action") and stick to it everywhere. Publish the exact conversion (e.g., "1 action = 1 credit," or "1 action averages N credits depending on step type"). Reconcile all three pages and the changelog entry for v1.0.8 ("per-action billing model").
4. Pricing page and billing-usage page disagree on which plan unlocks webhooks (significant)
Location: /pricing vs /docs/cloud/account-settings/billing-usage
Problem: The billing-usage table lists "Webhooks, geo-targeting, community support" as Free-plan features. The pricing page describes Hobby as "Everything in Free plus priority support, faster execution, and webhook integrations" — implying webhooks are a Hobby upgrade. The two pages also disagree on support tier names (billing-usage: Hobby has "email support"; pricing: Hobby has "priority support").
Consequence: Users select the Free plan expecting webhook delivery they may not actually get, or they overpay for Hobby thinking they need it to enable webhooks. Either way someone is going to file a support ticket.
The fix: Single source of truth for the feature matrix — generate the pricing page table and the billing-usage table from the same data file. Reconcile webhook entitlement and support-tier naming.
5. Default engine contradicts itself across UI, SDK, and API — and the UI's engine count doesn't match the API enum (significant)
Location: /docs/cloud/getting-started/run-your-first-task, /docs/developers/features/code-caching, /docs/getting-started/core-concepts, /docs/api-reference/agent/run-a-task
Problem: The run-your-first-task page lists three engines in the Cloud UI: "Skyvern 1.0", "Skyvern 2.0", and "Skyvern 2.0 with Code (default)". Core-concepts and the API reference list five engine enum values: skyvern-1.0, skyvern-2.0, openai-cua, anthropic-cua, ui-tars. The relationship between the UI label "Skyvern 2.0 with Code" and the underlying enum + run_with="code" parameter is never reconciled. On top of that, code-caching says: "The default engine is skyvern-1.0. To enable caching, explicitly specify engine='skyvern-2.0'. The Cloud UI defaults to version 2.0." — but the API reference for POST /v1/run/tasks lists default: skyvern-2.0 for the engine field. Core-concepts further says the Cloud UI default is skyvern-2.0 and the SDK default is skyvern-1.0.
Consequence: A developer using the SDK assumes they're getting the same engine they saw demoed in the UI ("Skyvern 2.0 with Code"), but the SDK silently runs skyvern-1.0 with no caching. Cost, behavior, and reliability all change — and the developer has no signal that the engine downgraded. The API reference and code-caching page also disagree about what the API default is, and the three-vs-five engine listing means agents can't tell which set is canonical.
The fix: Pin one fact: what is the default for (a) the Cloud UI, (b) the SDK constructor, and (c) the raw REST API. Document explicitly that "Skyvern 2.0 with Code" = engine="skyvern-2.0" + run_with="code". Make sure the API reference, core-concepts, code-caching, run-first-task, and cost-control pages all repeat the same enumeration and the same defaults.
6. x-api-key marked "optional" on most API reference pages, but the schema generator is inconsistent (significant)
Location: /docs/api-reference/agent/run-a-task, /docs/api-reference/agent/get-a-run-by-id (mark optional); /docs/api-reference/workflows/run-a-workflow (marks required); /docs/cloud/account-settings/api-keys
Problem: Most API reference pages — including POST /v1/run/tasks and GET /v1/runs/{run_id} — document x-api-key as an "optional" header. But the workflow endpoint (POST /v1/run/workflows) marks it as "Required Header: x-api-key". The API-keys page says "All Skyvern API requests require the x-api-key header." The error-handling page documents ForbiddenError (403): "Invalid or missing API key" — i.e., missing the header is a hard failure. The schema generator is inconsistent rather than uniformly wrong, which is arguably worse for agents.
Consequence: Agents and codegen tools that parse the per-endpoint reference will mark auth as optional for tasks and runs but required for workflows, producing inconsistent client output. The "optional" tag is almost certainly an artifact of the auth header being a global security scheme rather than a per-endpoint parameter — but because at least one page renders it correctly, downstream consumers can't even apply a blanket override.
The fix: Fix the schema generator so the rendered docs reflect the security requirement on every endpoint. Mark x-api-key as required: true everywhere. Use the workflow page's rendering as the reference.
7. No machine-readable OpenAPI spec is discoverable from the docs (significant)
Location: /docs/api-reference/*, /docs/sitemap.xml, /docs/llms.txt
Problem: No OpenAPI/Swagger spec is reachable anywhere in the sitemap or docs root. /docs/api-reference/openapi returns 404. The 186-URL sitemap contains only prose /docs/api-reference/agent/... and /docs/api-reference/workflows/... pages, not a downloadable schema. The llms.txt index references "page operations, agent methods, browser management" but no spec file path.
Consequence: Agents, codegen tools (Speakeasy, Stainless, Fern, etc.), Postman importers, and SDK generators have nothing to consume. The entire API reference is prose pages. Combined with finding #6, the surface that machine consumers most need is the surface that's broken.
The fix: Publish the OpenAPI 3.x JSON/YAML at a stable URL (e.g., /docs/openapi.json), link it from the API reference index, list it in llms.txt, and add a <link rel="alternate" type="application/openapi+json"> on reference pages.
8. Error catalogue contradicts standard HTTP semantics and skips 401 and 429 (significant)
Location: /docs/sdk-reference/error-handling
Problem: The SDK error reference maps "Invalid or missing API key" to ForbiddenError (403). There is no UnauthorizedError (401). 401 is the correct status for missing/invalid credentials; 403 means authenticated-but-not-permitted. The same page omits common production errors entirely — there's no rate-limit error (429), no server error class (500/502/503), and no documented retry-after handling. The page mentions "Retries apply to HTTP failures and 5xx" without defining the retry budget.
Consequence: Developers writing retry logic on the SDK can't distinguish "key is bad, never retry" from "permission denied for this resource, never retry" from "rate-limited, retry with backoff." Agents writing error-handling code will copy the wrong pattern.
The fix: Add UnauthorizedError (401) for auth failures and demote the 403 entry to "permission denied" semantics. Document RateLimitError (429) with retry-after semantics. Document the 5xx class with the SDK's automatic-retry policy, including the actual retry budget.
9. Self-hosted LLM provider list (14) disagrees with the README's list (~7) (significant)
Location: /docs/developers/self-hosted/llm-configuration vs github.com/Skyvern-AI/skyvern/README.md
Problem: The self-hosted docs page enumerates 14 LLM providers including MiniMax, VolcEngine, Novita, Moonshot, Inception, and Groq. The GitHub README lists only OpenAI, Anthropic, Azure OpenAI, AWS Bedrock, Gemini, Ollama, OpenRouter — about half. The README also lists "GPT-4 variants and o3/o4-mini models" while the docs reference LLM_KEY=OPENAI_GPT5_5 and "GPT-5.5, GPT-5 series." Neither page acknowledges the other.
Consequence: A developer evaluating Skyvern by reading the README undercounts compatibility and rules it out. A developer reading the docs configures a provider they expect to work, then finds the codepath isn't actually shipped in main (or is, but the README hasn't been updated). The OpenAI model-family drift between the two pages compounds the staleness.
The fix: Generate the provider list and the supported-model list from the same source the code reads (e.g., the ENABLE_* enum or LiteLLM provider registry) and embed it in both the README and the docs. Add a "last verified" date or git ref to the docs page.
10. README says SQLite is the local default; self-hosted docs and quickstart require PostgreSQL (significant)
Location: github.com/Skyvern-AI/skyvern/README.md, /docs/developers/self-hosted/overview, /docs/developers/getting-started/quickstart
Problem: The README states: "The system defaults to SQLite (no Postgres needed). Launch with skyvern quickstart for the UI and server." The self-hosted overview lists "PostgreSQL 14+ comes included or can be externally configured" as a prerequisite. The developer quickstart says outright: "Prerequisites include PostgreSQL and an LLM API key."
Consequence: A new self-hoster following the README expects a one-command SQLite setup, while a new self-hoster following the docs quickstart goes off and installs PostgreSQL 14+ before running anything. They reach completely different conclusions about what's needed to evaluate the product locally. An agent reading both will emit a Dockerfile that may or may not include a Postgres service.
The fix: Document the actual default database for local installs and state when Postgres becomes required (e.g., for multi-user, for production). Update README and quickstart to agree. If skyvern quickstart does in fact spin up SQLite while skyvern init (or the docker-compose path) uses Postgres, name that branch explicitly.
11. Changelog says v1.0.24 is latest; docs index still cites v1.0.22 (significant)
Location: /docs/changelog vs /docs index
Problem: The changelog page documents v1.0.24 (April 21, 2026) as the most recent release, with v1.0.23 and v1.0.22 below it. The top-level docs index says "Changelog (v1.0.22 latest)." Two releases worth of features — including Saudi Arabia proxy, workflow-level error code mapping, MCP OAuth, "Summarize with AI", Workflow Trigger block, CLI signup — are not surfaced from the index.
Consequence: Users skimming the docs index believe they're on the latest version and miss features that already shipped. The MCP OAuth flow especially (v1.0.23) is a meaningful agent-onboarding upgrade buried by stale metadata.
The fix: Make the index pull the latest version string from the changelog source rather than hardcoding it. Add CI that fails the docs build if the index version drifts from the most recent changelog entry.
12. Proxy location count contradicts itself (significant)
Location: /docs/getting-started/introduction, /docs/developers/features/browser-sessions, /docs/developers/optimization/browser-sessions
Problem: The introduction page advertises "Proxy rotation across 30+ countries" as a built-in capability. The browser-sessions feature page and the browser-sessions optimization page both say "21 supported geographic proxy locations." Even accounting for the v1.0.23 Saudi Arabia addition, the gap between 21 and "30+" is roughly 50%.
Consequence: A sales-relevant capability number disagrees with itself depending on which page you land on. Enterprise procurement teams that ask "which countries do you cover?" will get inconsistent answers from the docs themselves. Agents pulling capability stats for proposals or compliance docs have no canonical source.
The fix: Publish a definitive list of supported proxy locations (not just a count) and link to it from every page that mentions proxies. Generate the count from the list, not from prose.
13. TypeScript SDK feature gaps documented vaguely; no parity matrix (significant)
Location: /docs/sdk-reference/complete-reference, /docs/sdk-reference/overview
Problem: The complete reference says "Python-only features include local browser launching, form auto-fill, iframe management, and file uploads" and "TypeScript supports core AI methods but lacks advanced form handling." The overview page promises TypeScript "is also compatible with Bun, Deno, and Cloudflare Workers" but never lists which methods are missing on TypeScript, nor whether the missing methods throw, return undefined, or fail silently. No version-pinned parity table.
Consequence: A developer chooses TypeScript for a Cloudflare Workers deployment based on the overview, then halfway through a build discovers fillForm (or whatever they need) doesn't exist on the TS client. The "lacks advanced form handling" sentence isn't enough to plan around.
The fix: Publish an explicit Python/TypeScript parity table listing every public method, marking each ✅/❌/⚠️ with the gap explained. Include runtime support per method (Node only? Bun? Workers?). Link to it from both the overview and the complete reference.
14. Webhook delivery has no automatic retries, but the docs hide this until late (significant)
Location: /docs/developers/going-to-production/webhooks
Problem: Webhooks fire on terminal status — completed, failed, terminated, timed_out, canceled. If delivery fails (timeout >10s, non-2xx, signature rejection), Skyvern marks the run failed and "No automatic retries occur. You must explicitly call retry_run_webhook() after fixing issues." The 10-second timeout is short and the manual-retry requirement is unusual; both are buried below signature-verification content rather than called out at the top.
Consequence: A developer building a typical webhook receiver assumes at-least-once delivery with backoff (industry default). When their endpoint blips during deploy, runs silently move to failed and they have to discover retry_run_webhook exists. Production data is lost between the time the receiver goes down and the time someone notices.
The fix: Move the no-retry policy and 10s timeout into a callout at the top of the webhooks page. Document idempotency expectations and suggest a queue-based receiver pattern. Consider implementing exponential-backoff retries server-side; if you won't, make that the headline.
15. Self-hosted CAPTCHA pause window contradicts the "automatic detection and solving" pitch (significant)
Location: /docs/developers/features/captcha-and-bot-bypass, /docs/developers/self-hosted/overview
Problem: The captcha page leads with "Skyvern automatically detects and solves multiple CAPTCHA types including reCAPTCHA v2/v3, hCaptcha, Cloudflare Turnstile, FunCaptcha/ArkoseLabs, MTCaptcha, and standard text/number image CAPTCHAs" but ends with: "Self-hosted deployments require manual CAPTCHA solving with a 30-second pause window before agent resumption." The first sentence carries no "cloud only" caveat; the contradiction sits at opposite ends of the same page. The self-hosted overview's "Key Differences from Cloud" section does not list CAPTCHA solving as a gap.
Consequence: A team evaluating self-hosted Skyvern on the strength of the headline capability discovers, mid-deployment, that CAPTCHAs are now a human-in-the-loop task. CAPTCHA solving is one of the platform's six headline features — losing it for the entire self-hosted audience is a procurement-relevant capability gap, not a footnote.
The fix: Add a "Cloud only" tag next to each automatic solver. Surface the self-hosted CAPTCHA limitation in the self-hosted overview's "Key Differences from Cloud" section, not just on the captcha page.
16. Multiple guessable shortcut URLs return 404 instead of redirecting (significant)
Location: /docs/webhooks, /docs/captchas, /docs/faq, /docs/credentials/2fa, /docs/self-hosted/llm, /docs/self-hosted/llm-setup, /docs/sdk-reference/python, /docs/api-reference/run-task
Problem: While /docs/getting-started/quickstart and /docs/getting-started/introduction resolve (to ambiguous parallel content — see finding #1), other obvious shortcut paths a developer or agent would guess from category names return 404: /docs/webhooks, /docs/captchas, /docs/faq, /docs/credentials/2fa, /docs/self-hosted/llm, /docs/self-hosted/llm-setup, /docs/sdk-reference/python, /docs/api-reference/run-task. The canonical paths live under /docs/developers/... or /docs/api-reference/agent/..., with no redirect from the shortcut form.
Consequence: Agents indexing the site and humans guessing URLs from section names hit dead ends. Inbound links from blogs, Stack Overflow answers, or AI assistants citing the most natural-sounding URL pattern silently fail. Combined with the fact that some shortcuts (the /docs/getting-started/* ones) DO resolve, there's no learnable rule for which guesses work.
The fix: Either 301-redirect each guessable shortcut to a canonical page, or render a real page at each path. Decide one policy: shortcuts always resolve, or shortcuts never resolve. Mixed behavior is the worst case.
17. Marketing sitemap omits docs entirely; www vs apex split (minor)
Location: /sitemap.xml vs /docs/sitemap.xml
Problem: The marketing-site sitemap (12 URLs) lists no path under /docs. Docs live on the apex skyvern.com, marketing on www.skyvern.com. Cross-links between the two surfaces use both forms inconsistently. The marketing sitemap also doesn't link to the docs sitemap as a sub-sitemap (no <sitemapindex>).
Consequence: Search engines discovering Skyvern through the marketing sitemap won't find docs through it. Agents fetching the canonical sitemap miss 186 doc URLs unless they know to also fetch /docs/sitemap.xml. The www/apex split occasionally produces double-counted or canonical-mismatched pages in indexes.
The fix: Either publish a sitemap index that includes both /sitemap.xml and /docs/sitemap.xml, or merge them. Pick one host (apex or www), 301 the other, and update all internal links.
What they do well
- MCP coverage is thorough. OAuth + API-key + local-mode, with concrete Cursor/Claude Code/Claude Desktop snippets and 75+ exposed tools — among the better MCP onboarding stories in the agent-tooling space.
- Webhook security guidance is solid. HMAC-SHA256, timestamped headers, timing-safe comparison, raw-bytes signing, and explicit notes about JSON normalization before signing. This part is well-thought-out.
- Error codes via
error_code_mappingis a genuinely useful pattern. LLM-evaluated branching codes (login_failed,invoice_not_found, etc.) is more agent-friendly than parsing free-textfailure_reason.
Top 3 recommendations
- Collapse or canonicalize the parallel
/docs/cloudand/docs/developerstrees. The duplicate-with-drift pattern is the single biggest source of contradictions in this audit. - Reconcile pricing math and feature matrix across
/pricing,/docs/cloud/account-settings/billing-usage, and/docs/developers/optimization/cost-control. Generate all three from one data file — and pick one unit (credit OR action) so the ratio is constant across plans. - Publish a real OpenAPI 3.x spec at a stable URL and fix the schema generator so
x-api-keyrenders as required everywhere. This is the highest-leverage change for agent consumers and codegen users.