1. Define the schema
A tool schema is a plain dict. Write the description for the model: say what the tool does and when to reach for it.inputSchema and input_schema are both accepted.
2. Write the handler
A handler is an async function. Its return value is used twice: as the event streamed to the user, and as thetool_result sent back to the model.
3. Register it
details=True for tools whose raw output is long or uninteresting to read in
the transcript. The model still receives the full result.
4. Use the caller’s identity
Declare a second parameter and the handler receives request context.
One-argument handlers keep working unchanged.
5. Handle failure explicitly
The loop treats a returned string starting withError: as a failed call, which
is what the step indicator and the tool_call log record read.
Complete example
orders.py
When to use a connector instead
Write a custom tool when your code holds the credential, such as a service key that belongs to the deployment. Use a connector when the credential belongs to the end user, such as their own Notion or GitHub account. Connectors handle the grant, refresh, per-tool approvals and the audit trail.Next
Serve an app
A FastAPI service with sign-in and per-user storage.