Tools

The HTTP calls an agent can make while it is on a call.

A tool is a URL, a method, and parameters the model fills in. The agent decides when to call it from the description alone, so the description is the most important field here: it is the only part the model reads.

Tools are described in ordinary terms (a request with parameters that go in the path, the query, a header or the body) rather than in the voice stack's own schema, so which stack executes them is not something an integration has to know or track.

Attaching a tool to an agent is done on the agent, not here: see PUT /api/v1/agents/{agentId}/tools.

Credentials go in secretHeaders, a map of header name to value (up to 10; names up to 64 characters, values up to 4,096). They are write-only: stored encrypted, sent as headers on every request the tool makes, and never returned. A tool answers with their names only, as request.secretHeaders: [{ name, configured: true }]. They are not sent on to another origin if your endpoint redirects. To run the tool, the voice stack executing the call is given them too.

Parameters with in: "header" are sent as HTTP headers, including on GET, so their names must be valid header names and not ones the request sets itself (Host, Content-Type, Content-Length and the like); a tool that breaks this is refused when it is saved.

Secret headers belong to the host they were set for: an update that moves url to another origin (scheme, host or port) drops every stored secret header except those sent again in the same request. If stored secret headers can no longer be read, an update that would keep them answers CONFLICT; send all of them again to replace them.

An API that issues OAuth 2.0 access tokens goes in oauth2 instead: the token URL, client ID and client secret of a client credentials grant, plus an optional scope and audience. A token is fetched before the tool's first request, sent as Authorization: Bearer, and replaced shortly before it expires or when your API answers 401, so nothing has to be rotated by hand. clientAuthMethod says how the client proves itself to the token endpoint: client_secret_basic (the default, an HTTP Basic header) or client_secret_post (in the form body). The client secret is write-only; a tool answers with request.oauth2, which shows clientSecretConfigured: true in its place. A tool that uses oauth2 cannot also set Authorization in secretHeaders or as a parameter.

On an update, oauth2 replaces the settings and null removes them. clientSecret may be left out to keep the saved one, but only while tokenUrl, clientId and the tool's origin stay the same; otherwise send it again in the same request. Turning OAuth on for a tool always needs clientSecret. If a tool's saved OAuth settings can no longer be read, it answers request.oauth2: null and an update that would keep them answers CONFLICT; send oauth2 again with clientSecret to replace them.

List tools#

Tools the key can reach: created by this user, or shared to them.

GET/api/v1/tools

Responses

The tools.

curl -X GET "https://voice.evryhealth.com/api/v1/tools" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"tools": [
{
"id": "tool_9a1c…",
"name": "checkEligibility",
"description": "Look up whether a member's plan is active on a given date.",
"request": {
"url": "https://api.example.com/eligibility/{memberId}",
"method": "GET",
"parameters": [
{
"name": "memberId",
"in": "path",
"schema": {
"type": "string"
},
"required": true
}
],
"secretHeaders": [
{
"name": "Authorization",
"configured": true
}
],
"oauth2": null
},
"usageCount": 1284
}
]
},
"meta": {
"requestId": "req_…"
}
}

Create a tool#

The name is what the model calls: 1-64 characters, letters, digits, underscores and hyphens. Write the description for the model, not for a person reading documentation. A name already in use is refused with a 409.

POST/api/v1/tools

Body

application/json
name
string
required
description
string
required
url
string
required
method
GET | POST | PUT | PATCH | DELETE
required
parameters
{ name, in, schema, required, description }[]
category
string
tags
string[]
isOrgShared
boolean
secretHeaders
Record<string, string> (write-only)
oauth2
{ grantType?: "client_credentials", tokenUrl, clientId, clientSecret (write-only), scope?, audience?, clientAuthMethod?: "client_secret_basic" | "client_secret_post" }

Responses

The created tool.

curl -X POST "https://voice.evryhealth.com/api/v1/tools" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "checkEligibility",
"description": "Look up whether a member's plan is active on a given date. Call this before discussing coverage.",
"url": "https://api.example.com/eligibility/{memberId}",
"method": "GET",
"parameters": [
{
"name": "memberId",
"in": "path",
"schema": {
"type": "string"
},
"required": true
},
{
"name": "asOf",
"in": "query",
"schema": {
"type": "string"
},
"required": false
}
],
"secretHeaders": {
"Authorization": "Bearer sk_live_…"
}
}'
Response201
{
"data": {
"id": "tool_9a1c…",
"name": "checkEligibility"
},
"meta": {
"requestId": "req_…"
}
}

Get a tool#

One tool and the request it makes.

GET/api/v1/tools/{toolId}

Path parameters

toolIdstringrequired
Tool id.

Responses

The tool.

curl -X GET "https://voice.evryhealth.com/api/v1/tools/{toolId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"id": "tool_9a1c…",
"name": "checkEligibility"
},
"meta": {
"requestId": "req_…"
}
}

Update a tool#

Naming any part of the request rewrites the whole definition, from the current values where you did not say otherwise. The definition is one blob underneath, and a partial write would lose whatever the other writer set.

PATCH/api/v1/tools/{toolId}

Path parameters

toolIdstringrequired
Tool id.

Body

application/json
description
string
url
string
method
string
parameters
{ name, in, schema, required }[]
category
string
tags
string[]
isOrgShared
boolean
secretHeaders
Record<string, string | null> (null removes one; others are kept)
oauth2
{ tokenUrl, clientId, clientSecret?, scope?, audience?, clientAuthMethod? } | null (null removes; clientSecret left out keeps the saved one)

Responses

The updated tool.

curl -X PATCH "https://voice.evryhealth.com/api/v1/tools/{toolId}" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/v2/eligibility/{memberId}"
}'
Response200
{
"data": {
"id": "tool_9a1c…"
},
"meta": {
"requestId": "req_…"
}
}

Delete a tool#

Removes the tool and takes it off every agent using it. An agent whose prompt still describes a tool that no longer answers is worse than one that lost it. Only the tool's creator may delete it; anyone else gets a 403.

DELETE/api/v1/tools/{toolId}

Path parameters

toolIdstringrequired
Tool id.

Responses

Deleted.

curl -X DELETE "https://voice.evryhealth.com/api/v1/tools/{toolId}" \
-H "Authorization: Bearer YOUR_API_KEY"
Response200
{
"data": {
"deleted": true
},
"meta": {
"requestId": "req_…"
}
}