xpander.ai ships 2,000+ pre-built connectors (Slack, Gmail, GitHub, Salesforce, and more). You select which ones an agent can use in Agent Studio; the SDK then exposes them as ready-to-call functions on the loadedDocumentation Index
Fetch the complete documentation index at: https://docs.xpander.ai/llms.txt
Use this file to discover all available pages before exploring further.
Agent. No manual fetching, no schema conversion, no client setup.
Prerequisites
- Complete the Quickstart so the CLI, SDK, and
xpander loginare already set up. - Python 3.12+ for the local handler.
1. Set up connectors in Agent Studio
Setup is a one-time UI flow: pick a connector, authenticate, attach the actions you want to your agent. Once published, the connector’s actions are live on every loadedAgent instance and reachable from any framework you bind them into.
Set up connectors in Agent Studio
Pick a connector, authenticate, attach actions to your agent.

2. List all available tools
Once a connector is attached, your agent has access to three types of tools:- Connector tools: every action you selected from a pre-built connector (Slack, Gmail, GitHub, etc.)
- Custom tools: Python functions you decorated with
@register_tool - MCP tools: tools from any MCP server you’ve attached
agent.tools.list to enumerate all of them:
- Build a UI that shows the user which capabilities an agent has before they prompt it.
- Sanity-check after a publish that the connector you just attached actually shows up.
- Filter the tool list at runtime (e.g. drop write-actions when running in a read-only context).
Inspect individual tools
If you want to inspect the exact shape that’s about to be handed to the framework (debugging “are my FunctionTools correct?”, “did the LangChain callables get their docstrings?”), enumerate the framework-specific list instead:- Agno
- OpenAI Agents SDK
- LangChain
- AWS Strands
The args dict from
Backend.aget_args() carries the resolved tools list. Iterate args["tools"] to see exactly what Agno will receive:| Property | Returns | What it’s for |
|---|---|---|
agent.tools.list | list[Tool] | Canonical enumeration. Each Tool carries id, name, description, parameters (raw JSON schema), and a Pydantic schema. |
agent.tools.functions | list[Callable] | Normalized callables, one per tool, with a payload: <PydanticModel> parameter and an LLM-friendly docstring. Bind them straight into LangChain, OpenAI Agents SDK, or any “plain Python function” framework. |
agent.tools.get_tool_by_id(id) / get_tool_by_name(name) | Tool | Look up a single tool when you want to invoke it by hand. |
3. Bind tools into the framework
Listing tools tells you what the agent can do. Binding them is what gets the LLM to actually call them. Every framework wants tools in its own shape, and the xpander Agent exposes one property per supported framework, computed off the same underlying tool list:- Agno
- OpenAI Agents SDK
- LangChain
- AWS Strands
xpander_handler.py
4. Invoke a tool yourself (optional)
Most of the time the framework decides when to call a connector. But you can also reach in and call one directly. Use this to:- Run an admin or migration script that calls a connector 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 tool against each.
- Test a connector’s payload shape end-to-end before exposing it to the LLM.
agent.tools.get_tool_by_id(...)looks up the connector tool by its stable identifier. Useget_tool_by_name(...)if you have the human-readable name instead.- The
payloadmirrors the tool’s JSON schema. Connector tools typically havebody_params,path_params, andquery_paramsas the top-level keys, mapping to the underlying API’s request shape. Inspecttool.parametersif you need the schema. ToolInvocationResultcomes back withis_success(bool) andresult(the raw response). Checkis_successbefore consumingresult.
agent.invoke_tool(...) exists with the same signature.
5. Pass per-request context to every tool call
When the same agent definition serves many tenants, customers, or users, you usually need to stamp something onto every connector 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 whattool_call_payload_extension is for. It deep-merges into every tool call’s payload for the lifetime of the task:
- Multi-tenant: stamp the tenant ID on every downstream call so connector requests scope correctly.
- Per-user OAuth: pass a user-scoped token override into
body_paramsor a custom auth header. - Traceability: add a request ID to every connector call so you can follow a single user’s actions across systems.
| Where you pass it | Argument | Scope | When to use |
|---|---|---|---|
agent.acreate_task(...) | tool_call_payload_extension: Optional[dict] = None | Every tool call inside the task. | The default. Stamping context that’s the same for the whole task (tenant ID, request ID, user token). |
Backend.ainvoke_agent(...) | tool_call_payload_extension: Optional[dict] = None | Every tool call inside the task implicitly created by the invoke. | When you’re invoking an agent through Backend rather than creating a task explicitly. |
agent.ainvoke_tool(...) | payload_extension: Optional[Dict] = {} | One tool invocation. | Reaching past the LLM to call a specific tool by hand and you only want to stamp this call. |
body_params, path_params, query_params) when extending, otherwise the keys land at the wrong level and the connector ignores them.
Troubleshooting
`agent.tools.list` is empty
`agent.tools.list` is empty
The agent has no connectors attached, or the connectors you attached aren’t published yet. Open the agent in Agent Studio, check the Tools tab for at least one entry, and click Publish if you see a “Deploy changes” banner. Then reload the agent:
agent = await Agents().aget(agent_id=...).Tool call returns `is_success=False` with a 4xx body error
Tool call returns `is_success=False` with a 4xx body error
The payload doesn’t match the connector’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.`tool_call_payload_extension` doesn't show up in tool calls
`tool_call_payload_extension` doesn't show up in tool calls
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 tool’s body_params; it won’t appear in query_params. Mirror the tool’s payload structure when extending.Next steps
Custom tools
Add your own Python functions alongside connectors with
@register_tool.Tool hooks
Observe, log, and rewrite every tool call across the agent’s lifetime.
Output Response Filtering
How large tool responses get filtered before reaching the LLM.
Connectors catalog
Browse all 2,000+ pre-built integrations.
Set up connectors in Agent Studio
The UI walkthrough: connections, OAuth, attaching actions.
Frameworks
How
agent.tools.functions, openai_agents_sdk_tools, and strands_tools map onto each framework.
