Skip to main content
The Backend module resolves an agent stored on xpander into arguments for your code. It does three things:
  1. Resolves runtime arguments for your agent loop: aget_args(agent_id=..., task=task) returns kwargs you can spread directly into the Agno agent constructor (or another supported loop’s). In the SDK a skill is a Tool; the resolved tools kwarg carries them.
  2. Invokes agents directly: ainvoke_agent(agent_id=..., prompt=...) is shorthand for “load the agent, create a task.” Useful when you don’t need control over the agent loop.
  3. Reports externally executed runs: areport_external_task(...) lets you log a run that happened outside the runtime (e.g. in a queue consumer or another process) so it shows up in the same task history and metrics as runtime-managed runs.

Constructor

When called without arguments, the module reads XPANDER_API_KEY, XPANDER_ORGANIZATION_ID, and XPANDER_BASE_URL from the environment.

Methods

Typical pattern

@on_task listens for incoming task events from the runtime; the handler resolves the agent loop args for the current task, builds an Agno agent, runs it, and stores the result on the task. The runtime records status, metrics, and skill calls automatically.

Environment variable shortcut

Set XPANDER_AGENT_ID and you can omit agent_id from every Backend call:
Explicit arguments always override the env var.

get_args

Backend.aget_args returns a dictionary of keyword arguments ready for the agent loop of a stored agent. Spread the result directly into an Agno (or other supported loop’s) constructor: the dict already contains the model, system prompt, skills, memory settings, knowledge-base retrievers, and guardrails configured in Xpander Chat.
This is the primary integration point for code-based agents. Call it once per task, inside @on_task, passing the task so the resolved kwargs carry that run’s input, files, and output schema alongside the latest stored configuration.

Parameters

¹ Either agent_id or agent must be resolvable. If neither is passed, the method falls back to XPANDER_AGENT_ID. ² Optional in the signature, but pass it. The resolved kwargs are built from the task, so call aget_args from inside @on_task where a Task is in scope.

Returns dict[str, Any]

A dictionary of kwargs ready for the agent loop. The exact keys depend on the agent’s framework field (currently always Agno):
You don’t need to read these: pass them straight to the agent loop’s constructor.

Examples

Inside @on_task

Passing task=task enriches the args with task-specific context (session id, user id, output schema), so memory and structured output work transparently.

Pre-loaded agent (avoid re-fetching)

agent takes precedence over agent_id. This avoids a fresh GET /agents/:id call each time you build the agent loop args.

Override resolved kwargs

override is shallow-merged after the agent loop dispatcher builds its kwargs, so anything you set wins.

Add extra skills

The callable is appended to the agent’s skill list for this run only: it isn’t persisted to the runtime. For permanent skills, register with @register_tool instead.

Authentication events

When an agent uses skills that require OAuth, whether served over MCP or from the catalog, the SDK emits auth_event updates while the user authenticates. Register a callback to handle the OAuth URL or token-ready signals:

Per-call callback

Globally with @on_auth_event

You can combine both: decorated handlers are always invoked, and auth_events_callback adds a one-off handler on top. See @on_auth_event for details.

Sync version

Same parameters minus is_async (sync wrapper hard-codes it to False so local skills are wrapped synchronously). Don’t call from inside a running event loop.

invoke_agent

Backend.ainvoke_agent (and its sync sibling invoke_agent) is shorthand for “load the agent and create a task.” Internally it calls Agents.aget(agent_id) followed by Agent.acreate_task(...), returning the resulting Task. Use this when you want to invoke an agent from outside the @on_task runtime: for example, from a webhook handler, a script, or another agent.
If prompt happens to be a JSON string containing xpander_task_id, the method short-circuits and returns the existing task instead of creating a new one. This is how xpander passes task continuations through chat-style integrations.

Parameters

Returns Task

The created Task object, populated with the xpander-assigned id and an initial status of pending. See Task for the full attribute list.

Examples

Attach files

PDFs and images are auto-categorized by Task.get_files() / get_images() for Agno. Other file types (CSV, JSON, TXT, …) are inlined into the message via Task.to_message().

Structured output

Stream events

Continue an existing task

existing_task_id reuses the same memory thread, so the agent has full context from the prior run.

Per-end-user context

The User object scopes user-memory storage and connected accounts (e.g. OAuth tokens for Gmail or Calendar) to the right end user.

Sync version

Identical signature; blocks until the task is created. Don’t call from inside a running event loop: use ainvoke_agent there.

report_external_task

Backend.areport_external_task logs a task that was executed outside the xpander.ai runtime (for example, in a queue consumer, a Lambda, or a different process) so it shows up in the same task history, metrics, and activity views as runtime-managed tasks. Use this when you’ve called an LLM yourself (outside of an @on_task handler) but still want the run to count toward agent metrics and appear in the dashboard.

Parameters

¹ Either agent_id or agent must resolve. The method also reads XPANDER_AGENT_ID as a final fallback.

Returns Task

The xpander-side Task record after persistence. Re-using id returns the updated record; new ids create a fresh task.

Examples

Idempotent updates

Pass the same id to update an in-progress task as it makes progress:

Using a pre-loaded agent

Reporting a failure

is_success=False marks the task as failed in the dashboard.

Sync version

Same signature; blocks until the report is persisted.