Skip to main content
xpander.ai ships pre-built skills (Slack, Gmail, GitHub, Salesforce, and more) that expose their operations as callable functions. You select which ones an agent can use in Xpander Chat; the SDK then exposes them as ready-to-call functions on the loaded Agent. In the SDK a skill is a Tool; agent.tools lists them. No manual fetching, no schema conversion, no client setup.

Prerequisites

  • Complete the Quickstart so the CLI, SDK, and xpander login are already set up.
  • Python 3.12+ for the local handler.

1. Set up skills in Xpander Chat

Setup is a one-time UI flow: use Add skill in the agent’s settings, pick a skill, connect your account if it asks, and attach the operations you want (see Skills on an agent for the full flow). Once published, the skill’s operations are live on every loaded Agent instance and reachable from any agent loop you bind them into.

Set up skills in Xpander Chat

Pick a skill, connect your account, attach operations to your agent.
Skills attached to an agent in Xpander Chat, with each connection and its access level Everything below assumes you’ve done this and your agent has at least one skill attached.

2. List all available skills

Once a skill is attached, your agent has access to it. xpander’s kinds of skill are described on the catalog; from the SDK they arrive as three groups:
  • Catalog skills: every operation you selected from a pre-built skill (Slack, Gmail, GitHub, etc.)
  • Custom skills: Python functions you decorated with @register_tool
  • MCP skills: skills from any MCP endpoint you’ve attached
Use agent.tools.list to enumerate all of them:
This is what you’d use to:
  • Build a UI that shows the user which capabilities an agent has before they prompt it.
  • Sanity-check after a publish that the skill you just attached actually shows up.
  • Filter the skill list at runtime (e.g. drop write-operations when running in a read-only context).

Inspect individual skills

If you want to inspect the exact shape that’s about to be handed to the agent loop (debugging “are my FunctionTool objects correct?”, “did the LangChain callables get their docstrings?”), enumerate the loop-specific list instead:
The args dict from Backend.aget_args() carries the resolved skills list. Iterate args["tools"] to see exactly what Agno will receive:
Three properties you’ll reach for most often:

3. Bind skills into the agent loop

Listing skills tells you what the agent can do. Binding them is what gets the LLM to actually call them. Each agent loop (Agno, OpenAI Agents SDK, LangChain, AWS Strands) wants its functions in its own shape, and the xpander Agent exposes one property per supported loop, computed off the same underlying skill list:
xpander_handler.py
See the Agno page for the full walkthrough.

4. Invoke a skill yourself (optional)

To call a skill outside the agent loop: Use this to:
  • Run an admin or migration script that calls a skill once (send a Slack announcement, archive a Salesforce record) without standing up a full agent loop.
  • Backfill or batch-process by iterating over a queue of inputs and firing the same skill against each.
  • Test a skill’s payload shape end-to-end before exposing it to the LLM.
What this means in practice:
  1. agent.tools.get_tool_by_id(...) looks up the skill by its stable identifier. Use get_tool_by_name(...) if you have the human-readable name instead.
  2. The payload mirrors the skill’s JSON schema. Catalog skills typically have body_params, path_params, and query_params as the top-level keys, mapping to the underlying API’s request shape. Inspect tool.parameters if you need the schema.
  3. ToolInvocationResult comes back with is_success (bool) and result (the raw response). Check is_success before consuming result.
The sync form agent.invoke_tool(...) exists with the same signature.

5. Pass per-request context to every skill call

When the same agent definition serves many tenants, customers, or users, you usually need to stamp something onto every skill call (a tenant ID, a customer ID, a request ID, an OAuth token override) without putting it in the prompt or hardcoding it on the agent. That’s what tool_call_payload_extension is for. It deep-merges into every skill call’s payload for the lifetime of the task:
Common shapes:
  • Multi-tenant: stamp the tenant ID on every downstream call so skill requests scope correctly.
  • Per-user OAuth: pass a user-scoped token override into body_params or a custom auth header.
  • Traceability: add a request ID to every skill call so you can follow a single user’s actions across systems.
The same dict surface is accepted on three call sites, scoped differently: The merge is deep, not shallow. Mirror the skill’s payload shape (body_params, path_params, query_params) when extending, otherwise the keys land at the wrong level and the skill ignores them.

Troubleshooting

The agent has no skills attached, or the skills you attached aren’t published yet. Open the agent in Xpander Chat, check the Skills row for at least one entry, and click Publish if the agent has unpublished changes. Then reload the agent: agent = await Agents().aget(agent_id=...).
The payload doesn’t match the skill’s expected shape. Inspect tool.parameters (raw JSON schema) and confirm body_params, path_params, and query_params line up with the underlying API. The Pydantic tool.schema is also useful for type-checking the payload before sending.
The extension is deep-merged, so it only adds keys at the same path. If you pass {"body_params": {"tenant_id": "..."}}, it merges into the skill’s body_params; it won’t appear in query_params. Mirror the skill’s payload structure when extending.

Next steps

Custom skills

Add your own Python functions alongside catalog skills with @register_tool.

Skill call hooks

Observe, log, and rewrite every skill call across the agent’s lifetime.

Output Response Filtering

How large skill responses get filtered before reaching the LLM.

Skills catalog

Browse all pre-built skills.

Set up skills in Xpander Chat

The UI walkthrough: connected accounts, OAuth, attaching operations.

Agent loops

How agent.tools.functions, openai_agents_sdk_tools, and strands_tools map onto Agno, OpenAI Agents SDK, LangChain, and AWS Strands.