Skip to main content
Agno is the framework xpander.ai has the deepest integration with. In this guide, we’ll build a production-ready agent with credentials, instructions, tools, knowledge-base access, session DB, memory, guardrails, and a context-optimization pipeline.

Prerequisites

  • Complete the Quickstart so the CLI, SDK, and xpander login are already set up.
  • Python 3.12+ for the local handler.
  • An LLM provider key in your shell like OPENAI_API_KEY, ANTHROPIC_API_KEY. (These keys will only be used locally.)

1. Install

2. Set up scaffolding

These files get created:

xpander_config.json reference

xpander_config.json

3. Create task handler

The full pattern, wrapped in @on_task so the platform routes tasks to it:
xpander_handler.py
Here’s what’s happening:
  1. Backend(configuration=task.configuration) picks up the API key, organization ID, and base URL from the active task. No need to read .env directly.
  2. await backend.aget_args(task=task) calls the control plane and returns a dict with the full agent configuration (instructions, tools, model, knowledge bases, session storage, memory, guardrails). Always pass task=task inside an @on_task handler so task-level overrides (instructions_override, expected_output, output_schema) are merged in.
  3. Agent(**agno_args, debug_mode=True) splats that dict into Agno’s own Agent class. debug_mode prints tool calls and token usage; remove it for production.
  4. task.to_message() flattens the prompt text, file URLs, and any inline-readable file content into a single string ready for Agno. task.get_files() and task.get_images() return Agno-typed agno.media.File and agno.media.Image objects.
  5. Reporting task.tokens and task.used_tools is optional. Skipping them just means the metrics view in Agent Studio shows “no usage data” for that run.

backend.aget_args reference

Input parameters

backend.aget_args accepts these arguments: What can override change? override accepts any key Agno’s Agent.__init__ takes. Two ways to use it:
  1. Replace any value the SDK already resolves: any key from the output-params table below (model, instructions, tools, db, knowledge_retriever, pre_hooks, output_schema, and so on).
  2. Add Agno-native kwargs the SDK doesn’t set itself. Common ones:
See the Agno Agent reference for the full surface. Setting override["model"] skips the SDK’s own model resolution entirely, so use it whenever you want a different model client without re-implementing credential handling. Example using override to A/B-test two models against the same agent definition:
Example using override to tune Agno-native sampling parameters:
Example using tools to inject an ephemeral test tool:
For anything more invasive (a new pre-hook, a different DB), grab the args dict and mutate it directly before splatting into Agent(...). The dict is yours; the SDK won’t reach back in.

Output parameters

Calling backend.aget_args returns these fields:

4. Edit the agent’s system prompt

agent_instructions.json contains the agent’s system prompt and has exactly three fields:
agent_instructions.json
Save the file and the next xpander agent dev syncs it to the control plane.

5. Set up streaming (optional)

For token-by-token output, decorate an async def that yields TaskUpdateEvent objects instead of returning a Task. The decorator detects the difference automatically.
streaming_handler.py
Here’s what’s happening:
  1. stream=True, stream_events=True, yield_run_output=True tell Agno to emit events instead of buffering. The handler receives chunks, tool-call events, and a final RunOutput.
  2. The Chunk event forwards each token to the platform’s SSE stream so clients render output as it arrives.
  3. The TaskFinished event signals the end of the stream and carries the final task back to the platform.
A streaming handler exposes itself only through POST /invoke, returning Server-Sent Events. The platform’s SSE listener for cloud-deployed agents expects a regular handler that returns a Task. So if you need both an interactive streaming experience and platform-routed tasks, run two handlers, or have your streaming endpoint proxy through a regular handler.

6. Test local development

Run the handler with the dev server. Tasks created from any channel (REST, Slack, Agent Studio) route to your laptop:
Routing cloud traffic to a local instance is a preview feature.When a local instance is running via xpander agent dev, it takes over and all tasks route to your locally running agent instead. Only one can be active at a time.
For one-shot testing without a server:
--output_format and --output_schema are useful for testing structured output without changing the agent’s settings in the control plane.

Troubleshooting

Backend.aget_args() reads task.instructions_override while building the args. Inside an @on_task handler, always pass the active task: await backend.aget_args(task=task). The agent_id-only form is supported outside a handler (in scripts and notebooks), but inside one the active task is the source of truth for instruction overrides.
Session storage is on by default, so the args dict includes a db wired to xpander’s Postgres. For cloud-hosted agents this is automatic. For self-hosted or air-gapped deployments, the database needs to be reachable from where the agent runs. Check the connection string with await agent.aget_connection_string() and confirm the host is reachable. To turn session storage off, flip agno_settings.session_storage to False in Agent Studio.
Custom LLM keys configured on the agent take precedence on cloud deployments. Locally, your shell’s OPENAI_API_KEY (or the equivalent for your provider) wins. If you want the cloud-side custom key locally too, mirror it into your .env.
zsh expands the brackets. Quote the package name: pip install "xpander-sdk[agno]".

Next steps

Quickstart

The 10-minute scaffold-to-run walkthrough that produced the handler shown above.

Custom Tools

Wrap private APIs as tools with @register_tool and pass them through the args dict.

Memory & State

The deep dive on session_storage, user memories, and agent memories.

Core Concepts

The SDK class names mapped onto agents, tasks, threads, and memory.

Frameworks overview

What’s auto-wired vs. manual for Agno, OpenAI Agents SDK, LangChain, and AWS Strands.