xpander.ai Documentation Audit
The docs cover a sprawling agent platform (REST API, Python SDK, CLI, MCP, self-hosted Helm, workflows, connectors) and visibly try hard — there's an llms.txt, an OpenAPI 3.1 spec, and a changelog. But the surface area has outgrown the editorial discipline: getting-started paths contradict each other, the changelog contradicts the API reference about auth, integration counts swing from 50 to 2,000 across pages, and several core API endpoints document only 422 errors as if 401/404/429 don't exist.
1. Three different "getting started" paths install the SDK and CLI with three different commands (critical)
Location: /developers/quickstart, /Examples/00-setup-deployment, /Examples/01-simple-hello-world
Problem: Three "first agent" tutorials all live in the docs and each prescribes a different install/init flow:
/developers/quickstart: install CLI via npm, install SDK via pip, runxpander login, thenxpander agent new./Examples/00-setup-deployment:npm install -g xpander-cli, thenxpander agent new, thenxpander deploy./Examples/01-simple-hello-world:pip install "xpander-sdk[agno]"andxpander init(a command that appears nowhere in the CLI reference at/developers/cli-reference/overview, which listsxpander login,xpander agent new,xpander deploy,xpander logs,xpander invoke,xpander dev— noinit).
Consequence: A developer or coding agent following the example gallery will run xpander init, get an unrecognized-command error, and have no way to tell whether the docs are wrong or their install is broken. Different files end up scaffolded depending on which page you trust, and there's no canonical "this is the supported flow" pointer.
The fix: Designate one quickstart as canonical, link to it from every other entry page, and either document xpander init in the CLI reference or rewrite the hello-world example to use xpander agent new. Pick one of pip install xpander-sdk or pip install "xpander-sdk[agno]" as the recommended starting command.
2. Changelog says OAuth2 Bearer is supported; API reference says it explicitly isn't (critical)
Location: /changelog/product-updates (2026-05-10) vs. /api-reference/invoke-api
Problem: The May 10 2026 changelog entry announces: "OAuth2 JWT authentication for the API now accepts bearer tokens alongside API keys." The 2025 changelog already lists "OAuth 2.1 authorization server with JWT authentication" as shipped. Meanwhile /api-reference/invoke-api still states: "Authorization: Bearer is not supported" and lists Bearer auth under "Common Mistakes to Avoid."
Consequence: Developers who read the changelog and try a Bearer token can't tell whether the API reference is stale or the changelog is aspirational. Coding agents that scrape the API reference will refuse to attempt Bearer auth even though the platform supports it. Either way, half the audience is acting on wrong information about how to authenticate to a production API.
The fix: If OAuth2 JWT is GA, rewrite /api-reference/invoke-api to document both auth schemes (header names, how to obtain a token, scopes, expiry) and remove the "Bearer is not supported" line. If it's gated, say so explicitly on the reference page.
3. Integration count varies from "50+" to "2,000+" across pages — same product, four different numbers (significant)
Location: /llms.txt, /guides/core-concepts, /overview/what-is-xpander, /Examples (#10), marketing homepage
Problem: The same "connectors" or "tools" inventory is sized differently on every surface:
llms.txt: "50+ pre-built integrations"/guides/core-concepts: "100+ pre-built integrations"/overview/what-is-xpanderandxpander.aihomepage: "2,000+ tools" / "2,000+ pre-built integrations"/ExamplesLangChain card: "2000+ Xpander tools"
That's a 40× spread.
Consequence: Procurement, eval, and "will this integrate with X?" decisions all hinge on this number. Developers can't tell whether the catalog is small-and-curated or huge-and-uneven, and they can't tell whether "tools" and "connectors" are the same unit. Agents parsing the docs pick whichever number they saw last.
The fix: Define "connector" vs "tool" vs "integration" once, publish a single live count (ideally generated from the connector index), and reuse that exact phrase everywhere. If 50 is the count of connectors and 2,000 is the count of individual tool operations exposed by those connectors, say so.
4. SDK base URL points to a different host than the REST API base URL — with no explanation (critical)
Location: /developers/sdk-reference/overview vs. /api-reference/rest-api
Problem: REST API docs say the base URL is https://api.xpander.ai. The SDK reference tells you to export XPANDER_BASE_URL="https://inbound.xpander.ai". Neither page mentions the other host, and the invoke-api page specifically warns: "don't use webhook.xpander.ai endpoints" — implying there's already host confusion that hasn't been resolved.
Consequence: Developers debugging an SDK call who try curling the same endpoint hit a different host and assume the SDK is broken. Self-hosted deployments (where these hostnames change) have no map of which subdomain serves which traffic. Coding agents will guess wrong about which base URL to use when generating cross-language clients.
The fix: Document the host topology explicitly: which subdomain serves control-plane CRUD, which serves task ingress, which serves webhooks, and which the SDK actually talks to. Cross-link the SDK overview and REST API overview so the host difference is intentional rather than discovered.
5. Three async invocation patterns coexist; the docs never say which is current (significant)
Location: /api-reference/invoke-api, /api-reference/v1/agents/invoke-async, /api-reference/v1/agents/invoke-sync
Problem: There are three documented ways to invoke an agent asynchronously:
POST /v1/agents/{agent_id}/invoke?asynchronous=true(from/api-reference/invoke-api)POST /v1/agents/{agent_id}/invoke/async(dedicated endpoint,/api-reference/v1/agents/invoke-async)- The webhook URL
https://webhook.xpander.ai/?agent_id=<id>&asynchronous=falsereturned in the create-agent response
The reference pages don't acknowledge each other, and the invoke-api page warns against webhook.xpander.ai even though the create-agent API itself returns one.
Consequence: Developers can't tell which is the supported async pattern, which is legacy, and which is internal. The platform itself returns a webhook URL that the API docs tell you not to call.
The fix: Pick one canonical async invocation path, mark the others "deprecated" or "internal," and make the create-agent response field consistent with the documented public API.
6. Core invoke endpoints document only 422 (and sometimes 413) — no 401, 404, or 429 (significant)
Location: /api-reference/v1/agents/invoke-sync, /api-reference/v1/agents/invoke-async, /api-reference/v1/agents/invoke-stream, /api-reference/v1/agents/list-agents, /api-reference/v1/agents/deploy-agent, /api-reference/v1/tasks/list-tasks
Problem: The general REST page lists 200/201/400/401/404/422/500 as the status code set. But every single endpoint reference page only documents 422 (and 413 in one case). 401 (auth failure), 404 (unknown agent_id), and 429 (rate limit) aren't documented per-endpoint despite the platform advertising hard rate limits ("100 requests per minute" / "1000 requests per hour") and an x-api-key requirement.
Consequence: Developers writing retry/backoff and error-handling logic have no contract for what to expect when their key is wrong, the agent is deleted, or they're throttled. Coding agents generating typed clients can't model the error union. The OpenAPI 3.1 spec referenced in the overview may or may not match — readers have no way to tell from the prose pages.
The fix: Standardize an error-response table per endpoint that covers 401, 403, 404, 422, 429, 5xx — with the exact JSON shape for each — and ensure it matches the OpenAPI spec.
7. Agent user field schema differs between agent invoke and workflow invoke (significant)
Location: /api-reference/v1/agents/invoke-sync, /invoke-async, /invoke-stream vs. /api-reference/v1/workflows/invoke-sync
Problem: For /v1/agents/{id}/invoke*, the input.user object requires id and email. For /v1/workflows/{id}/invoke, the input.user object requires email, first_name, last_name, and external_id — same conceptual field, different mandatory keys. Separately, the streaming invoke page shows user without a "required" marker, contradicting the sync/async invoke pages that mark it required.
Consequence: Code that constructs a user payload once and reuses it across agent and workflow calls will get a 422 from one of them. Agents and SDK wrappers can't share a single user-identity helper. The streaming-vs-sync inconsistency means a developer migrating between modes can't tell whether user is optional or just under-documented.
The fix: Define one UserIdentity object in the OpenAPI spec, reference it from both agent and workflow invoke endpoints, and make required fields identical. If workflows genuinely need more identity fields, expose them as optional or document the rationale.
8. Task status enum is inconsistent across pages (significant)
Location: /api-reference/v1/tasks/list-tasks vs. /api-reference/v1/agents/invoke-async vs. /api-reference/v1/agents/invoke-sync
Problem: The task-status filter on /v1/tasks includes paused (along with pending, executing, error, failed, completed, stopped). The response schemas for invoke-async and invoke-sync enumerate pending | executing | completed | error | failed | stopped — no paused.
Consequence: Clients that pattern-match on task status will hit an unknown value when a task is paused, because the invoke responses' documented enum is a subset of reality. Typed SDKs generated from one page break when receiving values from the other.
The fix: Make the task-status enum a single referenced schema in the OpenAPI spec and document paused (and how a task enters that state) everywhere it can appear in a response.
9. Default model name in create-agent doesn't match the model name in the example response (significant)
Location: /api-reference/v1/agents/create-agent
Problem: The same page documents model_name default as claude-sonnet-4-6 and model_provider default as anthropic, but the example response shows model_provider: "openai" and model_name: "gpt-5.2". The deploy-agent example response shows yet another value: claude-sonnet-4-5-20250929.
Consequence: Developers can't tell what model their agent will actually run on if they omit those fields. Audit/compliance reviewers comparing the documented default to what's deployed see drift that isn't drift. Coding agents asked to "create an agent with the default model" pick whichever literal they saw last.
The fix: Regenerate example responses from real fixtures so example values respect documented defaults. If gpt-5.2 is the real current default, update the field-level docs to match.
10. Knowledge base example request and example response don't match (minor)
Location: /api-reference/v1/knowledge/create-knowledge-base
Problem: The example curl posts {"name": "Technical Documentation", "description": "Internal technical guides"} but the example response returns {"name": "Product Catalog", "description": "Product information and specifications", ...}. There's no note that the response is illustrative of a different KB.
Consequence: Readers wonder if the API silently renames things. Coding agents that round-trip the example as a sanity check produce mismatched fixtures.
The fix: Regenerate response examples from real fixtures so request and response refer to the same resource.
11. Two knowledge-base APIs documented, with no guidance on when to use which (significant)
Location: /api-reference/v1/knowledge/create-knowledge-base, /guides/agents/knowledge-bases, /Examples/08-knowledge-base-rag
Problem: The platform has a managed KB API (POST /v1/knowledge) and a UI flow with chunking/Top-K/similarity-threshold defaults. The RAG example (#08) bypasses both and wires Agno's PgVector directly using agno_agent.get_db() credentials. The example never explains why it ignores the documented managed knowledge base path, nor when a developer should pick one over the other.
Consequence: Developers don't know whether /v1/knowledge is the supported path going forward or a thin convenience over Agno's vector DB. Agents picking patterns to imitate end up wiring Postgres credentials into application code even though a managed endpoint exists.
The fix: Add a "Choosing a knowledge-base approach" page that contrasts managed KB (/v1/knowledge) with framework-native vector DBs (Agno PgVector). State the trade-offs (governance, multi-tenancy, portability) and link from both the API reference and the RAG example.
12. Stale URLs under /user-guide/* still surface in search and 404 (significant)
Location: Search across the docs site
Problem: The sitemap audit lists at least eleven user-guide/*, docs/01-get-started/*, and API%20reference/* URLs that Mintlify search still returns but that 404 on click — including user-guide/quick-start, user-guide/5-minute-wins/slack-agent-setup, user-guide/5-minute-wins/k8s-self-deploy, user-guide/backend-configuration/system-prompt, and user-guide/task-sources/slack.
Consequence: A developer searching "slack agent setup" or "quick start" gets dead links. External blog posts, Stack Overflow answers, and earlier changelog references that point at user-guide/* send people into 404 holes with no redirects to the new IA. Coding agents that crawled the site weeks ago and now follow their stored links land on errors.
The fix: Add 301 redirects from every stale user-guide/* and docs/01-get-started/* URL to its current equivalent (e.g., /user-guide/quick-start → /guides/quickstart or /developers/quickstart), and reindex search so dead URLs stop being suggested.
13. Self-hosted "BYOC on AWS/GCP/Azure" claim doesn't match the AWS-only Helm guide (significant)
Location: /overview/what-is-xpander vs. /self-hosted/deployment
Problem: The overview promises "Bring Your Own Cloud: Self-hosted Kubernetes on AWS, GCP, or Azure." The actual /self-hosted/deployment guide assumes AWS Route 53 for DNS, AWS ACM for the wildcard cert, AWS NLB for the ingress, and AWS PrivateLink as the alternative to public TLS. There's no GCP or Azure equivalent path documented.
Consequence: A GCP or Azure platform team kicking the tires can't actually self-host without inventing the cert/DNS/ingress story themselves. Sales-side claims and docs-side reality don't agree.
The fix: Either add a GCP and Azure deployment guide (cert-manager + Cloud DNS, Azure Front Door, etc.) or qualify the overview claim to "Kubernetes on any cloud; turnkey Helm chart available for AWS."
14. "SOUL" acronym expanded differently across docs (minor)
Location: /guides/core-concepts vs. /guides/quickstart
Problem: /guides/core-concepts defines SOUL as "System Orchestration & User Logic". The quickstart's "Configure Agent Personality (SOUL)" then lists the sub-fields as Who I Am, Vibe, Core Truths, Boundaries, Continuity, Current Focus — no mention of orchestration or user logic at all; it reads as personality config.
Consequence: Newcomers can't tell whether SOUL is a runtime orchestration construct or a persona/prompt template. Documentation reuse and prompt-engineering guidance ends up scattered because nobody knows which framing is canonical.
The fix: Pick one definition of SOUL, document its sub-fields once in the core-concepts page, and link the quickstart and Agent Studio docs to that single definition.
15. Connector count "100+ pre-built integrations" sits inside an article whose adjacent pages say 2,000+ and 50+ (minor)
Location: /guides/core-concepts ("100+"), /overview/what-is-xpander ("2,000+"), /llms.txt ("50+")
Problem: This is closely related to issue #3 but worth separating: even within a single user journey (overview → core-concepts → llms.txt), the numbers don't reconcile. Core-concepts lists "100+" without any note like "100 connectors exposing 2,000+ individual operations."
Consequence: Readers oscillate between believing the platform is broad-but-shallow vs. deep-and-mature within a few pages. Agents extracting "supported integrations" as a fact for product comparisons output whichever value won the page-load race.
The fix: Replace fixed-number prose with a generated count (e.g., a snippet rendered from a manifest) and explain the units. Tie this to the resolution of issue #3.
16. xpander deploy vs. xpander agent deploy — same command described two ways (minor)
Location: /Examples/00-setup-deployment vs. /developers/deployment/containers and /developers/cli-reference/overview
Problem: The setup-and-deployment example tells readers to run xpander deploy. The containers page and CLI reference use xpander agent deploy. The CLI reference does list xpander deploy as a "shortcut," but the relationship isn't called out in the example pages.
Consequence: Developers building CI/CD scripts (and coding agents writing those scripts) get mixed signals about whether the canonical form takes the agent subcommand. Pipelines that pin to one form may break if the shortcut is later removed.
The fix: Standardize on one form in all examples (recommended: xpander agent deploy) and explicitly document xpander deploy as an alias in the CLI reference.
What they do well
- An llms.txt file exists at
/llms.txt, giving coding agents a documented entry point — uncommon for platforms this size. - The MCP page is clear and actually useful: it gives both the standard and SSE endpoints and a copy-paste
claude_desktop_config.jsonblock. - The security/architecture page is unusually frank about the credential-brokering and least-privilege model, including the line "A capability that doesn't exist can't be jailbroken" — a concrete claim, not marketing fog.
Top 3 recommendations
- Pick one canonical quickstart and reconcile the CLI, SDK, and example install commands (
xpander init,xpander deploy,xpander agent deploy,pip install xpander-sdkvs.pip install xpander-sdk[agno]) so every "first 10 minutes" path agrees. - Make the OpenAPI spec the source of truth for endpoint shapes — fix the user-object divergence between agent and workflow invokes, document 401/404/429 per endpoint, add
pausedto the task-status enum everywhere it appears, and regenerate request/response examples from real fixtures (knowledge-base and create-agent are visibly desynced). - Resolve the OAuth2 vs. x-api-key contradiction: if Bearer JWT is GA per the May 10 2026 changelog, rewrite
/api-reference/invoke-apito support both schemes; if it's gated or beta, say so. Today the changelog and the API reference openly disagree about how to authenticate.