This page builds an agent end-to-end from the command line. No Agent Studio, no clicking. By the end, you’ll have: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.
- Created the agent in xpander’s control plane.
- Run its handler locally against real prompts.
- Deployed it as a container reachable through the REST API and any channel you wire up later.
If you’d rather start with a visual builder, the Product Guides Quickstart walks through the same flow inside Agent Studio.
Prerequisites
- Node.js 20+ for the CLI.
- Python 3.12+ for the local dev server.
- An LLM provider key in your shell (
OPENAI_API_KEY,ANTHROPIC_API_KEY, or whichever provider you’ll use). The agent runs against this key locally; in production, you can override it from the agent config.
1. Install and authenticate
All three commands are required:- The CLI ships via npm.
- The SDK ships via pip.
loginwrites credentials that both the CLI and the SDK read.
2. Create the agent
xpander agent new does two things at once:
- It creates the agent in xpander’s control plane (giving it an ID, a default model, and an empty tool list).
- It scaffolds the project files into the folder you point at.
3. Read the handler
The scaffoldedxpander_handler.py is the canonical pattern for an xpander agent. Every example in the rest of these docs is a variation on this:
xpander_handler.py
Backend(...).aget_args(task=task)calls the xpander control plane and returns a dict containing the full agent configuration: instructions, tools, model with credentials, knowledge bases, session storage, memory settings.- That dict gets splatted into
agno.agent.Agent(...), which gives you a real Agno agent ready to run. - You run it with
arun(), capture the output, and write it back totask.result. - The
@on_taskdecorator stands up an HTTP server on port 59321 and subscribes to the platform’s task event stream, so any task created for this agent (from the API, Slack, Agent Studio, anywhere) is routed to your handler.
4. Run it locally
The simplest “just boot it” command, copy-paste with zero typing:- A local URL you can chat with.
- Once your dev process is running, every task created for this agent (REST API, Slack, Agent Studio chat, MCP, any channel) is routed to your local handler, not just locally-initiated tests.
- To iterate: edit
xpander_handler.py, save, restart.
5. Customize the agent (Optional)
The agent created by the CLI starts blank: a default system prompt, no tools. Openagent_instructions.json to rewrite the role, goal, and general description; the next xpander agent dev or xpander agent deploy syncs it to the control plane.
agent_instructions.json
role and goal are arrays so you can add or remove individual statements without rewriting the prompt. general is a free-form description that wraps around them.
Beyond that, each customization has its own page:
- Custom tools wrapped with
@register_tool. See Custom Tools. - Prebuilt connectors from the catalog (Slack, Gmail, GitHub, 2,000+). See Pre-built Tools.
- Knowledge bases for RAG. See Document Management.
- Memory (session storage, user memories, agent memories). See Memory & State.
- Tool hooks for logging, metrics, and guardrails around tool calls. See Tool Hooks.
- A different framework (OpenAI Agents SDK, LangChain, AWS Strands). See Frameworks.
6. Deploy
When the local version works, push it:- A new immutable version on every deploy (rolling back is one flag away).
- Reachability through the REST API and every channel you enable.
Troubleshooting
KeyError: Missing required environment variable: XPANDER_API_KEY
KeyError: Missing required environment variable: XPANDER_API_KEY
The handler imports before
.env is loaded. The scaffolded handler already includes from dotenv import load_dotenv; load_dotenv() at the top. If you wrote your own entry point, add it before any xpander_sdk import.`pip install xpander-sdk[agno]` says 'no matches found'
`pip install xpander-sdk[agno]` says 'no matches found'
zsh expands the brackets. Quote the package name:
pip install "xpander-sdk[agno]".`Address already in use: 59321`
`Address already in use: 59321`
Another
@on_task process is running. Either kill it, or set a different port for this one: XPANDER_STREAMING_PORT=59322 python xpander_handler.py.`401 Unauthorized` when invoking via curl
`401 Unauthorized` when invoking via curl
Tasks don't reach my local handler
Tasks don't reach my local handler
Inbound traffic goes to your deployed container by default. When a local dev instance is running, it takes over. If a container is already deployed, run
xpander agent stop first to free the slot, then start xpander agent dev again.`xpander agent invoke` returns instantly with no result
`xpander agent invoke` returns instantly with no result
xpander agent invoke posts to the agent’s webhook and waits for a sync response. If your handler is taking more than ~30 seconds, the webhook times out even though the task keeps running on the platform. Check the task’s status in the Monitor tab, or invoke through the async REST endpoint (/v1/agents/{id}/invoke-async) for long-running tasks.Next steps
Things you can do now that you couldn’t from Agent Studio alone:Custom tools
Wrap a private API as a tool with
@register_tool instead of a REST connector.Container deployment
Ship custom dependencies the serverless runtime doesn’t include (numerical libraries, system packages, internal SDKs).
Local MCP servers
Run MCP servers that need filesystem or process access.
Lifecycle hooks
Warmup, graceful shutdown, and observability around tool calls.
Core Concepts
The SDK class names and how they map to agents, tasks, threads, and memory.
Frameworks: Agno
What
Backend.aget_args() actually wires up.
