What a tool is
A tool is an endpoint the LLM can call during a call. You register it on the character; the agent worker proxies calls to your URL when the LLM decides it’s needed. Examples:- Look up an order status by ID
- Check inventory before quoting a price
- Create a support ticket
- Fetch the user’s last invoice
Registering an HTTP tool
| Field | Purpose |
|---|---|
name | Tool name the LLM calls. Use snake_case. |
kind | "http" for REST endpoints. |
description | When the LLM should call it. Write this for the LLM, not for humans — be explicit about triggers. |
input_schema | JSON Schema for the arguments the LLM passes. |
config.url | Absolute URL of your endpoint. |
config.method | HTTP method, default POST. |
config.headers | Static headers (auth tokens, secrets) sent on every call. |
Your endpoint contract
The worker sends the LLM’s arguments as the JSON request body. Your endpoint returns JSON; the body is fed back to the LLM as the tool result.| Behaviour | What the agent does |
|---|---|
2xx with JSON body | Reads the JSON; LLM uses it in its next utterance |
Non-2xx | LLM is told the call failed; can retry or apologise |
| Timeout (>10s) | LLM is told the call timed out |
Multiple tools on one character
description fields.
Passing session context to your endpoint
The worker adds the session’smetadata and session_id into the request body by default, so your endpoint can act on behalf of the right user:
_session.metadata.user_id server-side to enforce that the looked-up ticket belongs to that user.
Securing your endpoint
| Risk | Mitigation |
|---|---|
| Anyone who knows the URL can call it | Require X-Oshara-Secret (set in config.headers); reject mismatches |
| Replay / IP spoofing | Limit to Oshara’s outbound IPs (contact support for the list) |
| Sensitive data leak | Don’t return fields the agent shouldn’t say out loud — strip from the response |
| Long-running calls | Return fast (<3s ideal) — if the work is slow, return a job ID and have the agent follow up |
Writing a good description
The LLM picks tools based on description. Write triggers, not features:
| Bad | Good |
|---|---|
"Returns ticket info" | "Look up a support ticket by its ID. Use when the user mentions a ticket number like TICKET-XXX or asks 'what's happening with my ticket'." |
"Creates a lead" | "Create a new sales lead. Use when the user expresses interest in pricing, demos, or scheduling a call — but only after collecting at least their name and email." |
Testing a tool
Client-event tools (no HTTP, just data channel)
Some tools don’t need to call your backend — they should fire a message to the browser instead (open a modal, navigate, scroll to an element). Usekind: "client_event":
