Skip to main content
The Agents module is your entry point to agents stored on the runtime. Use it to discover what agents exist, load a specific one, and from there create tasks, invoke skills, attach knowledge bases, and inspect sessions. In the SDK a skill is a Tool; agent.tools lists them.

Constructor

Module methods

Agent instance methods

Once you’ve loaded an Agent, use its instance methods for the actual work: See the Agent class reference for attribute documentation.

Quick patterns

Find and load

Pin to a specific version

Versioning is opt-in. Without version, you get the latest.

Default agent via env var

This works because Agents.aget() falls back to Configuration.agent_id and then to XPANDER_AGENT_ID.

list

Agents.alist returns a list of summary objects (AgentsListItem) for every agent visible to the configured organization. Each item carries enough metadata for display (id, name, icon, status, instructions, access scope) and a .aload() shortcut to fetch the full Agent.

Parameters

None.

Returns list[AgentsListItem]

AgentsListItem is a lightweight summary: not the full Agent. Notable fields: To load the full agent (graph, skills, model config, …) call .aload() on the item, or pass item.id to agents.aget().

Examples

Filter active agents

Load all in parallel

Sync version

Same return type; blocks until the list is fetched.

Errors

alist raises ModuleException on failure:

get

Agents.aget loads one agent’s complete configuration: instructions, model settings, the execution graph, all attached skills, knowledge-base links, and agent loop settings. Use this whenever you need to actually invoke an agent or inspect its config in code.

Parameters

¹ The method falls back to Configuration.agent_id and then XPANDER_AGENT_ID. If none of those are set, you’ll hit a 404 from the cloud.

Returns Agent

A full Agent instance. See Agent class reference for attributes (instructions, framework, graph, deployment_type, tools, knowledge_bases, agno_settings, etc.).

Examples

Latest version

Pinned version

The version corresponds to deployment snapshots in Xpander Chat. Pin a version in production to avoid surprises when someone edits the agent.

Use a default agent ID

This is the pattern used inside @on_task handlers: you don’t pass an agent ID explicitly, because the runtime injects it.

Sync version

Same parameters; blocks until the agent is loaded.

What gets loaded

When you call aget, the SDK:
  1. Fetches the agent record (GET /agents/:id).
  2. Builds the AgentGraph from the graph items returned in the response.
  3. Initializes a ToolsRepository populated with the agent’s skills.
  4. If any local skills (Python @register_tool functions) need syncing to the runtime’s graph, kicks off a background sync_local_tools task: non-blocking.
You can read agent.graph to inspect the skill wiring, agent.tools.list for all skills, agent.knowledge_bases for KB links, and agent.mcp_servers for the configured MCP endpoints.

Errors

aget raises ModuleException on failure:

create_task

Agent.acreate_task creates a new task on xpander and returns a Task object you can save, stream, or stop. This is the primary way to invoke an agent from code.
The newly-created task is queued by the runtime; the agent’s run (either on the managed execution tier or in your local @on_task handler) picks it up and executes it.

Parameters

Returns Task

The created Task. See Task class reference. The task starts in status Pending. It moves through Executing → Completed (or Error / Failed / Stopped) as the agent’s run progresses.

Examples

With files

Structured output

Streaming

events_streaming=True is required to use task.aevents(). See task.events.

Continue a thread

The new task reuses the prior task’s memory thread, so the agent has full context.

Per-end-user

user_details.id scopes user-memory and the user’s connected accounts (e.g. each end user’s Gmail OAuth token).

Add an MCP endpoint just for this task

Per-task MCP endpoints stack on top of the agent’s persistent MCP configuration.

Pin a version

Sync version

Same parameters; blocks until the task is created. Don’t call from inside an event loop.

Errors

Raises ModuleException on failure:

invoke_tool

Agent.ainvoke_tool runs a single skill from the agent’s ToolsRepository and returns a ToolInvocationResult. Use it when you want to test a skill, or when you’re building an agent loop yourself and the loop’s own dispatcher isn’t a good fit.

Parameters

Returns ToolInvocationResult

is_success and is_error are mutually exclusive in normal operation; check is_error first.

Examples

With payload_extension

payload_extension is deep-merged with payload, so nested objects compose naturally.

Local Python skills

Skills registered with @register_tool are invoked locally (the fn runs in-process) and pass through the same ToolInvocationResult interface:
See @register_tool for details.

Inside an @on_task handler

Passing task_id ensures the invocation appears in task.aget_activity_log().

Sync version

Notes

  • Payload validation: if payload doesn’t match tool.schema, the SDK raises ValueError (not ModuleException). Catch it separately if you’re invoking with untrusted input.
  • Lifecycle hooks (@on_tool_before / @on_tool_after / @on_tool_error) fire around the invocation.
  • For invocations outside an agent context, use tool.get_invocation_function() instead: it requires a connector_id and operation_id resolved via tools.aload_tool_by_id(...).

Knowledge bases

Agents can have knowledge bases linked to them in Xpander Chat. From code, you can attach more, load the KnowledgeBase objects, or build a retriever callable for use in your agent loop.

aget_knowledge_bases

Load every KnowledgeBase linked to the agent, in parallel.

Returns list[KnowledgeBase]

A list of full KnowledgeBase objects. See KnowledgeBase for the methods you can call on each.

Sync version

attach_knowledge_base

Link a knowledge base to the agent on the in-memory instance. Pass either a KnowledgeBase object or a knowledge-base ID.

Parameters

You must pass at least one of the two. If both are passed, knowledge_base.id is used.
attach_knowledge_base only updates the agent in memory. To persist the link, save the agent through xpander (e.g. via the API or Xpander Chat UI). The runtime instance will use the link for the current session, but it won’t survive a re-load.

knowledge_bases_retriever

Returns a search(query, agent=None, num_documents=5) callable that searches every linked KB and returns top-N results sorted by score. This is the form Agno expects as a custom retriever.

Returned callable signature

Each result is a dict from KnowledgeBaseSearchResult.model_dump():
The retriever swallows errors and returns [] if the search fails: useful for embedding into agent loop pipelines that shouldn’t crash on retrieval errors.

Patterns

Wire as the Agno knowledge

Backend.aget_args already wires the retriever for you: you don’t need to call knowledge_bases_retriever() directly. Use it only when bypassing the Backend dispatcher.

Add a KB on the fly

After attach_knowledge_base, agent.aget_knowledge_bases() includes the new KB in the list.

Sessions

Agents running on the Agno loop with agno_settings.session_storage = True persist their session history to a Postgres database managed by the runtime. The SDK exposes that database via Agent.aget_db() plus a small set of helpers for session CRUD.
Sessions are only available for Agno agents with session storage enabled. Calling these methods on other agents raises NotImplementedError (wrong framework) or LookupError (storage disabled). The Agno extras must be installed: pip install xpander-sdk[agno].

aget_db

Returns the Agno Postgres client backing the agent’s session storage.

Parameters

Returns

agno.db.postgres.AsyncPostgresDb (or PostgresDb if async_db=False). The client is namespaced to the agent’s schema, so different agents don’t share a session table. The connection URI is fetched (and cached) via agent.aget_connection_string() on the first call.

Sync version

aget_user_sessions

Load all sessions for a given end-user.

Parameters

Returns

A list of session records. The exact type comes from Agno’s db.get_sessions(...): fields include session_id, user_id, agent_id (or team_id for Team mode), and timestamps. The query caps results at 50 sessions per call. For Team agents (agent.is_a_team == True), this returns SessionType.TEAM records; otherwise SessionType.AGENT.

Sync version

aget_session

Load a single session by ID.

Parameters

Returns

The session record, or None if it doesn’t exist.

Sync version

adelete_session

Delete a session.

Parameters

Sync version

Errors

All session methods raise:
  • NotImplementedError: agent isn’t using Agno.
  • LookupError: Agno is configured but agno_settings.session_storage is False.
  • ImportError: Agno extras not installed (run pip install xpander-sdk[agno]).
  • ValueError: connection URI couldn’t be resolved.

Patterns

Inspect recent sessions for a user

Wipe all sessions for a user

aget_user_sessions returns at most 50 records per call, so loop until empty for users with many sessions.

Drop into the Agno DB directly

Use this when the four convenience methods don’t cover what you need; the Agno DB client has a richer API.

Agent class

Agent is the rich object returned by Agents.aget() and AgentsListItem.aload(). It carries the agent’s full stored configuration, plus methods for creating tasks, invoking skills, and managing sessions.

Class methods

Agent.aload(agent_id, configuration=None, version=None) -> Agent

Load an agent by ID. This is what Agents.aget() calls internally. Use the module-level agents.aget(...) in normal code; Agent.aload(...) is for places where you have a Configuration but no Agents instance.
The sync sibling is Agent.load(...).

Attributes

Computed properties

Instance methods

Streaming spec

agent.aget_streaming_spec() -> StreamingSpecResponse: returns the deployed agent’s streaming URL and an API key for its /invoke endpoint. Useful when you want to bypass the SSE channel and POST directly to the deployed agent’s run.
StreamingSpecResponse has two fields: url (str | None) and api_key (str | None). Both can be None if the agent isn’t deployed yet.

Connection string

agent.aget_connection_string() -> DatabaseConnectionString: returns DB connection details for agents using session storage. The result is cached on the instance after the first call.
DatabaseConnectionString has id, name, organization_id, and connection_uri.uri (a Postgres-compatible URI).

sync_local_tools

await agent.sync_local_tools(tools=[...]): pushes locally-decorated @register_tool(add_to_graph=True) skills to the runtime’s graph. Called automatically when Agent.aload detects unsynced skills, so you rarely need to invoke it directly.