Skip to main content
An agent is the runtime’s central object: a configured LLM with instructions, skills, knowledge bases, memory, and a deployment target. In the SDK, skills are exposed as 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:
The SDK objects are thin wrappers around xpander’s HTTP API. They’re how you read and write to it from Python.

Backend

Backend is the class that fetches a fully resolved agent definition. Inside an @on_task handler, the typical use is one line:
The returned dict contains everything Agno needs:
  1. Model client with credentials.
  2. Instructions (system prompt, role, goal).
  3. Skills (from the skills catalog + your @register_tool functions).
  4. Session DB.
  5. Memory settings.
  6. Output schema.
Splatting it into 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:
  1. Name and unique identifier.
  2. Instructions (role, goal, general).
  3. Agent loop selection (the framework field).
  4. Model + provider.
  5. Deployment type (Serverless).
  6. Skills, knowledge bases, sub-agents.
  7. Memory settings.
Two collection helpers:
  • Agents().get(agent_id=...): returns a fully loaded Agent. Heavyweight.
  • Agents().list(): returns AgentsListItem summaries (just names + IDs). Faster when you’re enumerating. Call .aload() on a list item to upgrade it to a full Agent.

Task

A Task is one execution. It has an ID, a status, an input, and a result.
Status values: 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 as agno.media.File objects.
  • task.get_images(): returns image URLs as agno.media.Image objects.
Load a task by ID later with 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 called Thread. 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:
Behind the scenes, 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 of agent.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_tool in 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 unified ToolsRepository that flattens all three into one list. agent.tools.list enumerates Tool objects; agent.tools.functions returns normalized callables ready to bind to LangChain, OpenAI Agents SDK, or any agent loop that accepts plain Python functions.
Each 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.
agent.tools.functions is a plain list of function-calling schemas, so you can import an xpander agent’s skill list into any LLM client that accepts plain Python callables, including raw openai.OpenAI().chat.completions.create(tools=[...]) calls or a homegrown ReAct loop. This is the escape hatch when none of the supported SDK integrations fit your stack.

Knowledge bases

KnowledgeBase represents one document collection. The xpander-managed type is the default; external KBs (your own vector store) are an advanced setup.
Inside an agent, a KB is attached through 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 through agent.agno_settings:
  • Session storage (session_storage=True, default): keeps conversation history within a single thread. Postgres-backed, scoped per agent.
  • User memories (user_memories=True or agentic_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=True or agentic_culture=True): organization-wide knowledge the agent should carry into every conversation. Same two-flag pattern.
Each kind is a separate switch because they each have a cost and a use case:
  1. Session storage is essentially free.
  2. User and agent memories cost LLM calls to maintain.
Pick what you need, leave the rest off. The deep dive is in Memory & State.

Decorators

The SDK exports a small set of decorators that handle the lifecycle for you:
What each one does:
  • @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.
Every agent needs @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.
Self-hosted deployments are the main reason to construct one explicitly. You need a custom 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.