A deployed agent doesn’t care how a task arrives. The sameDocumentation Index
Fetch the complete documentation index at: https://docs.xpander.ai/llms.txt
Use this file to discover all available pages before exploring further.
@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:| Mode | Endpoint | Best for |
|---|---|---|
| Sync | /invoke | Short tasks (under 30s) where the caller needs the answer immediately. Blocks until complete, returns the full result. |
| Async | /invoke-async | Long-running tasks or callers that can’t hold a connection open. Returns a task ID immediately; poll or stream events later. |
| Stream | /invoke-stream | Real-time UIs. Returns a Server-Sent Events stream of TaskUpdateEvents as the agent runs. |
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 tohttps://webhook.xpander.ai/:
| Parameter | Location |
|---|---|
agent_id | Query string or body |
x-api-key | Header or query string |
| Parameter | Type | Description |
|---|---|---|
prompt | string | Text input for the agent. |
asynchronous | boolean | Return immediately without waiting. Default: false. |
task_id | string | Continue an existing conversation thread. |
user_id | string | User identifier for tracking and memory scoping. |
user_email | string | User email for personalization. |
user_first_name / user_last_name | string | User name for personalization. |
getter | string | Dot-notation path to extract from the response instead of returning the full payload. |
json | boolean | Parse the result as JSON instead of returning a string. |
user_tokens | string (JSON) | Pre-authenticated MCP OAuth tokens (see below). |
disable_attachment_injection | boolean | When 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. |
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.asynchronous=true to return immediately. Best for long-running tasks, file processing, or when you don’t need the result inline.
{"status": "Started"} immediately. Check the Monitor tab for the result.
Upload files
Upload files usingmultipart/form-data. The agent automatically processes them: OCR for images, text extraction for PDFs, transcription for audio.
Extract data from responses
Usegetter with dot notation to extract a specific field from the agent’s response instead of the full object:
"Q4 revenue increased 15%".
Map dynamic parameters
Useparams_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:
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 viauser_tokens to bypass the interactive OAuth flow during webhook execution:
graph.items for entries with type: "mcp".
Error codes
| Status | Response | Cause |
|---|---|---|
| 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. |
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:| Transport | URL |
|---|---|
| HTTP (default) | https://mcp.xpander.ai/ag_YOUR_AGENT_ID/ |
| SSE | https://mcp.xpander.ai/ag_YOUR_AGENT_ID/sse |
npx install-mcp command per client.
| Placeholder | What 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. |
--client cursor for --client claude or --client windsurf. Run once per client.
Raw JSON for any other MCP-compatible client:
~/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. Callinvoke_agent to start a task, then poll get_task_status until it completes.
| Tool | What it does |
|---|---|
invoke_agent | Creates an asynchronous agent task and returns the task details immediately, including the task ID. |
get_task_status | Checks the state of a task created with invoke_agent and returns its result once complete. |
invoke_agent parameters:
| Parameter | Required | Description |
|---|---|---|
prompt | Yes | Natural language prompt to send to the agent. |
get_task_status parameters:
| Parameter | Required | Description |
|---|---|---|
task_id | Yes | The 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 anx-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.
Troubleshooting
MCP server not showing in Claude Desktop
MCP server not showing in Claude Desktop
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.Authentication fails
Authentication fails
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.Agent invocation fails
Agent invocation fails
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:- 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.
- 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 inagent.tools.list once it’s been added as a dependency in Agent Studio:
- 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.
- 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. - 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.
@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.

