Gainable Documentation Audit
Gainable's docs read like a coherent product story at the conceptual layer, but the moment you drop into anything an agent or developer would actually copy — playbook YAML, tool risk tiers, webhook setup, the API reference — the surfaces stop agreeing with each other. There's no machine-readable schema for playbooks or tools, and no OpenAPI/Swagger for the "generated app" REST API the docs reference.
1. Same tool, two different YAML shapes across pages (critical)
Location: /autopilot/playbooks vs /autopilot/recipes
Problem: Per the scraped pages, /autopilot/playbooks documents draft_for_approval with top-level fields (template, recipient, owner) while /autopilot/recipes documents the same tool with a different shape — underlying:, template:, owner:, and a nested payload: {to, subject, body}. Neither page acknowledges the other, and /autopilot/tools only describes the tool prose-side without a parameter schema.
Consequence: A developer (or an AI agent generating playbooks) copies one shape and the runtime either rejects it or silently uses defaults. Because draft_for_approval is the tool that gates every outbound action ("All outbound communication" lives behind it), getting it wrong means drafts never reach the inbox or land malformed.
The fix: Publish a single, authoritative tool reference for draft_for_approval (and every other tool in the registry) with the parameter table, types, required fields, and one canonical YAML example. Then update both /autopilot/playbooks and /autopilot/recipes to use that shape verbatim, in line with each other.
2. notify_user risk tier contradicts itself across pages (critical)
Location: /autopilot/risk-tiers vs /autopilot/tools
Problem: /autopilot/tools lists notify_user with a default risk tier of Low (the tier definition page describes Low/auto as "Action executes immediately. No human review. Cannot be reversed by the user."). But the undo-windows table on /autopilot/risk-tiers lists notify_user with a 5-minute undo window — i.e., auto_with_undo, a different tier with different runtime behavior.
Consequence: A developer designing a playbook can't tell whether notify_user fires instantly and is irreversible, or fires instantly with a 5-minute reversal window. The whole appeal of risk tiers is auditability and predictability ("It keeps agents auditable, predictable, and easy to reason about"); a self-contradiction at the tier level destroys that promise.
The fix: Decide which it is, fix one page, and add a single sentence stating the source of truth (e.g., "The tool registry table at /autopilot/tools is canonical; per-tool undo windows are listed at /autopilot/risk-tiers").
3. send_email undo entry promises a graduation path that's nowhere documented (significant)
Location: /autopilot/risk-tiers undo table
Problem: The undo-windows row for send_email says "Not eligible for auto_with_undo" with the parenthetical "(always draft_and_approve unless graduated to auto)." /autopilot/tools lists send_email as default High (draft-and-approve). Neither page documents the graduation procedure — what triggers it, who authorizes it, how it's audited.
Consequence: A developer reads "can be graduated to auto" and goes looking for the graduation procedure — there isn't one in the scraped docs. They either email support or assume it's possible and design a workflow that depends on a feature that may not exist.
The fix: Either remove the "unless graduated to auto" phrase, or add a "Graduation" section that documents how a tool moves between tiers, who can authorize it, and how it's audited.
4. "Five-phase build contract" — the phases themselves are missing (significant)
Location: /autopilot/overview
Problem: The overview asserts "Every Gainable app moves through a five-phase build contract:" — but the actual list of phases doesn't appear in any other scraped page either, nor is there a dedicated reference page for the build contract. The term is used as if defined elsewhere; it isn't.
Consequence: A developer trying to map their app's progress to "the five phases" has no list to map to. The build contract is presented as central enough to earn its own named term, but the term doesn't resolve to a definition.
The fix: On /autopilot/overview, follow the sentence "Every Gainable app moves through a five-phase build contract:" with the explicit list of phases with one-sentence descriptions of each, and add a /concepts/build-contract page that other pages can link to.
5. "Scopes" means two incompatible things in two namespaces (significant)
Location: /autopilot/scopes vs /copilots/data-access
Problem: /autopilot/scopes uses "scope" to mean a runtime identity boundary — app_wide vs personal, with strict RBAC rules ("A personal agent never sees data its owner can't see"). /copilots/data-access uses "scopes" to mean a collection-level allow-list — "Use scopes to restrict it to specific collections." Same product, same vocabulary, two unrelated concepts. Neither page cross-references the other or disambiguates.
Consequence: A developer configuring both a Copilot and an Autopilot agent on the same app will reasonably assume "scopes" is one mechanism. They'll mis-design access rules — likely under-restricting Copilot or over-restricting agents. For an AI agent generating configs, this is a silent failure mode.
The fix: Rename one. The Copilot concept is closer to "collection scope" or "data scope" or "allow-list"; the Autopilot concept is closer to "identity scope" or just "runtime scope." Pick distinct nouns and add a glossary entry.
6. /concepts/agents contradicts itself on the build-agent roster (significant)
Location: /concepts/agents (also referenced in /concepts/how-it-works)
Problem: The page's info box names five build agents: "Planner, DataAnalyzer, Build, Validation, Conversation." Two paragraphs later the same page says: "The agents described above (Planner, Build, Validation, Conversation)" — only four. DataAnalyzer is silently dropped. /concepts/how-it-works reinforces the four-agent list ("Planner, Build, Validation, Conversation"). Whether DataAnalyzer is a real build agent at all is genuinely ambiguous from the docs.
Consequence: A developer reading the concepts page can't tell whether DataAnalyzer is a fifth subsystem they should expect to see logs/output from, or a stray name that survived an edit pass. AI agents indexing the corpus will produce contradictory summaries depending on which paragraph they cite.
The fix: Decide whether DataAnalyzer exists. If yes, give it a definition like the other four and use the five-name list consistently across /concepts/agents and /concepts/how-it-works. If no, remove it from the info box.
7. "Build agents" and "Agents" are the same word for different concepts (significant)
Location: /concepts/agents, /autopilot/overview, /copilots/data-access
Problem: /concepts/agents introduces "build agents" (Planner, Build, Validation, Conversation) — internal subsystems that build your app. But across other pages, "Agents" with no qualifier refers to Autopilot autonomous agents. /copilots/data-access says "Use Agents for asynchronous, autonomous work" — meaning Autopilot agents — while the same word in /concepts/agents means the build pipeline. The page-title noun and the cross-page noun collide.
Consequence: A reader navigating from "Agents" in the sidebar lands on build internals instead of the autonomous Autopilot system they were looking for, or vice versa. AI coding agents trying to follow links will conflate the two.
The fix: Rename /concepts/agents to /concepts/build-pipeline (or similar), and reserve the unqualified word "Agents" for Autopilot throughout the docs.
8. Playbook templating language is used but never specified (critical)
Location: /autopilot/playbooks, /autopilot/recipes
Problem: Example YAML uses expressions like step1.deals[*].contact_id, but there is no documented spec: what helpers exist, what the path syntax supports (wildcards, filters, nested access), how nulls/missing fields behave, what type coercion happens. "Simulate on last 30 days" is referenced as a feature but documented nowhere procedurally.
Consequence: A developer cannot write a non-trivial playbook from the docs alone. They will copy the recipe verbatim and be unable to adapt it — or worse, guess at the syntax and ship a playbook that silently produces wrong outputs (e.g., a wildcard that doesn't actually wildcard).
The fix: Add a /autopilot/templating reference page documenting: variable scoping rules, path syntax (including [*]), built-in helpers (date, format, fallback), error semantics, and a "Simulate" workflow with screenshots.
9. Webhook signature verification claims have no admin-side counterpart (significant)
Location: /autopilot/connect-outbound
Problem: The page makes specific verification claims — Stripe Stripe-Signature HMAC-SHA256, GitHub X-Hub-Signature-256, Twilio X-Twilio-Signature, SendGrid public key, "Generic HMAC if shared secret is configured, else IP allow-list" — but no scraped page documents how to configure the shared secret, where in the UI the signing key is shown, how rotation works, or how IP allow-lists are managed. The promise "Credentials never appear in the action log" is made without a credentials-management page to link to.
Consequence: A developer wiring an inbound Stripe webhook can't tell from the docs how to actually paste in the signing secret, where it's stored, or whether it's rotated automatically. Either they wire it insecurely or they file a support ticket.
The fix: Add a "Webhook setup" page per integration (Stripe, GitHub, Twilio, SendGrid, Generic) showing the exact UI flow, where the secret lives, how rotation works, and what the failure log looks like in the action log.
10. Webhook URL pattern published, then the page cuts off mid-sentence (significant)
Location: /autopilot/triggers
Problem: The page declares the closed trigger vocabulary and then begins a "How webhook URLs work" section with: "When you configure a webhook trigger, Gainable provisions a URL like:" — and then the section is empty in the scraped content. There's no completed URL pattern, no description of where {app_id} and {trigger_id} are surfaced in the UI, no curl example, no expected response codes.
Consequence: A developer trying to wire an inbound webhook hits the only documentation that's supposed to explain the URL format and finds the explanation truncated. They can't proceed without filing a ticket or guessing.
The fix: Finish the "How webhook URLs work" section: show the literal URL pattern, screenshot or describe where in the UI a user finds the IDs, provide a curl test command for the Generic verifier, and show expected 2xx/4xx responses plus the corresponding action-log entry.
11. No API reference content for the "generated app" REST surface (critical)
Location: /reference/api (referenced in llms.txt)
Problem: The llms.txt index lists "API reference: Understanding the APIs in your generated apps" but no scraped page surfaces actual reference content — no endpoint list, no auth-header documentation, no rate limits, no error codes. For a platform whose generated apps are explicitly Node.js + Express + MongoDB + Socket.IO with a REST API, there is no OpenAPI/Swagger spec linked from anywhere in the scraped corpus.
Consequence: Any developer who wants to integrate a Gainable-built app with an external system (which is the entire point of "internal tools") is starting from prose, not a spec. An AI coding agent has no machine-readable endpoint registry to consume.
The fix: Ship an OpenAPI spec for the REST surface generated apps expose, link it from /reference/api, and populate the page with at minimum: base URL, auth scheme, the endpoint list, rate-limit headers, and an error-code table.
12. /copilots/data-access "Scopes" section is two sentences of stub (significant)
Location: /copilots/data-access
Problem: The entire Scopes section reads: "By default, a Copilot can access all collections in your app. Use scopes to restrict it to specific collections when you want to limit what it can see." That's it. No configuration syntax, no UI walk-through, no example of a scope declaration, no link to a how-to page, no description of whether scope is per-Copilot or per-app.
Consequence: A developer who wants to restrict a Copilot's data access — exactly the security-sensitive use case the section names — has nothing to copy. Combined with the terminology collision with Autopilot scopes (issue #5), this is the worst combination: an under-documented feature with an overloaded name.
The fix: Expand the section into a configuration reference: how scopes are declared, where in the UI they're set, an example with two collections allowed and one denied, and the default behavior on collections added after the scope is configured.
13. call_external is High-risk with no payload-shape reference (significant)
Location: /autopilot/tools, /autopilot/risk-tiers
Problem: call_external is listed in the tool registry as "External HTTP" / "High (draft-and-approve)" and is repeatedly cited as not undoable. But no scraped page documents the parameters the tool accepts — method, URL, headers, body shape, auth handling, timeouts, retry semantics. It's the most dangerous tool in the registry and has the least documentation.
Consequence: A developer who wants to use call_external in a playbook has nothing to copy, and the High risk tier means a misconfigured payload still requires human approval before doing damage — but the human reviewer also has no spec against which to evaluate the draft.
The fix: Add a call_external parameter reference with required/optional fields, a canonical YAML example, and an explicit note on how secrets (auth tokens, API keys) are referenced from playbook YAML.
14. ask_human (pauses playbook) has no resume semantics documented (minor)
Location: /autopilot/tools
Problem: The tool registry lists ask_human with Writes "Pauses playbook." Nothing in the scraped pages describes how a paused playbook resumes, what UI surface the human prompt lands in, what happens if the human never responds, timeout behavior, or how the human's answer is bound back into subsequent step variables.
Consequence: A developer who wants to gate a playbook on a human decision can't tell whether the pause is durable across restarts, whether it expires, or how to reference the answer in a later step.
The fix: Add an ask_human section to /autopilot/tools (or its own page) documenting the prompt-rendering surface, default and configurable timeout, expiry behavior, and how the answer is exposed to downstream steps.
15. Inbox "renderings" referenced but not configurable (minor)
Location: /autopilot/inbox
Problem: Three renderings are named — full view, ambient strip, dashboard widget — but the docs never explain how a developer enables/disables each, how the ambient strip differs from native browser notifications, or how the dashboard widget is added to a view (it's just listed "alongside Chart, Kanban, Table" with no link to a widget-config doc).
Consequence: A developer who wants the ambient strip on one page but not another has no documentation to consult.
The fix: Add per-rendering "How to enable" sections with screenshots.
16. "Autonomy contract" referenced as a term but never defined (minor)
Location: /autopilot/objectives, /autopilot/overview
Problem: The phrase "the autonomy contract" appears as if it's a named entity ("reviewable and disablable") but there's no /autopilot/autonomy-contract page, no schema, no editor screenshot, and no example of what one looks like at rest.
Consequence: A developer trying to review or edit the autonomy contract for an agent doesn't know what artifact to look for.
The fix: Either fold the term into "playbook + objective + risk tier" (which is what it appears to be) or add a dedicated page defining it.
17. parent_action_id in schema but no docs for follow-up playbooks (minor)
Location: /autopilot/agent-action-log
Problem: The AgentAction schema includes parent_action_id ("If this action was a follow-up to another") but nothing in the playbooks, recipes, or triggers pages explains how a playbook produces a follow-up action that populates this field.
Consequence: A developer auditing the action log can see the field but can't write a playbook that uses it deliberately.
The fix: Document the follow-up pattern in /autopilot/playbooks and link it from the schema table.
18. Grammatical artifact: "a Autopilot agent" (minor)
Location: /autopilot/agent-action-log (page subtitle and body)
Problem: Both the page subtitle and the first sentence read "everything a Autopilot agent does" / "Every time a Autopilot agent runs" — should be "an Autopilot agent."
Consequence: Minor, but appears in the page subtitle visible in search results and in any LLM index that quotes from the docs verbatim.
The fix: Two-character edit.
What they do well
- The Autopilot conceptual model — risk tiers, scopes, action log, allow-lists, and the "draft-and-approve" default — is clearly thought through and consistently described at the prose level.
- Copilot vs Autopilot is explicitly framed ("Copilot is reactive. Agents are proactive.") and the inbox page reinforces the distinction with a clear comparison table.
- The
llms.txtindex is present and well-structured, with a stable.mdURL convention per page.
Top 3 recommendations
- Ship one authoritative tool reference for the Autopilot tool registry (parameters, types, examples) covering
draft_for_approval,call_external,ask_human, and the rest. Update/autopilot/playbooksand/autopilot/recipesto use that single YAML shape verbatim. Resolve thenotify_userandsend_emailtier contradictions in the same pass. - Publish a real API reference — OpenAPI spec for the REST surface of generated apps, plus auth, rate limits, and error codes — and finish the truncated webhook-URL section on
/autopilot/triggers. - Disambiguate "scopes" and "agents" across the Copilot and Autopilot namespaces. Rename one of each, add a glossary, and link from every page that uses either term. While you're there, decide whether DataAnalyzer is the fifth build agent and make
/concepts/agentsagree with itself.