Tools

Reusable HTTP actions an assistant can call mid-conversation — and how to drive them from the prompt.

A tool is an HTTP action the assistant can call while talking to a user — for example “look up an order”, “create a ticket”, or “check availability”. Tools are defined once — at the organization level or at the partner level — and attached to the workspaces that should be able to use them.

Anatomy of a tool

GET /v1/tools/{toolId} returns a tool definition:

FieldWhat it is
nameThe tool’s identifier the model sees. 1–64 characters, letters/digits/underscores/hyphens, no spaces.
descriptionNatural-language explanation of what the tool does and when to use it. This is what the model reads to decide whether to call it.
method, urlThe HTTP request the tool makes (GET, POST, PUT, PATCH, DELETE).
headersHeader names and values, JSON-Schema-shaped. Every header value is masked in responses (the names are shown).
requestSchemaJSON Schema of the request payload — the parameters the model fills in from the conversation.
responseSchemaJSON Schema of the fields to extract from the tool’s HTTP response.
aliasesNamed bindings that map extracted response fields to variables you can reference.

Header values are never returned in full by default — every value is masked (••••••), whether or not it is actually a secret. (Headers appear only on the tool detail, GET /v1/tools/{toolId}, not in the tool list.) Reveal specific values on a single read with GET /v1/tools/{toolId}?unmask=Header-Name.

Two ownership scopes

Every tool is owned by exactly one of two scopes, and the scope decides who can use it:

ScopeCreated withUsable by
OrganizationPOST /v1/organizations/{orgId}/tools (with X-Account-Id)Workspaces of that organization only.
PartnerPOST /v1/tools (API key only, no X-Account-Id)Any workspace under your key — directly, or via prompt templates.

Use an org tool for something specific to one customer (their ticketing system, their credentials); use a partner tool for an action you want to reuse across customers.

On the item routes (GET/PATCH/DELETE /v1/tools/{toolId}), the X-Account-Id header selects the scope: with the header the id is resolved as an org tool under that account, without it as a partner tool — an org tool’s id without the header will not resolve (404). Tool names are unique within their scope (per organization, per partner).

Attaching a tool to a workspace

A workspace opts in to a tool by attaching it:

PUT /v1/workspaces/{workspaceId}/tools/{toolId} # attach (idempotent)
DELETE /v1/workspaces/{workspaceId}/tools/{toolId} # detach
GET /v1/workspaces/{workspaceId}/tools # list directly attached tools

An org tool must belong to the workspace’s own organization; a partner tool must be owned by your company. Only attached tools are exposed to that workspace’s assistant.

The effective tool set

Attachments are not the only way a workspace gets tools: a prompt template pinned to the workspace brings its own partner tools along. What the assistant actually sees is the union of both:

GET /v1/workspaces/{workspaceId}/tools/effective # per channel: chat + voice
GET /v1/workspaces/{workspaceId}/tools/effective?mode=chat

The response lists each channel’s runtime tools with their source (direct or template) and scope (organization or partner). When two tools collide on a name, only one is offered to the model: a directly attached org tool wins over a directly attached partner tool, which wins over a template-provided tool — the losers are reported as shadowed with the overriddenBy winner. The plain GET .../tools list stays direct attachments only.

A tool that is referenced by a published template version (or by an archived version still pinned to a workspace) cannot be renamed or deleted — those requests return 409. Its url, headers, schemas, and aliases stay editable, so rotating a credential never requires republishing a template.

Calling a tool from the prompt

You do not invoke a tool with special syntax. Every tool attached to a workspace is offered to the assistant by its name and description, and the model decides on its own when to call one, filling the requestSchema parameters from what the caller said (this is standard function-calling).

Your prompt’s job is to guide that decision. Refer to the tool by its name and say when to use it:

You are a support assistant.
When the caller asks about the status of an order, call the lookup_order
tool with their order number. Do not guess an order status — always use
the tool.

Two things make tools reliable:

  1. A precise description on the tool itself — the model leans on it heavily to decide whether the tool applies.
  2. Clear instructions in the prompt naming the tool and the situations that should trigger it.

Using a tool’s response in the prompt

To feed a tool’s result back into the conversation, extract fields from its HTTP response and expose them as variables:

  1. responseSchema — declare which fields to pull out of the tool’s JSON response.
  2. aliases — give each extracted field a variable name. An alias maps a name to a Liquid expression pointing at the response, e.g. the alias orderStatus{{ data.status }}.
  3. Reference the alias anywhere in your prompt or the assistant’s messages as a Liquid variable: {{ orderStatus }}.

For example, with an alias orderStatus bound to the response field data.status:

The caller's order status is {{ orderStatus }}. Tell them clearly and
ask if there is anything else you can help with.

At runtime the assistant calls the tool, extracts the fields defined by responseSchema, binds them to your alias names, and substitutes {{ orderStatus }} with the live value.

Alias values are Liquid expressions over the tool’s response (e.g. {{ data.user.id }}). The alias name (left side) is what you reference in the prompt; the expression (right side) is where the value comes from in the response.

Tools and voice

Tools are how a voice assistant takes real actions during a call. Attach the tools a workspace’s voice assistant should be able to use, then guide their use from the voice prompt exactly as above.