The docs are a tidy six pages — Introduction, Quickstart, AI Setup, CLI, Tool Files, Components — but the platform behind them is much larger than that, and the gaps show: the flagship homepage code sample violates the docs' own rules, one provider is referred to by two names, the runtime caps and model menu that govern whether your agent works live only on the marketing site, and a fifth UI component is documented but uninstallable. For a product whose pitch is "let an AI coding agent install this for you," the internal contradictions are exactly the kind that an agent follows off a cliff.
1. The homepage's flagship server-action sample violates the docs' own "no array export" rule (critical)
Problem:/tools states the rule plainly: "No array export — export each action individually. "use server" files cannot export arrays; the generated AgentProvider uses import * to pick them all up automatically." Yet the marketing homepage's headline server-actions.betteragent.ts sample does precisely the forbidden thing: export const serverActions = [ defineServerAction({...}) ]. The same snippet also references z.object(...) without importing z.
Consequence: The most visible code sample on the entire site is one the docs say will not work. A developer — or an AI coding agent told to "discover your tools and wire up the provider" — copies the homepage pattern, exports an array, and the import * collection silently picks up nothing (or breaks), so the agent ends up with zero callable server actions and no error explaining why.
The fix: Rewrite the homepage sample to export each action individually (export const createInvoice = defineServerAction({...})), add the missing import { z } from "zod", and have one canonical, copy-runnable tool-file example shared between marketing and /tools.
2. One provider, two names, never reconciled (critical)
Problem: The docs use AgentProvider (the generated wrapper in ) and (the SDK component from ) interchangeably, without ever defining the relationship. On the AI Setup page, the embedded prompt and full layout example import and render , but the page's own "What the agent will do" summary says it and the client-action snippet shows . The Components page wraps the app in imported directly from , contradicting Quickstart/AI-Setup, which use the generated . The file fed to AI assistants carries the same mix.
"Wraps your root layout with BetterAgentProvider,"
<BetterAgentProvider ... actions={...}>
BetterAgentProvider
betteragent-react
AgentProvider
agent-setup.md
Consequence: A developer can't tell whether these are the same thing, two layers, or a typo. An AI agent ingesting agent-setup.md will emit imports for both identifiers, or register the actions prop on the wrong wrapper, producing import errors or client actions that never fire. This is the single most load-bearing object in setup and it has no defined identity.
The fix: Pick one mental model and state it once, prominently: "AgentProvider is the generated wrapper in components/betteragent-provider.tsx; it internally renders the SDK's BetterAgentProvider. Always import AgentProvider from your generated file." Then make every page — including the summary and the action-registration snippet — use that name consistently.
3. NEXT_PUBLIC_BETTERAGENT_API_URL is used in every layout example but defined nowhere (critical)
Problem: The provider examples pass apiUrl={process.env.NEXT_PUBLIC_BETTERAGENT_API_URL}, but the only environment variable the docs ever tell you to set is NEXT_PUBLIC_BETTERAGENT_CLIENT_KEY (the AI Setup summary explicitly lists only that one being added to .env.local). The NEXT_PUBLIC_BETTERAGENT_API_URL variable is referenced, never defined, never explained, and has no documented default or accepted values.
Consequence: Copy the layout example as-is and apiUrl resolves to undefined at runtime. Depending on how the SDK handles that, the provider either points at the wrong host or fails to connect — and the developer has no doc page telling them what the variable is for or what to set it to. This compounds with the host confusion in finding #9.
The fix: Either drop apiUrl from the examples (let the SDK use its default) or document the variable: what it defaults to, when you'd override it (local dev vs production), and add it to the .env.local instructions alongside the client key.
4. Runtime caps that decide whether your agent works exist only on the marketing page (critical)
Problem: The marketing homepage lists hard operational limits the agent enforces at runtime: 8KB / tool result, 30s route timeout, 20 turns / conv, 80k tokens / conv, plus per-project/per-IP rate limits and idempotency behavior. None of these appear anywhere in the docs. The /tools reference — the page a developer reads to learn how tool results are returned — only says vaguely "Keep it concise."
Consequence: A developer writes a route tool that returns a 200KB JSON blob or a handler that takes 45s, ships it, and the agent silently truncates or times out in production. "Keep it concise" gives no number to design against. These are contract-level limits buried in a marketing widget rather than stated in the reference where they'd be acted on.
The fix: Add a "Limits" section to /tools (and ideally a dedicated limits page) with the concrete numbers — 8KB tool-result cap, 30s route timeout, 20 turns and 80k tokens per conversation, rate limits — and what happens on each overrun (truncation? error? dropped turn?).
5. ChatDrawer is documented but uninstallable (significant)
Problem: The "Available components" table lists exactly four containers: sidebar, chat-popup, cmd-k, inline-bar. But the Attribution section says the attribution prop is available on ChatSidebar, ChatPopup, ChatCmdk, ChatInlineBar, and ChatDrawer, and shows a <ChatDrawer /> example. The CLI add/remove commands and betteragent.config.json only ever reference the same four (sidebar | chat-popup | cmd-k | inline-bar) — there is no drawer slug.
Consequence: A developer sees ChatDrawer, tries betteragent add drawer, and it doesn't exist. The component is either unreleased, deprecated, or internal — but the docs present it as supported, wasting time on a dead end.
The fix: If ChatDrawer ships, add it to the components table and the CLI's installable slug list. If it doesn't, remove it from the Attribution section and the example.
6. Credits and billing are never explained in the docs, yet the CLI prints plan state (significant)
Problem:login prints Signed in to acme-app (FREE). and whoami reports plan: FREE, but no docs page explains what a plan is, what credits are, how they're consumed, or what happens when they run out. The only place credit mechanics appear is the AI Setup "Key facts" block (2 per conversation start · 1 per message · 3 per tool call) and the marketing pricing tiers. The CLI reference — where a developer encountering plan: FREE would look — says nothing.
Consequence: A developer can't reason about cost or plan limits from the docs. When the agent stops responding because credits ran out, there's no documented explanation of the failure or how credit consumption maps to usage. Cost is a first-order concern for a metered AI product and it's absent from the reference surface.
The fix: Add a Billing/Credits page covering: the credit cost table, plan tiers and their caps, what happens when credits are exhausted (the marketing site mentions hard caps that "shut off before they bill you" — document that behavior), and that the Plus tier supports bring-your-own-API-key.
7. The default model and model menu live only on marketing — the docs never mention model selection (significant)
Problem: The homepage advertises a selectable model menu — claude-sonnet-4.6 as the default, claude-haiku-4.5 (fast, $0.80), and claude-opus-4.5 (smart, $15), all hosted with cache hits at 10% of normal token cost. None of the six docs pages tell a developer that a model is selectable, what the default is, or how to change it. This is the same omission class as the runtime caps (#4) and credits (#6): operational reality stranded on a marketing widget.
Consequence: A developer who wants Haiku for high-volume conversations or Opus for hard tasks has no documented way to discover the option exists, let alone set it — and no way to reason about how model choice maps to the per-conversation credit math in #6. They ship on Sonnet unknowingly, either overpaying or underperforming, with no reference page to consult.
The fix: Add a "Models" section (or fold it into the Limits/Billing page) stating the default model, the full menu with relative cost, how to select a model (per project or per conversation), and how model choice interacts with credit consumption.
8. authToken Function form is documented on one page and omitted on another (significant)
Problem: The Quickstart documents only two authToken forms — String (forwarded as Authorization: Bearer <token>) and Object (forwarded verbatim). The AI Setup page documents a third: Function (Client Component only), "called per-request for refreshed tokens."
Consequence: A developer reading Quickstart never learns about the Function form, which is the only option that handles token refresh — the exact thing you need for long-lived sessions with expiring tokens. They build a String-based integration, tokens expire mid-conversation, and authenticated route tools start failing with no obvious cause.
The fix: Document all three authToken forms identically on every page that mentions the prop, and call out that the Function form is the recommended choice when backend tokens expire.
9. Inconsistent API host across CLI output, examples, and attribution (significant)
Problem: The host the SDK and CLI talk to is presented three different ways. The CLI's API-URL resolution order ends at a production default of https://www.betteragent.dev, and whoami prints api: https://www.betteragent.dev. But the init examples and the config sample use http://localhost:3000. Separately, the Components attribution footer's default href is https://betteragent.dev (apex), while docs live at docs.betteragent.dev and the API at www.betteragent.dev. Fetching the apex betteragent.dev/agent-setup.md 301-redirects to www.
Consequence: A developer trying to confirm what apiUrl should be (see finding #3) gets conflicting signals: localhost in the scaffold, apex in attribution, www in whoami. It's unclear whether localhost:3000 is a placeholder for their own app or the BetterAgent backend, and whether apex vs www matters.
The fix: Standardize on one canonical API host string and use it everywhere; clearly mark http://localhost:3000 as the developer's own app URL (not BetterAgent's) where it appears; and point the attribution default at the same host family used elsewhere.
10. CLI example output disagrees with itself on counts and login wording (minor)
Problem: For the same example project, init reports Found 8 routes · 4 server actions while discover reports Found 11 route handlers · 9 server action exports — different counts and different nouns ("routes" vs "route handlers," "server actions" vs "server action exports"). Separately, login prints Signed in to acme-app (FREE). while the /cli page's init example prints Signed in as acme-app (http://localhost:3000) — different preposition, different parenthetical (plan vs URL).
Consequence: A developer comparing their real terminal output against the docs can't tell whether a count mismatch is a bug in their project or just doc drift, and the inconsistent "Signed in" lines make it unclear what successful auth actually looks like.
The fix: Regenerate all CLI sample output from a single fixture project so counts and wording match across pages, and use consistent terminology for routes vs route handlers and server actions vs exports.
11. Free-plan credit period is stated two incompatible ways (minor)
Problem: AI Setup's "Key facts" say "Free plan: 500 credits/30-day period," while the marketing pricing tier and surrounding copy say "500 credits / month." A rolling 30-day window and a calendar month are different reset semantics.
Consequence: A developer planning around quota can't tell whether credits reset on the 1st of each month or on a rolling 30-day clock from signup — which changes when prototyping capacity comes back. Minor, but it's a billing fact stated two ways.
The fix: Pick the actual reset behavior and use the same wording in both places.
12. No documented machine-readable surface for the platform's API, errors, or limits (significant)
Problem: The docs are six prose pages with no errors/troubleshooting page, no authentication page, no API reference, no observability/rate-limit page, and no changelog — even though ai-setup, the CLI, and the marketing site all reference auth tokens, rate limits, error states, and credits. There is an agent-setup.md file for AI assistants (a good touch), but it's an install script, not a structured index — and nowhere in the six pages is a machine-readable index (llms.txt/llms-full.txt) or an OpenAPI/JSON schema for the protocol the agent speaks ("two messages on the wire," per marketing) documented or linked.
Consequence: For a product explicitly built to be installed by AI coding agents, there's no documented, parseable contract an agent can index — no error-code list to handle failures, no schema for the route/server-action/client-action message format, no rate-limit table. Agents (and humans) must infer the protocol from prose scattered across marketing and docs, and silently mis-handle the cases that aren't written down anywhere.
The fix: Publish and link an llms.txt index of the docs, add a structured Errors page (codes + meaning + remedy) and a Limits page, and provide a machine-readable schema for the tool-file protocol and the on-the-wire message format so agents can validate against it rather than guess.
What they do well
The agent-setup.md prompt (served live and reachable from /ai-setup) is a genuinely good idea — a single copy-paste payload that an AI IDE can execute end-to-end — and it's a smart acknowledgment that agents are now installing this product.
The three-primitive model (routes read, server actions mutate, client actions steer the UI) is a clean, memorable mental model, and the /tools table explaining each file's purpose is concise and well-targeted.
The tool-file guidance to "describe when to use a tool, not just what it does" is exactly the right advice for agent-driven tool selection.
Top 3 recommendations
Fix the contradictions that break copy-paste: correct the homepage array-export sample (#1), define AgentProvider vs BetterAgentProvider once and use it consistently (#2), and document or remove the NEXT_PUBLIC_BETTERAGENT_API_URL env var (#3). These are the failures an AI installer will propagate verbatim.
Move operational reality into the docs: add Limits, Errors, Models, and Billing/Credits pages so the 8KB/30s/20-turn caps, the model menu and default, credit mechanics, and plan behavior live where developers act on them — not only in marketing widgets (#4, #6, #7).
Give agents something to parse: publish and link llms.txt plus a machine-readable schema for the tool-file protocol, and reconcile the smaller drifts (ChatDrawer, authToken forms, API host, CLI output, credit period) against a single source of truth (#5, #8, #9, #10, #11, #12).
Fixed
0
Skip
43
Fail
0
Summary
Verified the six docs pages plus the two marketing URLs in scope. Runtimes available: Node 24, npm/npx, python3, curl (bun/ruby/elixir absent — not needed here).
What I executed against the live API (https://www.betteragent.dev) using the supplied project secret key:
betteragent login → PASS — ✓ Signed in to Manicule-test (FREE). (matches the documented Signed in to <project> (FREE). format).
Environment note for -D betteragent-cli install lines: this sandbox sets npm omit=dev, so devDependencies never materialize via npm install (the control package installed fine; betteragent-cli did not, and its bin never linked). The package is genuinely published (betteragent-cli@0.1.3, bin betteragent) and fully functional — every documented subcommand above ran from the published tarball — so the install examples are marked PASS with this caveat rather than penalized for a sandbox setting.
Setup-dependent CLI commands are SKIP: init is a fully interactive wizard (prompts for a chat variant; needs a TTY + Next.js project), discover reports it must run from a Next.js project root, sync reports No tool files found, remove needs installed components + interactive confirmation. All provider/layout/chat/tool-file code blocks are SKIP — partial fragment (they require a full Next.js app, the generated provider, and user-defined handlers; running them would require inventing surrounding code). CSS theming blocks and .env/config fragments are non-executable (SKIP). The betteragent.config.json sample is annotated JSONC (// comments + a literal "..." placeholder) and is SKIP as illustrative — it is not valid under strict JSON.parse and is not a copy-paste artifact.
The agent-setup.md reference resolves: apex betteragent.dev/agent-setup.md → 307 → www.betteragent.dev/agent-setup.md (HTTP 200). No FAIL rows: everything executable worked as written; the remainder is partial/illustrative/setup-gated.
Required credentials
Project secret key — placeholder ba_secret_…, supplied by the user; used only for betteragent login --key … (and thus whoami/add/logout). Never printed.
NEXT_PUBLIC_BETTERAGENT_API_URL — referenced by the provider examples but never defined anywhere in the docs (not required for the executed CLI snippets).
Anchor on the AI Setup page; the "What the agent will do" section is a prose bullet list with no additional runnable code (it names BetterAgentProvider where the prompt body uses the generated AgentProvider). Nothing to execute.