# Assistant tools

In the middle of a conversation, DoneTalk's AI assistant can look up or change data in your system: an order's status, a customer's account, an e-mail to change. It calls an address of yours, gets a short text back and answers the contact with that fact.

The company builds the tool in **Settings › Tools**: the connection (address and secret), the path, the fields the AI must find out, and whether the tool only reads or changes data. This page is for whoever builds the address that receives the call.

## What arrives

```http
POST /your-path HTTP/1.1
Content-Type: application/json
User-Agent: DoneTalk-Tools/1.0 (+https://donetalk.com/desenvolvedores)
DoneTalk-Signature: t=1792756800,v1=5f0c…
```

```json
{
  "tool": "order_status",
  "contact": { "phone": "+5511999990000", "name": "Camila", "fields": {} },
  "conversation": { "id": "01a3e4f5-…", "test": false },
  "assistant": { "id": "01a0c0de-…", "name": "Amanda" },
  "input": { "number": "77" },
  "test": false,
  "sentAt": "2026-10-24T12:00:00.000Z"
}
```

- `contact.phone` is the conversation's number, set by DoneTalk and covered by the signature. **Use only it to find the account.** The AI never chooses whose account it is; what it sends is in `input`.
- `input` carries the fields the tool declares, already typed (text, number, yes/no, list, date).
- `contact.fields` carries only the contact fields the company ticked on the tool.
- `confirmed` comes with tools that change data and ask first: `false` asks only for a description of the change; `true` makes it.
- `test: true` comes from tests ("Test now" and the assistant's "Test"): change nothing.

## The signature

The same as the webhooks': `t` is the time in seconds and `v1` is the HMAC-SHA256, in hex, of `t + "." + body`, with the connection's secret. Refuse calls older than 5 minutes.

```js
import { createHmac, timingSafeEqual } from "node:crypto";

function verify(header, rawBody, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const age = Math.abs(Date.now() / 1000 - Number(parts.t));
  const expected = createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
  return age < 300 && timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 ?? ""));
}
```

A connection also takes a token (`Authorization: Bearer`), a key in a header of yours, or the Copiloto-format signature (`X-Copiloto-Timestamp` and `X-Copiloto-Signature`), for systems built for its external lookup.

## What to answer

`200` with JSON:

```json
{
  "ok": true,
  "text": "Order 77 left for delivery today at 2 pm.",
  "data": { "status": "shipped" }
}
```

- `text` is the only thing the AI reads: plain language, no markdown, up to 1,500 characters. Say the fact and the contact's next step.
- `ok: false` with `text` also reaches the AI as a fact ("No order found for this phone").
- `data` is optional and only kept in the call history.
- Any other answer (another status, no `text`, over 64 KB, over 8 seconds by default) becomes "unavailable now": the AI goes on without the data.

## Tools that change data

The company chooses, per tool, how to confirm:

| Choice                   | What your system receives                                                                                                                                                                                                                            |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Confirm with the contact | With "the system describes the change first": first `confirmed: false` (answer what would change, without changing it), then `confirmed: true`, with the same data, only after the contact agreed. Without it, only the call with `confirmed: true`. |
| A person approves        | One call with `confirmed: true`, when someone from the team approves.                                                                                                                                                                                |
| No confirmation          | The call as soon as the AI decides.                                                                                                                                                                                                                  |

## Limits

- Up to 5 calls of the same tool per conversation per hour.
- Public `https` addresses only; redirects are not followed.
- A tool with the `GET` method sends the call in the address's `call` parameter instead of a body; the signature covers that parameter's value.

## Any API

If your system already has an API, a tool can call it without this format: the company builds the path, headers and body with `{{contact.phone}}`, `{{contact.name}}`, `{{input.field}}` and `{{conversation.id}}`, and chooses what the AI reads: the whole answer, one field (`data.status`) or a sentence built from it.
