Tools
Tools let the agent act: hand a conversation to your team, open a ticket, look something up in your systems. There are three kinds:
| Kind | Runs where | Defined in |
|---|---|---|
| Built-in | Inside K-Agent | Always available; switch each one on or off in tools.builtin |
HTTP tool (tool_…) |
K-Agent calls your HTTPS endpoint | POST /v1/tools, then granted to agents in tools.http |
| Client tool | Your app runs it and sends back the result | The agent’s tools.client |
tools.enabled is the master switch: turning it off removes every tool but keeps your grants and rules for later.
Built-in tools
Section titled “Built-in tools”| Tool | Effect | Default | What it does |
|---|---|---|---|
transfer_to_human |
escalation | on | Hands the conversation to your team. Parameters: reason_type (customer_requested · out_of_scope · complaint · liability · technical) and summary (the topic, not an accusation). Returns a truthful status. |
create_ticket |
action | off | Opens ticket TKT-<n> with title, description, priority (low · normal · high · urgent) and resolution_attempted. Refuses when the customer already has an open ticket from the agent, and gives the model the existing number instead. |
flag_conversation |
escalation | off | Marks the session flagged with a reason and an urgency (low · normal · high) so your team reviews it. Sessions only. |
search_knowledge |
read | on | Searches the agent’s searchable knowledge with an Arabic-aware query. Offered only when the agent has searchable sources. |
The tool descriptions carry rules measured in production: announcing an action is not doing it, ask at most one clarifying question (none for angry customers or damage claims), and record the topic rather than the accusation.
Your rules for each tool
Section titled “Your rules for each tool”Every tool grant has a rules field (up to 4,000 characters). It is added to the tool’s description under “This company’s rules for this action”, so you can say when to use it in your own words:
{ "tools": { "builtin": { "transfer_to_human": { "enabled": true, "rules": "Hand over any question about wholesale or corporate gift orders. During Ramadan, hand over requests for same-day delivery." }, "create_ticket": { "enabled": true, "rules": "Open a ticket only for delivery complaints after the customer has described the problem." } } }}The dashboard offers starter rules for each tool, with the reasoning behind them.
Effects and when tools are available
Section titled “Effects and when tools are available”Every tool has an effect:
| Effect | Tools | Gated? |
|---|---|---|
read |
search_knowledge, HTTP tools that only look things up |
HTTP read tools follow their requires_verified_user flag. |
escalation |
transfer_to_human, flag_conversation |
Never. They work in one-shot calls, for anonymous users and in the playground, so the liability reply works everywhere. |
action |
create_ticket, HTTP tools that change something, client tools (by default) |
Removed when the call is one-shot without allow_actions: true, when the end user isn’t verified and tools.allow_anonymous_actions is off, or when the agent’s actions_paused is on. |
The tool list is decided when a segment starts and stays fixed, sorted by name, until the next one. This keeps prompt caching effective. Inside a segment, a tool that can’t succeed right now is refused with guidance rather than removed.
The policy check
Section titled “The policy check”Before any tool executes, K-Agent checks all of the following. If one fails, the model gets {"ok": false, "error": {"code": …, "guidance": …}} and nothing runs:
- The tool is in the run’s tool set and
tools.enabledis on. - The arguments validate strictly against the tool’s JSON Schema.
- If the tool needs a verified user, the run has one. Identity is filled in by K-Agent from the credential — the model never supplies it.
- It is available: business hours, catalog present, no open agent ticket for
create_ticket. - The same tool with the same arguments hasn’t already succeeded in this run.
- The run hasn’t been cancelled or superseded.
- Per-user limits: all HTTP tools together, 20 calls an hour per end user (or per session for anonymous users), counting every attempt;
create_ticket, 5 a day. - The round budget isn’t used up, and at most 5 calls run per round (extra calls get
too_many_calls).
The agent works for up to tools.max_tool_rounds rounds (1–5, default 3). If it still wants a tool after the last round, one final answer is produced with tools disabled. Confirmations — a ticket number, a handoff — come only from tool results, never from the model’s imagination.
HTTP tools
Section titled “HTTP tools”An HTTP tool calls an endpoint you own. K-Agent fills the request from a template, calls it through a protected client and shows the model only the fields you choose. The HTTP tools guide walks through one end to end.
{ "name": "order_status", "description": "Look up the status of the customer's order by its number.", "effect": "read", "requires_verified_user": true, "config": { "method": "GET", "url": "https://api.example.com/customers/{{end_user.external_id}}/orders/{{args.order_number}}", "headers": { "Authorization": "Bearer {{secret.ORDERS_TOKEN}}" }, "parameters": { "type": "object", "properties": { "order_number": { "type": "string", "description": "The order number, e.g. 8812" } }, "required": ["order_number"], "additionalProperties": false }, "response": { "items_path": "data", "fields": [ { "path": "status", "label": "Status" }, { "path": "eta", "label": "Expected delivery" } ], "max_items": 1, "empty_message": "No order with that number." }, "timeout_ms": 8000 }}Templating rules
Section titled “Templating rules”- Placeholders:
{{args.x}}(from the model),{{end_user.external_id}}and{{end_user.traits.k}}(from the credential, verified users only),{{secret.NAME}}(from your secrets) and{{var.name}}(from the agent’s variables). - Fail-closed: any placeholder that is unresolved or blank aborts the call. A request is never sent with a hole in it.
- Values are escaped for where they land: URL path, query string, header or JSON body.
- The URL must start with a literal
https://host[:port]/. Placeholders are allowed only in the path and query, and after substitution the path may not contain.or..segments. - At most 8 parameters. The names
args,end_user,secret,varandsysare reserved. - Any
{{end_user.*}}placeholder requiresrequires_verified_user: true. On such tools, parameters named like identity (phone,mobile,email,user_id,customer_id,account_id,external_id) are rejected with422 identity_as_parameter— identity comes from the credential, never from the model. - Each parameter has a format,
x-kagent-format:token(default, and required for anything used in the URL or headers): letters, digits, spaces and._@:+-, up to 64 characters;text: only for body parameters; up to 1,000 characters, JSON-encoded, with control, bidi and zero-width characters stripped.
- Arabic-Indic digits are converted to ASCII before checks, so
٨٨١٢and8812are the same order number. - A secret can only be sent to the hosts in its
allowed_hosts; anything else fails withsecret_host_not_allowed. - Headers named
Host,Forwarded,X-Forwarded-*,X-Real-IP,Connection,Transfer-Encoding,Content-LengthorProxy-*are rejected.
Network limits
Section titled “Network limits”Every request to a URL you configure — HTTP tools, API knowledge sources, webhooks and custom model base_urls — goes through one protected client:
https://only, on port 443 or 8443, with no proxy and no redirects;- addresses are checked when connecting, after DNS: loopback, private ranges (10/8, 172.16/12, 192.168/16), carrier-grade NAT (100.64/10), link-local and cloud metadata (169.254/16), IPv6 unique-local and link-local, multicast,
0.0.0.0/8and K-Agent’s own hosts are all refused; - connect timeout 3 seconds; total time up to
timeout_ms(at most 15 seconds); - responses over 1 MiB are rejected, not truncated.
What the model sees
Section titled “What the model sees”- Only the
response.fieldsyou list (up to 12, with labels), from up tomax_itemsrows (at most 20). - Values are cleaned — control, bidi and zero-width characters removed, Arabic joiners kept — and cut to 200 characters. The whole result stays under 4 KiB by dropping whole rows.
- The result is marked as data, not instructions, so text in your API can’t steer the agent.
- Upstream errors reach the model only as
upstream_failed,unreadableorrate_limited, with neutral wording. Status codes and bodies go to the run steps only.
Every call is signed with Standard Webhooks headers (webhook-id, webhook-timestamp, webhook-signature) using your project’s tool signing secret (GET /v1/tool_signing_secret), and sends User-Agent: K-Agent/1, so your endpoint can verify the call came from K-Agent.
HTTP tool definitions are copied into each published version. After editing a tool, publish the agent again for the change to reach production.
Client tools
Section titled “Client tools”A client tool runs in your app — reading a shopping cart in the browser, opening a screen in your mobile app. You declare it in the agent:
{ "tools": { "client": [ { "name": "get_cart", "description": "Returns the items in the customer's cart with prices.", "parameters": { "type": "object", "properties": {}, "additionalProperties": false }, "effect": "read", "rules": "Check the cart before answering questions about delivery fees." } ] }}When the model calls it, the run pauses:
{ "status": "requires_action", "required_action": { "type": "submit_tool_outputs", "tool_calls": [{ "call_id": "call_4kq7", "name": "get_cart", "arguments": {} }], "expires_at": 1791272520 }}Your app runs the tool and resumes the run with POST /v1/runs/{run}/submit_tool_outputs and {"tool_outputs": [{"call_id": "call_4kq7", "output": {…}, "is_error": false}]}. Every open call must be answered. If no outputs arrive within 10 minutes, the run fails with tool_outputs_expired. The client tools guide shows the whole loop.
Client tool names match ^[a-z][a-z0-9_]{0,47}$; their effect defaults to action. They are not offered on store: false calls.
Tool names must be unique across an agent’s built-in, HTTP and client tools (422 tool_name_conflict) and can’t reuse a built-in name. HTTP tool names match ^[a-z][a-z0-9_]{0,29}$.
In the test panel
Section titled “In the test panel”The dashboard’s test panel is a sandbox: read tools run live, action tools return {"ok": true, "simulated": true} unless you switch on Run real actions, and handoffs and tickets are marked as tests and never reach your Desk or webhooks.