Tools
Tools extend what an agent can do during a conversation.
Tools
Tools extend what an agent can do during a conversation.
Two Types Of Tools
The Tools page can show:
- built-in tools provided by the platform
- custom tools that you create and manage yourself
You can enable or disable tools per agent, and custom tools can be edited later.
When To Use A Tool
Use a tool when the agent needs to perform an action or fetch live data that should not live in static sources.
Examples:
- check an order status
- look up account data
- fetch structured product availability
- call an internal HTTP service
Tools vs Skills vs MCP Servers
| Use | Choose this |
|---|---|
| The agent needs reusable instructions or behavior guidance | Skills |
| The agent needs one focused action or HTTP call | Tools |
| The agent needs a larger external integration with multiple exposed tools | MCP Servers |
Working With Custom Tools
The custom tool flow lets you:
- create a tool
- configure its HTTP behavior
- test it
- enable or disable it for an agent
Good Custom Tool Workflow
- define one clear job for the tool
- configure the request method, URL, headers, and body shape
- test the tool with realistic inputs
- attach it to the right agent only
- monitor real usage in conversations before expanding scope
If the tool fails often, reduce the scope of what it tries to do instead of piling more fallback logic into the prompt.
Runtime Data Visibility
Widget and public Chat API callers use the same three runtime field names:
| Field | Model | Model provider | Configured Kravos tools | Durable runtime-input storage |
|---|---|---|---|---|
context | Yes | Yes | Not automatically | No |
toolContext | No | No | Explicit selected bindings | No |
toolCredentials | Never | Never | Explicit selected auth slots | Never |
Do not put secrets in context; it is model-visible and provider-visible during widget voice. toolContext is for
hidden non-secret values selected by stored bindings. toolCredentials is for short-lived values selected by stored
authentication slots. Neither hidden field is a model argument or an authorization shortcut.
HTTP Configuration (Canonical Fields)
A custom tool calls one HTTP endpoint. The canonical httpConfig contract has exactly these fields:
| Field | Type | Meaning |
|---|---|---|
method | string | GET, POST, PUT, PATCH, or DELETE (default GET) |
url | string | Endpoint URL. Supports ${param} interpolation from the tool input |
headers | object | Static request headers, for example { "Accept": "application/json" } |
authType | string | none, bearer, api_key, or widget-session (default none). basic is dashboard-only |
authConfig | object | Auth settings. secretRef for secret values, headerName for api_key |
toolContextBindings | array | Optional explicit bindings from widget toolContext to request headers/body |
timeout | number | Timeout in milliseconds, 500-30000 (default 10000) |
body | object | Optional { mode: "none" | "json" | "raw"; jsonLiteral?: string; rawTemplate?: string; contentType?: string } |
responseMapping | object | Optional { fields: ["status", "id"] } to return only top-level JSON fields |
Guessed keys are rejected, not ignored
requestHeaders, authentication, endpointUrl, and httpMethod are not canonical. MCP create_custom_tool,
update_custom_tool, and test_custom_tool reject them with a field error naming the exact path (for example
httpConfig.authentication) so a misconfigured tool can never silently lose its auth and reach the endpoint as an
unauthenticated request. Use headers, authType + authConfig, url, and method instead.
bearer and api_key require authConfig.secretRef; omitting it fails with a httpConfig.authConfig.secretRef
field error instead of sending an unauthenticated request. authType: "none" must not include a secretRef. Static
headers may not carry secrets: Authorization, Proxy-Authorization, x-api-key, Cookie (any casing), or any name
containing auth, token, api-key, secret, signature, credential, or password are rejected with
a httpConfig.headers.<name> field error. basic auth is not available over MCP — it stays dashboard-only with
raw username/password values.
Path And Query Interpolation
Placeholders ${param} in the URL are replaced with values from the tool input:
{
"url": "https://api.example.com/orders/${order_id}"
}
With input { "order_id": "A-1001" } the tool calls https://api.example.com/orders/A-1001. The value is URL-encoded. Missing input parameters fail the call with a clear error.
Request Body
Use httpConfig.body to choose a Body mode:
- None (
mode: "none"): never send a body or add a defaultContent-Type. - JSON (
mode: "json"): send the full tool input parameter object as JSON, withContent-Type: application/jsonunless aContent-Typerequest header is set.jsonLiteralis persisted authoring data only; it is never sent as the request body. - Raw (
mode: "raw"): sendrawTemplatewith${name}slots replaced from top-level tool input. Objects and arrays become JSON; other values become strings. Over MCP, Raw requires a non-emptyrawTemplate.
Unresolved Raw slots fail the call before the request is sent with Missing raw body parameters: <names>.
When a Raw body is sent, Content-Type uses the last case-insensitive content-type request header, then body.contentType (trimmed), then text/plain if it is missing or blank.
Omitting body preserves legacy behavior: non-GET methods (POST, PUT, PATCH, DELETE) send the full tool input object as JSON with the same Content-Type default as JSON mode. Existing tools need no migration. GET never sends a body, regardless of mode.
Widget Tool-Context Bindings
toolContext is not added to the model prompt or to model-generated tool arguments. A custom HTTP tool must explicitly
bind each value it needs. Bindings can add a scalar value to a request header or set a value at a JSON body path:
{
"toolContextBindings": [
{
"source": "toolContext",
"path": "accountId",
"target": { "type": "header", "name": "x-account-id" }
},
{
"source": "toolContext",
"path": "locale",
"target": { "type": "body", "path": "request.locale" }
}
]
}
Only explicitly bound values are sent. Header names that look like authentication or secret-bearing headers are rejected. Bound values are redacted if the endpoint echoes them in tool output.
Body bindings are applied before JSON serialization or Raw slot interpolation. In Raw mode, a bound top-level value is sent only when the template references its slot. None mode and GET never send a body, including bound body values.
For browser-held credentials, configure a dashboard-managed custom tool with authType: "widget-session" and a
credential slot. The slot value is sent only in the configured auth header and is never included in model arguments,
conversation data, or tool output:
{
"authType": "widget-session",
"authConfig": { "slot": "billing" }
}
Use setToolCredentials({ billing: 'browser-token' }) to provide the slot from the SDK. With no headerName, the
credential is sent as Authorization: Bearer <value>; set headerName only when the endpoint requires a custom header.
Missing slots fail the tool call without sending an unauthenticated request. Credentials stay in widget memory only;
they are not model input, conversation data, or persisted tool configuration. Rotate the value through the setter when
your host refreshes it.
Custom HTTP Tools In Widget Voice
Native voice delegates to the agent's configured backend tools with normal authorization, argument validation and
outbound safety. The ElevenLabs browser-mediated relay is retired; it no longer accepts discovery or execution calls.
Native speech does not receive hidden toolContext, toolCredentials or authentication headers through that relay.
Existing text/dashboard HTTP execution remains available, including widget-session bindings and server-managed auth.
A missing required session slot returns SESSION_CREDENTIAL_REQUIRED before outbound HTTP. Do not copy credentials
into model context or prompts to work around a missing binding. An accepted external effect cannot be undone by ending voice.
Authentication
No Auth
Omit authConfig and set authType: "none" (the default):
{
"url": "https://api.example.com/public/orders/${order_id}",
"method": "GET",
"authType": "none"
}
Bearer Token From An Environment Secret Reference
The MCP tools never accept raw bearer tokens, API keys, or passwords in httpConfig.authConfig. Instead, reference a secret that lives in the runtime environment. bearer (and api_key) auth requires authConfig.secretRef — a config that declares bearer without one is rejected with a httpConfig.authConfig.secretRef field error instead of silently going out unauthenticated:
{
"url": "https://api.example.com/orders/${order_id}",
"method": "GET",
"authType": "bearer",
"authConfig": {
"secretRef": {
"type": "environment",
"name": "KRAVOS_CUSTOM_TOOL_<TENANT_ID>_TASKS_BEARER"
}
}
}
At execution time the runtime resolves the environment variable and sends Authorization: Bearer <value>. The resolved secret is never returned by any API or MCP tool, and it is never stored in the tool configuration — only the reference is.
API Key From An Environment Secret Reference
For api_key auth, the resolved secret is sent in the header named by authConfig.headerName (default x-api-key):
{
"url": "https://api.example.com/orders",
"method": "GET",
"authType": "api_key",
"authConfig": {
"headerName": "x-api-key",
"secretRef": {
"type": "environment",
"name": "KRAVOS_CUSTOM_TOOL_<TENANT_ID>_TASKS_API_KEY"
}
}
}
Secret Setup And Naming
External secret provisioning is required
Copilot and Platform MCP store only the environment-variable reference. They do not create or write the secret value. An operator must provision the referenced variable on every agent runtime that can execute the tool.
Copilot secure forms are not an environment-secret provisioning service. They are offered only for supported MCP
credential storage and MCP OAuth. A custom HTTP tool remains reference-only: creating its secretRef does not create,
replace, or distribute the referenced environment variable.
-
Set an environment variable on the runtime that executes the agent. The name must follow the tenant-scoped convention:
KRAVOS_CUSTOM_TOOL_<TENANT_ID>_<NAME>For example
KRAVOS_CUSTOM_TOOL_tenant_1_TASKS_BEARER. -
Reference the exact same name in
authConfig.secretRef.name.
The KRAVOS_CUSTOM_TOOL_ prefix is dedicated to custom tool secrets. The reference is validated against the tenant at write time and again at execution time, so one tenant can never reference another tenant's custom-tool secret. If the variable is missing, empty, or not scoped to the runtime tenant, the tool call fails safely without leaking anything.
authType: "none" must not include a secretRef — that combination is rejected as misleading. basic auth is not available over MCP and remains dashboard-only with raw username/password values.
Static Headers
Non-secret headers are static keys in headers. Do not put secret values in headers; use authConfig.secretRef instead. Authorization, Proxy-Authorization, x-api-key, Cookie (any casing), and any header name containing auth, token, api-key, secret, signature, credential, or password are rejected as static headers with a httpConfig.headers.<name> field error so secrets cannot bypass the secretRef rule.
Testing Custom Tools
test_custom_tool runs a real request against the endpoint. Provide exactly one of:
toolId— tests the stored configuration of an existing toolhttpConfig— tests an ad-hoc configuration before you create the tool
Pass the tool input in the input object. The response is the HTTP result (status, mapped data, truncation flag); auth configuration is never echoed back. Passing neither (or both) toolId and httpConfig is a validation error.
MCP Automation
Custom tools are fully manageable over Platform MCP:
create_custom_tool— create and link a tool to an agentupdate_custom_tool— update the tool or its HTTP configtest_custom_tool— test a stored or ad-hoc configlist_custom_tools/get_custom_tool— read sanitized metadata (never raw auth values)
Validation failures return structured field errors such as httpConfig.url or httpConfig.authConfig.secretRef.name with the expected constraint, so autonomous clients can correct one field at a time.
Copilot protected inputs
Some Copilot operations require information that must not enter the model conversation. When the file-enabled cohort is available, Copilot opens a dedicated secure handoff for:
- source files and images
- batch source files
- bulk ZIP uploads
- credentials and other private configuration values
Choose files or enter private values only in that handoff. Files are uploaded directly to protected storage, and the transcript receives only safe metadata and opaque artifact references. Signed upload URLs, file bytes, credentials, and protected JSON are not model inputs, tool results, receipts, or log data.
Submitting a secure handoff does not execute a confirmed write. Review and confirm the action in the normal Copilot confirmation step. If an upload is still being inspected, wait for the secure status to become ready; do not paste a storage URL into the conversation or retry the operation manually.
Protected outputs, such as generated credentials or upload capabilities, are shown only in the owner-scoped secure browser flow and may be revealed once. Copy them from that flow when needed; they are not recoverable from the transcript.
Best Practices
- keep tool behavior narrow and reliable
- use sources for stable reference knowledge, not live actions
- test tools before enabling them broadly
- monitor tool-heavy voice sessions in Voice Lab if voice is enabled
Related Docs
Skills
Use reusable instructions when the agent needs behavior guidance, not live actions.
MCP Servers
Connect GitHub, Slack, Notion, databases, and external systems.
API Keys
Create and manage keys for chat, retrieve, and ingest use cases.
API Reference
Interactive endpoint docs for chat, retrieval, and source management.


