VoiceLayer
Dashboard

Build / Tools

Connecting your systems

A tool is an HTTP endpoint your agent can call mid-conversation — look up an account, create a ticket, check availability. This is how an agent stops guessing and starts knowing.

Two ways to call an API

A registered tool recommended

Define it once under Tools, then pick it by name from any flow. The URL, headers and credentials live on the server — the flow only refers to the name. Change the endpoint in one place and every agent follows.

Inline on a step

Configure the URL directly on a Call an API step. Quick for a one-off or while you’re trying something out, but the config lives in that one flow.

Defining a tool

Tools → New HTTP tool. The fields:

fields
Name          lookup_order          # snake_case identifier the agent refers to
Method        GET
URL template  https://api.example.com/orders/{{ order_id }}
Allowed hosts api.example.com       # this tool may only ever reach these hosts
Headers       { "authorization": "Bearer {{ api_token }}" }
Inputs        [{ "name": "order_id", "type": "string", "required": true }]
Body template { "id": "{{ order_id }}" }     # POST/PUT/PATCH only
Timeout       8000

Inputs are what the tool needs to run. They fill automatically from variables of the same name — capture order_id with an Ask step and a tool that declares an order_id input gets it without any wiring.

🔒

Allowed hosts are required, deliberately. A tool may only ever reach the hosts you list, checked again after the URL is built — so a variable can’t be used to redirect a call somewhere else. Calls are made from the server, so your credentials never reach the agent or the caller.

Using the result

A Call an API step has two exits — Success and Failure. Wire both: an API that’s down should say something human, not leave dead air. Pull fields out of the response with Save outputs to variables, one name = path per line.

response → variables
{
  "ok": true,
  "customer": { "name": "Jane Doe", "plan": "pro" },
  "eta": "Thursday"
}

Save outputs to variables:
  customer_name = customer.name
  eta           = eta

Later steps then use {{ customer_name }} directly. Design your endpoint to return a small, flat object — the agent needs a handful of speakable values, not your full domain model.

Authentication

Put the credential in a header on the tool. For anything long-lived, store it under Connections and reference it — secrets stay in the vault rather than sitting in a flow that people can read. Never put a key in the URL: URLs end up in logs.

Writing an endpoint an agent can use

  • Answer fast. The caller is waiting in silence. Aim for under a second; the timeout exists for the bad day, not the normal one.
  • Return speakable values. "arriving Thursday" is better than a raw timestamp — whatever you return may be read out loud.
  • Fail honestly. A clear non-2xx routes to the Failure port. A 200 containing an error message looks like success and the agent will cheerfully tell the caller it worked.
  • Be idempotent where it matters. A create call can be retried; make sure that doesn’t open two tickets.

By API

register a tool
curl -X POST https://api.vlayers.ai/v1/tools/http \
  -H 'authorization: Bearer vl_...' \
  -H 'content-type: application/json' \
  -d '{
    "name": "lookup_order",
    "description": "Look up an order by its id",
    "method": "GET",
    "urlTemplate": "https://api.example.com/orders/{{ order_id }}",
    "allowedHosts": ["api.example.com"],
    "inputs": [{ "name": "order_id", "type": "string", "required": true }],
    "timeoutMs": 8000
  }'
🧪

Tools run in a dry run exactly as they do on a call, so you can prove an integration works over text before dialling anything. The call detail shows each tool invocation and what it saved.