tools, the name agent loops use for them, so the class and attribute names on this page say tools while the prose says skills. This page is the SDK companion that tells you which Python class each of those concepts becomes when you import xpander_sdk.
User guide → Agents and conversations
The same model from Xpander Chat side. Read that for the concepts; read this for the class names.
The two halves
xpander splits responsibilities between a control plane (cloud or self-hosted) and your process. Reading code, you’ll move between three boundaries constantly:Backend
Backend is the class that fetches a fully resolved agent definition. Inside an @on_task handler, the typical use is one line:
- Model client with credentials.
- Instructions (system prompt, role, goal).
- Skills (from the skills catalog + your
@register_toolfunctions). - Session DB.
- Memory settings.
- Output schema.
agno.agent.Agent(**args) is the production pattern.
Pass the current task so the SDK can forward task-level overrides (instructions overrides, expected output, output schema) through to the agent loop. Both get_args (sync) and aget_args (async) accept the same arguments. The async form is what you’ll use inside @on_task and any FastAPI service; the sync form is fine in scripts and notebooks. This async/sync pairing holds across the entire SDK.
Agent
Agent is the loaded, in-memory representation of an agent. It carries everything the control plane knows about it:
- Name and unique identifier.
- Instructions (role, goal, general).
- Agent loop selection (the
frameworkfield). - Model + provider.
- Deployment type (
Serverless). - Skills, knowledge bases, sub-agents.
- Memory settings.
Agents().get(agent_id=...): returns a fully loadedAgent. Heavyweight.Agents().list(): returnsAgentsListItemsummaries (just names + IDs). Faster when you’re enumerating. Call.aload()on a list item to upgrade it to a fullAgent.
Task
ATask is one execution. It has an ID, a status, an input, and a result.
pending, executing, completed, failed, plus a few transitional states.
Inside @on_task, xpander creates the Task for you and you receive it as a parameter. Your job is to set task.result and return the task. The decorator marks it completed if you return cleanly, or failed if you raise.
Helpers on Task for agent-loop integration:
task.to_message(): joins input text, file URLs, and any embedded readable file content into a single string ready to feed into Agno.task.get_files(): returns PDFs asagno.media.Fileobjects.task.get_images(): returns image URLs asagno.media.Imageobjects.
Tasks().get(task_id). That’s how you implement retries, audit logging, or deferred result fetching.
Threads (sessions)
The SDK doesn’t have a class calledThread. What Xpander Chat shows as a thread is a session_id shared across multiple Tasks, with the conversation history persisted in the agent’s Postgres schema.
If your agent has Agno session storage enabled, you can list and inspect those sessions directly:
agent.get_db() returns the underlying agno.db.postgres.AsyncPostgresDb instance scoped to this agent’s schema. Reach for it directly only when you want to do something Agno doesn’t expose, like writing custom Postgres queries against session metadata.
Skills
Whatever you add to the agent in Xpander Chat under “Skills” becomes available in code as part ofagent.tools. There are three flavors:
- Catalog skills: pre-built skills from the skills catalog (Slack, Gmail, GitHub, and more). Authenticated and configured in Xpander Chat.
- Custom skills: Python functions you’ve decorated with
@register_toolin your handler. - Skills over MCP: served over the Model Context Protocol, either remote (URL) or local (process), wired in through Xpander Chat.
agent.tools: the unifiedToolsRepositorythat flattens all three into one list.agent.tools.listenumeratesToolobjects;agent.tools.functionsreturns normalized callables ready to bind to LangChain, OpenAI Agents SDK, or any agent loop that accepts plain Python functions.
Tool has a parameters JSON schema that the agent’s LLM uses to call it. The SDK auto-generates that schema from your function’s type hints and docstring, which is why annotation matters more than usual here.
Knowledge bases
KnowledgeBase represents one document collection. The xpander-managed type is the default; external KBs (your own vector store) are an advanced setup.
agent.knowledge_bases and queried automatically by the agent loop. Call kb.search directly only when you’re building something outside the agent loop, like a search box or a one-off enrichment job.
Memory
There are three kinds of memory, and they’re not the same thing. The Agno integration configures all of them throughagent.agno_settings:
- Session storage (
session_storage=True, default): keeps conversation history within a single thread. Postgres-backed, scoped per agent. - User memories (
user_memories=Trueoragentic_memory=True): facts the agent should remember about a specific user, across all their sessions. The two flags select between manual and agentic-managed mode. - Agent memories (
agent_memories=Trueoragentic_culture=True): organization-wide knowledge the agent should carry into every conversation. Same two-flag pattern.
- Session storage is essentially free.
- User and agent memories cost LLM calls to maintain.
Decorators
The SDK exports a small set of decorators that handle the lifecycle for you:@on_task: the entry point. Stands up the HTTP server and subscribes to xpander task stream.@on_boot/@on_shutdown: lifecycle hooks that run before and after the handler is registered.@register_tool: turns a Python function into an agent skill. SDK generates the JSON schema from your type hints.@on_tool_before/@on_tool_after/@on_tool_error: observe skill calls without modifying the skills themselves. Use for logging, metrics, alerting.@on_auth_event: fires when an MCP OAuth flow needs the user to log in.
@on_task; add @register_tool if you’re defining local skills. The rest are situational and covered in their own pages.
Configuration
Configuration is the explicit form of the credentials and base URL. Most code never instantiates it: the SDK reads from XPANDER_API_KEY, XPANDER_ORGANIZATION_ID, and XPANDER_BASE_URL automatically.
base_url, and the agent controller’s API key, not your cloud key. See SDK configuration for the full setup.
Cheat sheet
Next steps
SDK integrations: Agno
What
Backend.aget_args() actually wires up, with the AgnoSettings reference.Custom skills
The full
@register_tool decorator surface.Memory & State
Session storage, user memories, and agent memories explained.
SDK Reference
Per-method reference for every class on this page.

