Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.xpander.ai/llms.txt

Use this file to discover all available pages before exploring further.

A deployed agent doesn’t care how a task arrives. The same @on_task handler runs whether the input came from a Slack message, a webhook, a cron trigger, or another agent. You enable channels per agent in the Workbench under the agent’s Channels tab.

REST API

The default channel. Every agent is reachable through the platform’s REST API as soon as it’s deployed:
curl -X POST "https://api.xpander.ai/v1/agents/{agent_id}/invoke" \
  -H "x-api-key: $XPANDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input": {"text": "Summarize the attached file"}}'
Three invocation modes:
ModeEndpointBest for
Sync/invokeShort tasks (under 30s) where the caller needs the answer immediately. Blocks until complete, returns the full result.
Async/invoke-asyncLong-running tasks or callers that can’t hold a connection open. Returns a task ID immediately; poll or stream events later.
Stream/invoke-streamReal-time UIs. Returns a Server-Sent Events stream of TaskUpdateEvents as the agent runs.
Full endpoint reference: REST API → Agents.

Slack

Deploys your agent as a bot in your Slack workspace. Any DM or channel mention routes to your agent’s @on_task handler. The user who sends the message becomes the user_id on the task, so user memories work out of the box. Set up in the Workbench under the agent’s Channels tab. Each Slack workspace is one connection; the Workbench walks through OAuth.

Webhooks

Webhooks let any system that can make an HTTP POST trigger an agent run: automation platforms like Zapier, form submissions, CI/CD pipelines, or your own backend.

Enable

In Agent Studio, open the Channels tab, enable Webhook, and click Configure and test. The tester shows your payload URL (with agent ID and API key embedded) and a ready-to-use cURL command.

Make requests

All webhook requests are POST to https://webhook.xpander.ai/:
curl -X POST 'https://webhook.xpander.ai/?agent_id=YOUR_AGENT_ID' \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: YOUR_API_KEY' \
  -d '{"prompt": "Summarize the latest support tickets"}'
Required parameters:
ParameterLocation
agent_idQuery string or body
x-api-keyHeader or query string
Optional parameters:
ParameterTypeDescription
promptstringText input for the agent.
asynchronousbooleanReturn immediately without waiting. Default: false.
task_idstringContinue an existing conversation thread.
user_idstringUser identifier for tracking and memory scoping.
user_emailstringUser email for personalization.
user_first_name / user_last_namestringUser name for personalization.
getterstringDot-notation path to extract from the response instead of returning the full payload.
jsonbooleanParse the result as JSON instead of returning a string.
user_tokensstring (JSON)Pre-authenticated MCP OAuth tokens (see below).
disable_attachment_injectionbooleanWhen true, uploaded files are not injected into the LLM context window. File URLs are still available to the agent’s tools, but raw content is not prepended to the prompt. Useful when files are large or a tool handles processing directly.
Any additional fields in the request body are passed to the agent as context.
When the same parameter appears in multiple places, query parameters take priority over body parameters, which take priority over defaults.

Sync vs async

Synchronous (default): blocks until the agent finishes and returns the full result.
{
  "id": "task-uuid",
  "agent_id": "your-agent-id",
  "status": "completed",
  "result": "The agent's response...",
  "created_at": "2026-01-29T00:40:46.161472+00:00",
  "finished_at": "2026-01-29T00:40:47.919145+00:00",
  "source": "webhook",
  "execution_attempts": 1
}
Asynchronous: set asynchronous=true to return immediately. Best for long-running tasks, file processing, or when you don’t need the result inline.
curl -X POST 'https://webhook.xpander.ai/?agent_id=YOUR_AGENT_ID&asynchronous=true' \
  -H 'x-api-key: YOUR_API_KEY' \
  -d '{"prompt": "Generate the monthly report"}'
Returns {"status": "Started"} immediately. Check the Monitor tab for the result.

Upload files

Upload files using multipart/form-data. The agent automatically processes them: OCR for images, text extraction for PDFs, transcription for audio.
curl -X POST 'https://webhook.xpander.ai/?agent_id=YOUR_AGENT_ID' \
  -H 'x-api-key: YOUR_API_KEY' \
  --form 'files=@"/path/to/document.pdf"' \
  --form 'files=@"/path/to/image.png"'
Supported formats: PDF, DOC, DOCX, TXT, XLS, XLSX, CSV, PNG, JPEG, GIF, WEBP, SVG, ZIP. Uploaded files are stored on the xpander platform and exposed to your agent through presigned URLs scoped to your organization. URLs remain valid for 30 days after upload. For large batches (10+ files), use async mode and break uploads into batches of 5–10 files.

Extract data from responses

Use getter with dot notation to extract a specific field from the agent’s response instead of the full object:
curl -X POST 'https://webhook.xpander.ai/?agent_id=YOUR_AGENT_ID&getter=result.summary' \
  -H 'x-api-key: YOUR_API_KEY' \
  -d '{"prompt": "Analyze quarterly report"}'
Returns the extracted value directly: "Q4 revenue increased 15%".

Map dynamic parameters

Use params_mapping as a query parameter to extract values from nested payload fields and map them to webhook parameters. Useful for Telegram bots, WhatsApp, and other messaging platforms where identifiers are nested:
curl -X POST 'https://webhook.xpander.ai/?agent_id=YOUR_AGENT_ID&params_mapping={"task_id":"message.chat.id","prompt":"message.text","user_email":"message.from.email"}' \
  -H 'x-api-key: YOUR_API_KEY' \
  -d '{
    "message": {
      "chat": {"id": 123456789},
      "from": {"email": "user@example.com"},
      "text": "Hello agent!"
    }
  }'
Supports all standard parameters: task_id, user_id, user_email, user_first_name, user_last_name, prompt.

Pass MCP OAuth tokens

If your agent uses MCP servers with OAuth authentication, pass pre-authenticated user tokens via user_tokens to bypass the interactive OAuth flow during webhook execution:
curl -X POST 'https://webhook.xpander.ai/?agent_id=YOUR_AGENT_ID' \
  -H 'x-api-key: YOUR_API_KEY' \
  -d '{
    "prompt": "Check my calendar",
    "user_email": "user@example.com",
    "user_tokens": {
      "mcp-graph-item-uuid-1": "user-access-token-abc123"
    }
  }'
To find the graph item IDs for your MCP servers, call the Get Agent API and inspect graph.items for entries with type: "mcp".

Error codes

StatusResponseCause
400{"detail": "agent_id is required"}Missing agent_id parameter.
401{"detail": "API key not specified"}Missing x-api-key header or query param.
403{"detail": "Invalid API key"}Wrong API key or no access to this agent.
The x-api-key header is the only auth on the webhook endpoint by default. If you need request signing (HMAC for GitHub webhooks, signature verification for Stripe), validate it inside your handler before consuming the payload. The platform doesn’t validate third-party signatures for you.

MCP (Model Context Protocol)

Exposes your agent as an MCP server so developer tools like Claude Desktop, Cursor, and VS Code can call it directly. Your team works in the tools they already have; xpander handles running the agent.
MCP is not available for Personal Agents. Create a Custom Agent to use MCP.

Enable

In Agent Studio, open the Channels tab, enable MCP, and click Details. The modal shows your MCP server URL, API key, and transport options. Under Easy setup, select your client and copy the ready-to-paste configuration. Click Publish to make the server live.

Connect from a client

The MCP server supports two transports:
TransportURL
HTTP (default)https://mcp.xpander.ai/ag_YOUR_AGENT_ID/
SSEhttps://mcp.xpander.ai/ag_YOUR_AGENT_ID/sse
HTTP works with all current MCP clients. SSE (Server-Sent Events) enables server-initiated updates during long-running tasks. Easy setup for Cursor, Claude Desktop, Windsurf: Agent Studio generates an npx install-mcp command per client.
npx install-mcp <URL> \
  --name "<NAME>" \
  --client cursor \
  --header "x-api-key:<API_KEY>" \
  -y --oauth no
PlaceholderWhat to use
<URL>The per-agent MCP URL from the Details modal (append /sse for SSE transport).
<NAME>A short slug for the server in your client’s MCP list, e.g. support-bot.
<API_KEY>The API key from the Details modal.
Swap --client cursor for --client claude or --client windsurf. Run once per client. Raw JSON for any other MCP-compatible client:
{
  "your_agent_name": {
    "command": "npx",
    "args": [
      "mcp-remote",
      "https://mcp.xpander.ai/ag_YOUR_AGENT_ID/",
      "--header",
      "Authorization:${AUTH_TOKEN}"
    ],
    "env": {
      "AUTH_TOKEN": "Bearer YOUR_API_KEY"
    }
  }
}
Paste into the client’s config file (e.g., ~/Library/Application Support/Claude/claude_desktop_config.json on macOS). Restart the client after saving.

Available tools

Each agent’s MCP server exposes two tools. The flow is asynchronous because agent runs can take seconds to minutes. Call invoke_agent to start a task, then poll get_task_status until it completes.
ToolWhat it does
invoke_agentCreates an asynchronous agent task and returns the task details immediately, including the task ID.
get_task_statusChecks the state of a task created with invoke_agent and returns its result once complete.
invoke_agent parameters:
ParameterRequiredDescription
promptYesNatural language prompt to send to the agent.
get_task_status parameters:
ParameterRequiredDescription
task_idYesThe task ID returned from invoke_agent.

Authentication and security

Each MCP server is protected by a per-agent API key generated in Agent Studio. The client passes it on every request as an x-api-key header (via npx install-mcp) or as Authorization: Bearer <key> (Raw JSON). No interactive OAuth.
  • Per-agent scope: the key only authorizes calls to that agent’s two MCP tools. It can’t access other agents or org-level operations.
  • Revoke anytime: rotate or revoke the key from the MCP section of the Channels tab.
The API key is stored in the client’s MCP config file. Treat that file as a secret. Don’t commit it or share it.

Troubleshooting

Verify your claude_desktop_config.json is valid JSON. Check the file location: ~/Library/Application Support/Claude/claude_desktop_config.json on macOS. Restart Claude Desktop completely. Check Claude logs at ~/Library/Logs/Claude/mcp.log.
Confirm the API key in your MCP config matches the one in the Agent Studio Details modal. If you rotated the key, re-run install-mcp or update the Raw JSON config. Check that the agent isn’t restricted to specific users in org permissions.
Verify the agent is published in Agent Studio and not stopped or in an error state. Check the agent’s logs in the Monitor tab.

Scheduled tasks (cron)

A cron expression that creates a task on a schedule. The task input is whatever you configure in the Workbench: a fixed prompt or a templated one with placeholders. The agent’s @on_task handler runs as if a user invoked it. Use this for recurring work like “every morning, summarize yesterday’s deploys” or “every hour, check for new GitHub issues and triage them.”

Agent-to-agent (A2A)

A2A lets other agents (inside or outside your organization) discover and invoke this agent via Google’s Agent2Agent protocol. This is how multi-agent teams compose: a manager agent delegates to specialist agents by calling them as tools.

Enable

In Agent Studio, open the Channels tab, enable A2A, then:
  1. Click Agent card to see the agent’s A2A identity: its Agent A2A URL, name, and version. This is what external agents use to discover and call it.
  2. Click Manage API keys to generate credentials. External agents authenticate with these keys on every call. Generate one per external agent or team to keep access scoped and revocable.

Call an agent from code

From a parent agent’s handler, calling a child agent looks like calling any other tool. The child appears in agent.tools.list once it’s been added as a dependency in Agent Studio:
from xpander_sdk import Agents

parent_agent = Agents().get(agent_id="agt_parent...")
result = await parent_agent.ainvoke_tool(
    tool=parent_agent.tools.get_tool_by_name("call_specialist_agent"),
    payload={"prompt": "Investigate this incident and return a summary"},
)
print(result.is_success, result.result)
What this means in practice:
  1. The child agent runs its full loop. It has its own tools, instructions, memory, and knowledge bases. The parent only sees the final output as a tool result.
  2. Each agent has its own A2A URL. External systems (agents on other platforms) can discover and call your agent at https://a2a.xpander.ai/ag_YOUR_AGENT_ID/ using the A2A protocol.
  3. API keys are per external agent. Generate a separate key for each external caller so you can revoke access independently. The keys are scoped to the A2A channel; they can’t be used to invoke the agent through REST or webhooks.

Cross-platform delegation

The A2A protocol is designed for agents on different platforms to call each other. An agent built on LangChain, AutoGen, or any other A2A-compatible framework can invoke your xpander agent at its A2A URL using a standard A2A request, and vice versa. The Workbench graph view lets you visualize agent relationships across your organization.

Picking a channel

Most agents end up enabling more than one. A common pattern:
  • REST for programmatic access and backend integrations.
  • Slack for the team.
  • MCP for individual developers in their IDE or Claude Desktop.
  • Webhooks for inbound triggers from external systems (GitHub, Stripe, Zapier).
  • Cron for scheduled routine work.
  • A2A for delegation from a manager agent or cross-platform invocation.
All channels route through the same @on_task handler. There’s no per-channel cost in the SDK.

Things to watch for

Channels can collide in subtle ways. A scheduled task that fires every minute while a Slack user is mid-conversation creates two concurrent invocations against the same agent and sometimes the same session. If your handler isn’t idempotent, you’ll see weird interleavings in the conversation history. Either scope cron tasks to dedicated agents, or design handler logic that tolerates concurrent runs against the same session.

Next steps

REST API reference

Sync, async, and stream endpoints.

MCP guide

Full MCP setup walkthrough with screenshots.

Webhooks guide

Full webhook reference with the Workbench tester.

Scheduled tasks

Cron-driven invocations.