# Demo Tools

Before you wire a tool up to a real service, it helps to watch one work from end to end. A "tool" lets an AI receptionist reach out to an outside system through an API (Application Programming Interface, the doorway one program uses to talk to another) while it is still on the call. Cloud Voice ships with three sample tools you can drop into your system in a couple of clicks. Each one reads from or posts to a free public mock API, so you can see the receptionist call an external endpoint mid-call without going near any of your own data.

:::caution
These samples are for evaluation only. They talk to a public mock service ([jsonplaceholder.typicode.com](https://jsonplaceholder.typicode.com/)), which hands back canned responses and stores nothing. Keep them out of production.
:::

:::note
There are two ways to load a sample into your system:

- Copy its JSON below and paste it into the JSON editor while building a tool by hand, see [Add a Tool Manually](/pbx/ai-guide/add-a-tool-manually/).
- Save its JSON to a `.json` file and import the file directly, see [Add a Tool via File Upload](/pbx/ai-guide/add-a-tool-via-file-upload/).

JSON (JavaScript Object Notation) is just a plain-text format for structured data. You can copy the blocks below straight out of this page.
:::

:::note[How to read each configuration]
Every sample shares the same building blocks, so it is worth learning them once:

- **`method`** is the HTTP verb the tool uses. `GET` reads data (Tools 1 and 2); `POST` creates or submits data (Tool 3).
- **Parameters** are the pieces of information sent with the request, grouped by where they go: `path_params` slot into the URL itself (the `{order_id}` placeholder), `query_params` are added to the end of the URL (for example `?userId=1`), and `body_params` travel inside the request body.
- **`value_logic`** decides where each value comes from. `"llm"` means the AI model (LLM, Large Language Model) pulls the value out of what the caller says on the call. `"constant"` means the value is fixed and never changes.
- **`response_settings`** are pre-tuned for you (for example `response_timeout` is set to 20 seconds, so the tool waits that long for the mock API to answer before giving up). Leave them as they are for testing.
:::

## Tool 1: Query order

Looks up a single order by its ID (identifier). Reach for this one when a caller wants the status of one specific order.

- **What triggers it:** a caller asks something like "Can you check the status of order 5?"
- **How it works:** a `GET` request that drops the order number into the URL path where `{order_id}` sits. The AI reads the number ("order 5") straight from the conversation.
- **How to add it:** copy the configuration below.

```json
{
    "basic": {
        "name": "query_order",
        "description": "Use this tool when customer asks to 'query order', 'check order status', or 'get order details'. Extract the numeric order_id from conversation (e.g., 'order 3' → order_id=3).",
        "method": "GET",
        "url": "https://jsonplaceholder.typicode.com/posts/{order_id}",
        "remark": "Demo - Query order by ID"
    },
    "response_settings": {
        "disable_interruptions": false,
        "force_pre_tool_speech": true,
        "execution_mode": "immediate",
        "tool_call_sound": "Typing",
        "sound_behavior": "always_play",
        "response_timeout": 20
    },
    "path_params": [
        {
            "parameter": "order_id",
            "data_type": "Integer",
            "value_logic": "llm",
            "description": "Extract order ID from customer request, e.g., 'order 3' → 3"
        }
    ],
    "headers": [
        {
            "parameter": "Accept",
            "value": "application/json"
        }
    ],
    "query_params": [],
    "body_description": "",
    "body_params": []
}
```

## Tool 2: Get orders by user

Returns every order tied to one account. Use it when a caller wants to see all of their orders at once.

- **What triggers it:** a caller asks something like "Show me all my recent orders. My account ID is 1."
- **How it works:** a `GET` request that sends the account number as a query parameter (`userId`) on the end of the URL. The AI extracts that number from the call.
- **How to add it:** copy the configuration below.

```json
{
    "basic": {
        "name": "get_orders_by_user",
        "description": "Use this tool when customer asks to 'list my orders', 'show my posts', or 'what are my recent requests'. Extract userId from conversation.",
        "method": "GET",
        "url": "https://jsonplaceholder.typicode.com/posts",
        "remark": "Demo - Query orders by user ID"
    },
    "response_settings": {
        "disable_interruptions": false,
        "force_pre_tool_speech": true,
        "execution_mode": "immediate",
        "tool_call_sound": "Typing",
        "sound_behavior": "always_play",
        "response_timeout": 20
    },
    "path_params": [],
     "headers": [
        {
            "parameter": "Accept",
            "value": "application/json"
        }
    ],
    "query_params": [
        {
            "parameter": "userId",
            "required": true,
            "data_type": "Integer",
            "value_logic": "llm",
            "description": "Extract user ID from conversation, e.g., 'my user ID is 1' → 1"
        }
    ],
    "body_description": "",
    "body_params": []
}
```

## Tool 3: Create order

Files a new record from details gathered on the call. Use it when a caller wants to report a problem or open a support ticket.

- **What triggers it:** a caller says something like "I need to report an issue. My package arrived damaged and I'd like a refund."
- **How it works:** a `POST` request that sends three body parameters. The AI writes the `title` (a short summary, kept under 10 words) and `body` (the full description) from what the caller says, while `userId` is a fixed value of `1`.
- **How to add it:** copy the configuration below.

:::tip
In this sample the `userId` is hard-coded to `1` because the mock API has no real accounts. When you adapt this pattern for a real service, switch that parameter's `value_logic` to `"llm"` (or map it to the caller) so each ticket is filed under the right account instead of always account 1.
:::

```json
{
    "basic": {
        "name": "create_order",
        "description": "Use this tool when customer wants to create a ticket, submit a request, or report an issue. Extract the title (short summary) and body (detailed description) from the conversation.",
        "method": "POST",
        "url": "https://jsonplaceholder.typicode.com/posts",
        "remark": "Demo - Create an order/ticket"
    },
    "response_settings": {
        "disable_interruptions": false,
        "force_pre_tool_speech": false,
        "execution_mode": "immediate",
        "tool_call_sound": "Typing",
        "sound_behavior": "always_play",
        "response_timeout": 20
    },
    "path_params": [],
    "headers": [
        {
            "parameter": "Content-Type",
            "value": "application/json"
        }
    ],
    "query_params": [],
    "body_description": "Extract request information from customer conversation.",
    "body_params": [
        {
            "parameter": "title",
            "required": true,
            "data_type": "String",
            "value_logic": "llm",
            "description": "Extract a short title/summary of the issue from conversation. Keep it under 10 words.",
            "optional_values": []
        },
        {
            "parameter": "body",
            "required": true,
            "data_type": "String",
            "value_logic": "llm",
            "description": "Extract the full description of the issue from conversation, including all details mentioned by customer.",
            "optional_values": []
        },
        {
            "parameter": "userId",
            "required": true,
            "data_type": "Integer",
            "value_logic": "constant",
            "constant_value": "1"
        }
    ]
}
```
