Skip to main content
The Backend module is the bridge between your code and an agent stored in the xpander.ai platform. It does three things:
  1. Resolves runtime arguments for your AI framework: aget_args(agent_id=..., task=task) returns kwargs you can spread directly into Agno (or another supported framework’s) agent constructor.
  2. Invokes agents directly: ainvoke_agent(agent_id=..., prompt=...) is shorthand for “load the agent, create a task.” Useful when you don’t need framework-level control.
  3. Reports externally executed runs: areport_external_task(...) lets you log a run that happened outside the platform (e.g. in a queue worker or another runtime) so it shows up in the same task history and metrics as platform-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 platform; the handler resolves framework args for the current task, builds an Agno agent, runs it, and stores the result on the task. The platform records status, metrics, and tool 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 framework-ready keyword arguments for a stored agent. Spread the result directly into an Agno (or other supported framework’s) constructor: the dict already contains the model, system prompt, tools, memory settings, knowledge-base retrievers, and guardrails configured in the Workbench.
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 framework-ready kwargs. The exact keys depend on the agent’s framework (currently always Agno):
You don’t need to read these: pass them straight to the framework’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 framework args.

Override resolved kwargs

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

Add extra tools

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

Authentication events

When an agent uses MCP servers or connectors that require OAuth, the framework 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 tools 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 the platform passes task continuations through chat-style integrations.

Parameters

Returns Task

The created Task object, populated with the platform-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 connector authentication (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 worker, a Lambda, or a different process) so it shows up in the same task history, metrics, and observability views as platform-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 platform-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.