The TOOLS: section defines the external capabilities available to an agent. Each tool declares a typed signature (parameters and return type), an optional execution binding, and metadata that guides the LLM’s tool selection.
The type: property selects how a tool is executed. The supported values are:
type | Purpose |
|---|
http | Call a REST (or SOAP) API endpoint. See HTTP tools. |
mcp | Bind a tool exposed by an MCP server. See MCP tools. |
sandbox | Run inline JavaScript/Python in an isolated sandbox. See Code tools. |
lambda | Invoke a cloud serverless function. See Lambda tools. |
async_webhook | Fire-and-callback async HTTP. See Async webhook tools. |
workflow | Invoke a durable workflow on the workflow engine. See Workflow tools. |
searchai | Query a SearchAI knowledge base. See SearchAI tools. |
A tool is declared with a function-style signature followed by indented properties:
TOOLS:
tool_name(param1: type1, param2: type2 = default) -> ReturnType
description: "What this tool does"
type: http
endpoint: "/api/path"
method: POST
name(parameters) -> return_type
- name — a lowercase identifier using
snake_case
- parameters — comma-separated list of typed parameters
- return_type — the type of data the tool returns
Parameter syntax
Each parameter follows the format name: type with an optional default value:
param_name: type
param_name: type = default_value
| Component | Description | Examples |
|---|
name | Parameter identifier (snake_case) | account_id, query, limit |
type | Data type | string, number, boolean, date |
= default | Default value (makes parameter optional) | = 10, = "USD", = true |
Parameters without a default value are required. Parameters with a default value are optional.
Parameter types
| Type | Description | Examples |
|---|
string | Text value | "hello" |
number | Numeric value (integer or float) | 42, 3.14 |
boolean | True or false | true, false |
date | Date value | "2026-03-01" |
object | Nested object (specify fields with nested parameters:) | — |
type[] | Array of the given type | string[], number[] |
Object parameters
When a parameter has type object, you can define nested fields using a parameters: block under the tool:
TOOLS:
create_order(customer: object, items: object[]) -> {order_id: string}
description: "Create a new order"
parameters:
customer:
name: string
email: string
items:
product_id: string
quantity: number
Array parameters
Array types use the [] suffix:
TOOLS:
bulk_lookup(ids: string[]) -> {results: object[]}
description: "Look up multiple records by ID"
Parameter enrichment and sources
The parameters: block does more than describe nested object fields — it can enrich any
signature-declared parameter with a description, validation, visibility, and a value source.
This lets you inject values (from system state, config, auth, an expression, or a lookup table)
without the LLM having to supply them, and optionally hide them from the model.
TOOLS:
charge_card(amount: number, customer_id: string) -> {receipt_id: string}
description: "Charge the customer's card on file"
type: http
endpoint: "/api/charges"
method: POST
parameters:
customer_id:
source: system # model | system | runtime | config | auth | expr | lookup
value: "session.customer_id"
hidden: true # do not expose to the model
amount:
description: "Charge amount in the account currency"
required: true
| Enrichment key | Type | Description |
|---|
description | string | Parameter description shown to the model. |
required | boolean | Whether the parameter is required. |
default | any | Default value. |
source | string | Value source: model, system, runtime, config, auth, expr, lookup. |
value | string | The expression or reference used with expr/lookup/system/config sources. |
key / table | string | Lookup key and table (with source: lookup). |
hidden | boolean | Hide the parameter from the model (still sent to the tool). |
visibility | object | Fine-grained { model, trace } visibility flags. |
properties | object | Nested object field schema (for object params). |
items | object | Item schema (for array params). |
Return type
The return type appears after the -> arrow. It can be:
| Form | Syntax | Example |
|---|
| Simple type | -> type | -> string |
| Object type | -> {field: type, ...} | -> {id: string, name: string} |
| Array type | -> type[] | -> Hotel[] |
| Nested object | -> {field: {nested: type}} | -> {user: {name: string, age: number}} |
| Optional fields | -> {field?: type} | -> {error?: string} |
| Array of objects | -> {field: type}[] | -> {id: string, title: string}[] |
TOOLS:
search_hotels(destination: string, checkin: date, checkout: date) -> {hotels: {id: string, name: string, price: number, rating: number}[], total: number}
description: "Search available hotels"
Description
The description: property provides a natural-language explanation of what the tool does. The LLM uses this description to decide when and how to call the tool.
TOOLS:
verify_account(account_id: string) -> {name: string, status: string}
description: "Retrieve account details and verify the account is active"
Write descriptions that help the LLM understand:
- What the tool does
- When to call it
- What data it returns
Hints
The hints: block provides execution metadata that the runtime uses for optimization:
TOOLS:
get_balance(account_id: string) -> {balance: number}
description: "Get account balance"
hints:
cacheable: true
latency: fast
timeout: 5000
| Hint | Type | Default | Description |
|---|
cacheable | boolean | none | Whether results can be cached across calls with the same parameters |
latency | "fast" , "medium" , "slow" | none | Expected latency category for runtime scheduling |
side_effects | boolean | none | Whether the tool modifies external state |
requires_auth | boolean | none | Whether the tool requires authenticated context |
timeout | number | none | Tool-specific timeout in milliseconds (overrides EXECUTION.tool_timeout) |
HTTP tools call REST API endpoints. They are the most common tool type.
TOOLS:
search_flights(origin: string, destination: string, date: date) -> {flights: {id: string, price: number}[]}
description: "Search available flights"
type: http
endpoint: "https://api.flights.com/v1/search"
method: POST
auth: bearer
timeout: 10000
retry: 3
retry_delay: 1000
HTTP binding properties
| Property | Type | Required | Default | Description |
|---|
type | "http" | Yes | — | Declares this as an HTTP tool |
endpoint | string | Yes | — | URL or path for the API call. Supports path parameters: "/hotels/{hotel_id}" |
method | "GET" , "POST" , "PUT" , "PATCH" , "DELETE" | Yes | — | HTTP method |
auth | string | No | "none" | Authentication type (see Auth) |
timeout | number | No | EXECUTION.tool_timeout | Request timeout in milliseconds |
retry | number | No | none | Number of retry attempts on failure |
retry_delay | number | No | none | Delay in milliseconds between retries |
headers | Record<string, string> | No | none | Custom HTTP headers |
query_params | Record<string, string> | No | none | Query string parameters |
body_type | "json" , "form" , "xml" , "text" | No | none | Request body encoding. |
body_template | string | No | none | Custom body template with interpolation. body is accepted as an alias. |
request_variants | object[] | No | none | Conditional request variants selected by a when expression. See Request variants. |
rate_limit | number | No | none | Maximum requests per second |
circuit_breaker | {threshold, resetMs} | No | none | Circuit breaker configuration |
protocol | "rest" , "soap" | No | "rest" | Wire protocol. Set soap for SOAP endpoints. See SOAP support. |
soap_version | "1.1" , "1.2" | No | "1.1" | SOAP version (when protocol: soap). |
soap_action | string | No | none | SOAPAction header (1.1) or action media-type parameter (1.2). |
on_soap_fault | "error" , "data" | No | none | How to handle <soap:Fault> — error throws, data returns the fault payload. |
Path parameters
Use curly braces in the endpoint to reference tool parameters:
TOOLS:
get_hotel(hotel_id: string) -> Hotel
type: http
endpoint: "/hotels/{hotel_id}"
method: GET
Custom headers are specified as key-value pairs:
TOOLS:
get_data(query: string) -> {results: object[]}
type: http
endpoint: "/api/data"
method: POST
headers:
X-Api-Version: "2024-01"
Accept: "application/json"
Auth
The auth: property specifies the authentication mechanism. The runtime resolves credentials from the project’s credential store — the ABL document never contains actual secrets.
| Auth type | Description |
|---|
none | No authentication |
bearer | Bearer token in Authorization header |
api_key | API key (header name configurable via auth_config) |
oauth2_client | OAuth 2.0 client credentials flow |
oauth2_user | OAuth 2.0 authorization code flow (user-scoped tokens) |
saml | SAML assertion-based authentication |
custom | Custom authentication with configurable headers |
saml is accepted by the parser but is not currently resolved at runtime — it is dropped
during compilation. Prefer an auth profile for
enterprise SSO-backed integrations.
Auth configuration
For auth types that require additional configuration, use the auth_config: block:
TOOLS:
get_user_data(user_id: string) -> {name: string, email: string}
type: http
endpoint: "/api/users/{user_id}"
method: GET
auth: oauth2_client
auth_config:
token_url: "https://auth.example.com/oauth/token"
client_id: "my-client-id"
client_secret: "{{config.OAUTH_CLIENT_SECRET}}"
scopes: "read:users"
TOOLS:
call_partner_api(payload: string) -> {status: string}
type: http
endpoint: "https://partner.example.com/api"
method: POST
auth: api_key
auth_config:
header_name: "X-API-Key"
| Auth config property | Type | Used with | Description |
|---|
token_url | string | oauth2_client, oauth2_user | OAuth token endpoint URL |
client_id | string | oauth2_client, oauth2_user | OAuth client identifier |
client_secret | string | oauth2_client, oauth2_user | OAuth client secret (use {{config.X}} placeholders) |
scopes | string | oauth2_client, oauth2_user | Space-separated OAuth scopes |
header_name | string | api_key | Custom header name for the API key |
provider | string | oauth2_user, saml | Auth provider identifier |
custom_headers | Record<string, string> | custom | Custom authentication headers |
Credential placeholders
Credentials use {{config.NAME}} placeholder syntax (with isSecret: true on the config var). The runtime resolves these from the project’s config vars at execution time. For OAuth integrations, binding an auth profile is the preferred approach. Never embed actual credentials in ABL files.
auth_config:
client_secret: "{{config.PARTNER_OAUTH_SECRET}}"
Auth profiles, JIT, consent, and connections
For OAuth and enterprise integrations, the preferred approach is to bind a pre-configured auth
profile by name rather than declaring auth_config inline. These tool-level properties control
credential resolution, transport security, just-in-time authorization, consent, and per-user vs.
shared connections:
TOOLS:
create_ticket(subject: string, body: string) -> {ticket_id: string}
description: "Create a support ticket"
type: http
endpoint: "https://itsm.example.com/api/tickets"
method: POST
auth_profile: servicenow_oauth # named profile resolved at runtime
tls_profile: partner_mtls # mTLS transport cert profile
auth_jit: true # acquire credentials just-in-time
consent: preflight # preflight | inline
connection: per_user # per_user | shared
| Property | Type | Description |
|---|
auth_profile | string | Name of a pre-configured auth profile; resolved at runtime (no secrets in the ABL file). |
tls_profile | string | Name of an mTLS transport-certificate profile (independent of auth_profile). |
auth_jit | boolean | Acquire credentials just-in-time at call time rather than up front. |
consent | "preflight" , "inline" | When user consent is obtained — before the run (preflight) or during the conversation (inline). |
connection | "per_user" , "shared" | Whether the integration uses per-end-user connections or a single shared connection. |
Tool results are available in the session context after execution. You can map specific result fields to session variables using on_result: and handle errors with on_error::
TOOLS:
get_balance(account_id: string) -> {balance: number, currency: string}
description: "Get account balance"
type: http
endpoint: "/api/balance"
method: GET
on_result:
set:
current_balance: result.balance
account_currency: result.currency
on_error:
set:
balance_error: error.message
Beyond set:, both on_result: and on_error: accept an ordered do: action block that can run
SET, CLEAR, LOG, RESPOND, CALL, GOTO/THEN, HANDOFF, DELEGATE, RETURN, FORMATS,
and COMPLETE actions, with conditional IF:/WHEN:/ELSE: branches.
SSRF protection
The platform enforces SSRF (Server-Side Request Forgery) protection on all HTTP tool endpoints. Private IP ranges, localhost, and internal network addresses are blocked at the runtime level. Only allowlisted domains and public endpoints are permitted for HTTP tool calls.
Circuit breaker
The circuit breaker prevents cascading failures by halting requests to a failing endpoint after a threshold of consecutive errors:
TOOLS:
unreliable_api(query: string) -> {data: string}
type: http
endpoint: "https://api.example.com/data"
method: GET
circuit_breaker:
threshold: 5
resetMs: 30000
| Property | Type | Description |
|---|
threshold | number | Number of consecutive failures before the circuit opens |
resetMs | number | Milliseconds to wait before trying the endpoint again |
SOAP support
HTTP tools can call SOAP endpoints by setting protocol: soap.
TOOLS:
lookup_policy(policy_number: string) -> {status: string, holder: string}
description: "Look up an insurance policy"
type: http
endpoint: "https://legacy.example.com/PolicyService"
method: POST
protocol: soap
soap_version: "1.1"
soap_action: "urn:PolicyService#lookupPolicy"
on_soap_fault: error # error | data
| Property | Type | Default | Description |
|---|
protocol | "rest" , "soap" | "rest" | Wire protocol. |
soap_version | "1.1" , "1.2" | "1.1" | SOAP envelope version. |
soap_action | string | none | SOAPAction header (1.1) or action media-type parameter (1.2). |
on_soap_fault | "error" , "data" | none | error raises on <soap:Fault>; data returns the fault as the result. |
Request variants
For endpoints that vary by condition, request_variants selects a request shape at call time based
on a when expression. Each variant can override the endpoint, method, headers, query params, and
body.
TOOLS:
submit(order: object, region: string) -> {ref: string}
type: http
endpoint: "https://api.example.com/us/submit"
method: POST
request_variants:
- name: eu
when: region == "EU"
endpoint: "https://api.eu.example.com/submit"
body_type: json
- name: default
default: true
MCP (Model Context Protocol) tools connect to external MCP servers that expose tools dynamically. The runtime handles protocol negotiation, transport, and tool discovery.
TOOLS:
web_search(query: string) -> {results: {title: string, url: string, snippet: string}[]}
description: "Search the web"
type: mcp
server: "brave-search"
MCP binding properties
| Property | Type | Required | Default | Description |
|---|
type | "mcp" | Yes | — | Declares this as an MCP tool |
server | string | Yes | — | MCP server name (resolved from runtime configuration) |
server_tool | string | No | Tool name | Tool name on the MCP server (if different from the ABL tool name) |
headers | Record<string, string> | No | none | Per-call headers, supporting {{config.X}} / {{session.X}} templates. |
Server configuration
The server value is a logical name that maps to an MCP server configuration in the project’s runtime settings. Server configuration (transport type, connection URL, authentication) is managed at the project level, not in the ABL file.
The platform supports these MCP transport types:
| Transport | Description |
|---|
stdio | Standard input/output (for local MCP server processes) |
http | HTTP-based transport (Streamable HTTP) |
websocket | WebSocket-based transport |
MCP servers can expose multiple tools. When you declare an MCP tool in ABL, you bind a specific tool from the server. If the tool name on the MCP server differs from the tool name in your ABL file, use server_tool: to specify the server-side name:
TOOLS:
search(query: string) -> {results: object[]}
description: "Search using Brave"
type: mcp
server: "brave-search"
server_tool: "brave_web_search"
Code tools execute user-provided JavaScript or Python code in an isolated sandbox environment with resource limits and no network access.
TOOLS:
calculate_tax(income: number, state: string) -> {tax: number, rate: number}
description: "Calculate state income tax"
type: sandbox
runtime: javascript
timeout: 5000
memory_mb: 128
code: |
const rates = { CA: 0.133, NY: 0.109, TX: 0 };
const rate = rates[state] || 0.05;
return { tax: income * rate, rate };
Sandbox binding properties
| Property | Type | Required | Default | Description |
|---|
type | "sandbox" | Yes | — | Declares this as a sandbox tool |
runtime | "javascript" , "python" | Yes | — | Execution runtime |
code | string | No | none | Inline source code (pipe block syntax for multi-line) |
timeout | number | No | Platform default | Maximum execution time in milliseconds |
memory_mb | number | No | Platform default | Memory limit in megabytes |
Isolation
Sandbox tools execute in a gVisor-isolated environment with the following restrictions:
- No network access
- No filesystem access beyond the sandbox working directory
- Resource limits enforced (CPU, memory, execution time)
- Each execution runs in a fresh environment
JavaScript runtime
JavaScript code tools have access to standard JavaScript built-ins. The code should return a value matching the declared return type.
TOOLS:
format_currency(amount: number, currency: string) -> {formatted: string}
type: sandbox
runtime: javascript
code: |
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency
});
return { formatted: formatter.format(amount) };
Python runtime
Python code tools use a sandboxed Python interpreter. The code should return a dictionary matching the declared return type.
TOOLS:
analyze_text(text: string) -> {word_count: number, sentences: number}
type: sandbox
runtime: python
code: |
import re
words = len(text.split())
sentences = len(re.split(r'[.!?]+', text))
return {"word_count": words, "sentences": sentences}
Lambda tools invoke cloud serverless functions. The function name is a logical identifier resolved to an actual endpoint (ARN, URL) at runtime through the project’s function registry.
TOOLS:
process_document(document_url: string, format: string) -> {text: string, pages: number}
description: "Extract text from a document"
type: lambda
function: "document-processor"
runtime: "nodejs20"
timeout: 30000
Lambda binding properties
| Property | Type | Required | Default | Description |
|---|
type | "lambda" | Yes | — | Declares this as a lambda tool |
function | string | Yes | — | Logical function name (resolved at runtime) |
runtime | string | No | none | Runtime hint (for example. "nodejs20", "python3.12") |
timeout | number | No | Platform default | Override timeout for this function in milliseconds |
Async webhook tools send an HTTP request with a callback URL injected into the payload. The external system processes the request asynchronously and posts the result back to the callback URL when complete.
TOOLS:
generate_report(report_type: string, date_range: string) -> {report_url: string, status: string}
description: "Generate a financial report (processed asynchronously)"
type: async_webhook
endpoint: "https://reports.internal/api/generate"
method: POST
callback_url_field: "callbackUrl"
timeout_seconds: 3600
Async webhook binding properties
| Property | Type | Required | Default | Description |
|---|
type | "async_webhook" | Yes | — | Declares this as an async webhook tool |
endpoint | string | Yes | — | URL to send the initial request |
method | "POST" , "PUT" , "PATCH" | Yes | — | HTTP method |
headers | Record<string, string> | No | none | Custom HTTP headers |
callback_url_field | string | No | "callbackUrl" | Dot-path in the request body where the callback URL is injected |
timeout_seconds | number | No | 3600 | Timeout in seconds for the async callback response |
Workflow tools invoke a durable workflow on the workflow engine. Use these for long-running,
stateful orchestrations (waits, polling, human approval, multi-hour processes) that should not run
inside the stateless agent runtime.
TOOLS:
start_onboarding(customer_id: string, plan: string) -> {run_id: string, status: string}
description: "Kick off the customer onboarding workflow"
type: workflow
workflow_id: "customer-onboarding"
mode: async
timeout_ms: 60000
param_mapping:
customerId: customer_id
selectedPlan: plan
Workflow binding properties
| Property | Type | Required | Default | Description |
|---|
type | "workflow" | Yes | — | Declares this as a workflow tool. |
workflow_id | string | Yes | — | Logical workflow identifier. Version routing comes from the deployment manifest. |
mode | "sync" , "async" | No | "sync" | sync waits for completion; async starts the run and returns a handle. |
timeout_ms | number | No | none | Maximum time to wait. Supports {{config.X}} interpolation. |
param_mapping | Record<string,string> | No | none | Maps workflow input fields to tool parameters (workflow key → tool parameter). |
The workflow must exist in the same tenant/project; this is validated at compile time. Legacy
workflow_version / trigger_id fields are no longer used and are silently ignored.
SearchAI tools query a SearchAI knowledge base (KB) index, letting an agent ground its answers in
indexed content.
TOOLS:
search_policies(query: string) -> {results: object[]}
description: "Search the HR policy knowledge base"
type: searchai
index_id: "hr-policies-v2"
kb_name: "HR Policies"
search_instructions: "Prefer the most recent policy version when duplicates exist."
SearchAI binding properties
| Property | Type | Required | Default | Description |
|---|
type | "searchai" | Yes | — | Declares this as a SearchAI tool. |
index_id | string | Yes | — | SearchAI KB index to query. |
kb_name | string | No | — | Display name for the knowledge base. |
search_instructions | string | No | — | Extra instructions injected into the search/classification prompt. |
SearchAI tools are tenant-scoped; the tenant binding is applied by the platform. Do not hardcode
a tenant_id in shared/exported definitions.
Tool definitions can be organized into reusable .tools.abl files and imported into agent documents. This allows sharing tool definitions across multiple agents.
A .tools.abl file starts with a TOOLS: section that can include shared defaults:
TOOLS:
base_url: "https://api.hotels.com/v1"
auth: bearer
timeout: 5000
retry: 3
search_hotels(destination: string, checkin: date, checkout: date) -> Hotel[]
type: http
endpoint: "/search"
method: POST
description: "Search available hotels"
get_hotel(hotel_id: string) -> Hotel
type: http
endpoint: "/hotels/{hotel_id}"
method: GET
description: "Get hotel details by ID"
Shared defaults
The following defaults can be set at the top of a .tools.abl file and apply to all tools in the file:
| Default | Type | Description |
|---|
base_url | string | Base URL prepended to all relative endpoint paths |
auth | string | Default auth type for all tools |
timeout | number | Default timeout in milliseconds |
retry | number | Default retry count |
retry_delay | number | Default retry delay in milliseconds |
rate_limit | number | Default rate limit (requests per second) |
headers | Record<string, string> | Default headers applied to all tools |
Import syntax
Import tools from a .tools.abl file into an agent using the file: directive within the TOOLS: section:
TOOLS:
file: "./tools/hotels-api.tools.abl" [search_hotels, get_hotel]
The import specifies:
- The path to the
.tools.abl file (relative to the agent file)
- An optional list of specific tool names to import (in brackets). If omitted, all tools from the file are imported.
Project bundle import can also synthesize tool stubs from inline agent TOOLS: signatures during apply. That keeps imported agents compileable even when the bundle didn’t include companion .tools.abl files, and the next export writes those synthesized stubs back out as tools/<name>.tools.abl.
Example
Given the file tools/hotels-api.tools.abl:
TOOLS:
base_url: "https://api.hotels.com/v1"
auth: bearer
search_hotels(destination: string, checkin: date, checkout: date) -> Hotel[]
type: http
endpoint: "/search"
method: POST
description: "Search available hotels"
get_hotel(hotel_id: string) -> Hotel
type: http
endpoint: "/hotels/{hotel_id}"
method: GET
description: "Get hotel details by ID"
get_hotel_reviews(hotel_id: string, limit: number = 10) -> Review[]
type: http
endpoint: "/hotels/{hotel_id}/reviews"
method: GET
description: "Get reviews for a hotel"
An agent file can import selected tools:
AGENT: Hotel_Search
TOOLS:
file: "./tools/hotels-api.tools.abl" [search_hotels, get_hotel]
# Additional agent-specific tools
check_availability(hotel_id: string, dates: string) -> {available: boolean}
description: "Check real-time availability"
type: http
endpoint: "/api/availability"
method: POST
Confirmation
The confirmation: block configures whether the agent should ask the user for confirmation before executing a tool. This is particularly important for tools with side effects (for example. executing a payment, deleting a record).
TOOLS:
execute_payment(amount: number, recipient: string) -> {confirmation_id: string}
description: "Execute a payment"
type: http
endpoint: "/api/payments"
method: POST
confirmation:
require: always
immutable_params: [recipient]
| Property | Type | Default | Description |
|---|
require | "always" , "never" , "when_side_effects" | none | When to require user confirmation |
immutable_params | string[] | none | Parameters that cannot be changed after confirmation |
consent_required_in | "conversation" , "explicit_prompt" | none | Where consent must be obtained. |
consent_scope | string[] | none | Consent scopes required before executing. |
consent_action | string | none | Named consent action to trigger. |
consent_fallback | "explicit_prompt" , "block" | none | What to do if consent is not granted. |
State authority and provided fields
The effect property declares a tool’s authority over session state, and provides lists the
fields the tool is authoritative to supply. These help the runtime reason about which values a tool
is allowed to write.
TOOLS:
set_shipping_address(address: object) -> {saved: boolean}
description: "Persist the customer's shipping address"
type: http
endpoint: "/api/shipping-address"
method: PUT
effect: state_write # read_only | state_write | side_effect
provides: [shipping_address, shipping_zone]
| Property | Type | Values | Description |
|---|
effect | string | read_only, state_write, side_effect | The tool’s authority over external/session state. |
provides | string[] | — | Fields this tool is authoritative to provide. |
Result compaction
The per-tool compaction: block controls how this tool’s results are compacted in conversation
history (independent of the agent-wide EXECUTION.compaction policy).
TOOLS:
search_catalog(query: string) -> {items: object[]}
type: http
endpoint: "/api/catalog/search"
method: GET
compaction:
essential_fields: [items.id, items.name, items.price]
max_description_length: 500
summary_timeout_ms: 3000
| Property | Type | Description |
|---|
essential_fields | string[] | Fields to preserve verbatim when compacting this tool’s result. |
max_description_length | number | Maximum characters kept for descriptive fields. |
summary_timeout_ms | number | Timeout for LLM summarization of this tool’s result. |
The process: block defines pure input (before) and output (after) transform stages that run
around the tool call — remapping parameters, enforcing preconditions, and reshaping results.
TOOLS:
quote_fx(amount: number, from: string, to: string) -> {converted: number}
type: http
endpoint: "/api/fx/quote"
method: POST
process:
before:
params:
amount_cents: "amount * 100"
require: [amount > 0]
on_fail: reask("Please provide a positive amount.")
after:
result:
converted: "result.amount_cents / 100"
on_fail: warn("Could not normalize the quote.")
before supports params (computed parameter map), require (precondition expressions), on_fail
(one of block("msg"), reask("msg"), warn("msg"), use_original, fallback("msg")), and use
(a named transform). after supports result (output remapping) and on_fail.
Caching hints
Use the cacheable hint to indicate that a tool’s results can be cached:
TOOLS:
get_exchange_rate(from: string, to: string) -> {rate: number}
description: "Get current exchange rate"
type: http
endpoint: "/api/fx/rate"
method: GET
hints:
cacheable: true
latency: fast
When cacheable: true, the runtime may cache results for identical parameter combinations. When cacheable: false, results are never cached (use this for tools that return time-sensitive data).
PII access
The pii_access: property declares what level of personally identifiable information (PII) a tool can access:
TOOLS:
verify_identity(ssn_last4: string, dob: string) -> {verified: boolean}
description: "Verify customer identity"
type: http
endpoint: "/api/identity/verify"
method: POST
pii_access: user
| Value | Description |
|---|
tools | Tool can access PII data from other tool results |
user | Tool can access user-provided PII |
logs | PII from this tool may appear in logs |
llm | PII from this tool is sent to the LLM |
Context access
The context_access: block declares which session context variables a tool reads from and writes to. This enables the runtime to automatically inject context into HTTP requests and apply result values back to session state:
TOOLS:
update_profile(name: string) -> {updated: boolean}
description: "Update user profile"
type: http
endpoint: "/api/profile"
method: PUT
context_access:
read: [user.id, user.email]
write: [user.name, user.updated_at]
Store result
The store_result: property controls whether the raw tool result blob is stored in the session context. Defaults to true.
TOOLS:
log_event(event: string) -> {logged: boolean}
description: "Log an audit event"
type: http
endpoint: "/api/audit"
method: POST
store_result: false
- Language overview — file structure and syntax
- Agent declaration —
tool_timeout and model settings in EXECUTION
- GATHER — information collection (often used alongside tools)
- FLOW —
CALL action for invoking tools within flow steps