> ## Documentation Index
> Fetch the complete documentation index at: https://koreai-content-gov.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Tools

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.

## Tool binding types

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](#http-tools).                          |
| `mcp`           | Bind a tool exposed by an MCP server. See [MCP tools](#mcp-tools).                          |
| `sandbox`       | Run inline JavaScript/Python in an isolated sandbox. See [Code tools](#code-tools-sandbox). |
| `lambda`        | Invoke a cloud serverless function. See [Lambda tools](#lambda-tools).                      |
| `async_webhook` | Fire-and-callback async HTTP. See [Async webhook tools](#async-webhook-tools).              |
| `workflow`      | Invoke a durable workflow on the workflow engine. See [Workflow tools](#workflow-tools).    |
| `searchai`      | Query a SearchAI knowledge base. See [SearchAI tools](#searchai-tools).                     |
| `table`         | Structured CRUD against an Agent Table. See [Table tools](#table-tools).                    |

## Tool declaration syntax

You declare a tool with a function-style signature followed by indented properties.

```yaml theme={null}
TOOLS:
  tool_name(param1: type1, param2: type2 = default) -> ReturnType
    description: "What this tool does"
    type: http
    endpoint: "/api/path"
    method: POST
```

### Signature format

```yaml theme={null}
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`, optionally marked optional with `?` and/or given a default value:

```yaml theme={null}
param_name: type
param_name?: type              # optional (no default)
param_name: type = default_value
```

| Component   | Description                                                                               | Examples                              |
| ----------- | ----------------------------------------------------------------------------------------- | ------------------------------------- |
| `name`      | Parameter identifier (snake\_case)                                                        | `account_id`, `query`, `limit`        |
| `?`         | Optional marker after the name — makes the parameter optional without giving it a default | `note?: string`                       |
| `type`      | Data type                                                                                 | `string`, `number`, `boolean`, `date` |
| `= default` | Default value (also makes the parameter optional)                                         | `= 10`, `= "USD"`, `= true`           |

A parameter is required only when it has **neither** a `?` marker **nor** a default value. Both `name?: type` and `name: type = default` make it 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:

```yaml theme={null}
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:

```yaml theme={null}
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.

```yaml theme={null}
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}[]`       |

```yaml theme={null}
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.

```yaml theme={null}
TOOLS:
  verify_account(account_id: string) -> {name: string, status: string}
    description: "Retrieve account details and verify the account is active"
```

Write meaningful 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:

```yaml theme={null}
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

HTTP tools call REST API endpoints. They're the most common tool type.

```yaml theme={null}
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](#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                                                                                       |
| `retry_policy`     | `object`                                              | No       | *none*                   | Structured backoff policy (richer alternative to `retry`/`retry_delay`). See [Retry policy](#retry-policy).                 |
| `headers`          | `Record<string, string>`                              | No       | *none*                   | Custom HTTP headers                                                                                                         |
| `query_params`     | `Record<string,string>` / `object[]`                  | No       | *none*                   | Query string parameters. A `key: value` block keeps insertion order; an array of `{key, value}` also allows duplicate keys. |
| `body_type`        | `"json"` , `"form"` , `"xml"` , `"text"`              | No       | *none*                   | Request body encoding.                                                                                                      |
| `body_mode`        | `"auto"` , `"none"`                                   | No       | `"auto"`                 | For non-GET methods: `auto` serializes remaining params as the body; `none` sends no body.                                  |
| `body_template`    | `string`                                              | No       | *none*                   | Custom body template with interpolation. `body` is accepted as an alias.                                                    |
| `body_schema`      | `string`                                              | No       | *none*                   | JSON Schema for the request body (used with `use_body_schema: true`).                                                       |
| `use_body_schema`  | `boolean`                                             | No       | `false`                  | Author/validate the request body from `body_schema`.                                                                        |
| `request_variants` | `object[]`                                            | No       | *none*                   | Conditional request variants selected by a `when` expression. See [Request variants](#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-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.                                            |
| `wsdl_*`           | see [WSDL operation binding](#wsdl-operation-binding) | No       | *none*                   | Bind a SOAP tool to a stored WSDL operation instead of authoring the envelope.                                              |

### Path parameters

Use curly braces in the endpoint to reference tool parameters:

```yaml theme={null}
TOOLS:
  get_hotel(hotel_id: string) -> Hotel
    type: http
    endpoint: "/hotels/{hotel_id}"
    method: GET
```

### Headers

Custom headers are specified as key-value pairs:

```yaml theme={null}
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        |

<Note>`saml` is accepted by the parser but is **not currently resolved at runtime** — it is dropped during compilation. Prefer an [auth profile](#auth-profiles-jit-consent-and-connections) for enterprise SSO-backed integrations.</Note>

#### Auth configuration

For auth types that require additional configuration, use the `auth_config:` block:

```yaml theme={null}
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"
```

```yaml theme={null}
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.

```yaml theme={null}
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:

```yaml theme={null}
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.                |

### Result transformation

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:`:

```yaml theme={null}
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:

```yaml theme={null}
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   |

### Retry policy

`retry_policy` is a structured backoff configuration — a richer alternative to the scalar `retry`/`retry_delay` fields (both forms are still accepted).

```yaml theme={null}
TOOLS:
  flaky_api(id: string) -> {data: string}
    type: http
    endpoint: "https://api.example.com/{id}"
    method: GET
    retry_policy:
      strategy: exponential     # fixed | exponential
      initial_delay_ms: 200
      multiplier: 2
      max_delay_ms: 5000
      max_retries: 4
      jitter: full              # none | full
```

| Property           | Type                        | Default | Description                                    |
| ------------------ | --------------------------- | ------- | ---------------------------------------------- |
| `strategy`         | `"fixed"` , `"exponential"` | --      | Backoff strategy (required).                   |
| `initial_delay_ms` | `number`                    | --      | Delay before the first retry.                  |
| `multiplier`       | `number`                    | --      | Growth factor per attempt (for `exponential`). |
| `max_delay_ms`     | `number`                    | --      | Ceiling on the delay between attempts.         |
| `max_retries`      | `number`                    | --      | Maximum retry attempts.                        |
| `jitter`           | `"none"` , `"full"`         | --      | Randomization applied to the delay.            |

### SOAP support

HTTP tools can call SOAP endpoints by setting `protocol: soap`.

```yaml theme={null}
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. |

#### WSDL operation binding

Instead of hand-writing the SOAP envelope, a SOAP tool can bind to an operation from a WSDL asset stored in the project [WSDL Repository](/agent-platform/tools/wsdl-repo). When bound, the runtime resolves the operation's namespace, `SOAPAction`, and SOAP version from the stored WSDL and **generates the request body from the tool's JSON input** — no manual `body` template is needed. The request `endpoint` still comes from the tool: bulk-created tools are populated with the WSDL service address (or an endpoint override), and hand-authored tools must set `endpoint` explicitly.

Reference the WSDL by name; the platform resolves it to a stable asset/version at save time:

```yaml theme={null}
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"
    wsdl_asset: "PolicyService"       # asset name in the WSDL Repository
    wsdl_version: latest              # version number or "latest" (default)
    wsdl_operation: "lookupPolicy"
```

| Property                | Type     | Required | Description                                                                                     |
| ----------------------- | -------- | -------- | ----------------------------------------------------------------------------------------------- |
| `wsdl_asset`            | `string` | No       | WSDL asset **name** to bind. Resolved to `wsdl_asset_id` at save time.                          |
| `wsdl_version`          | `string` | No       | Version number (for example `2`) or `latest`. Defaults to the asset's latest version.           |
| `wsdl_operation`        | `string` | Yes\*    | Name of the WSDL operation to invoke.                                                           |
| `wsdl_asset_id`         | `string` | Yes\*    | Stable asset ID. Written automatically when `wsdl_asset` is resolved; may be authored directly. |
| `wsdl_version_id`       | `string` | Yes\*    | Stable immutable version ID. Written automatically when `wsdl_version` is resolved.             |
| `wsdl_service`          | `string` | No       | WSDL `service` name (when an operation is ambiguous across services).                           |
| `wsdl_port`             | `string` | No       | WSDL `port` name.                                                                               |
| `wsdl_binding`          | `string` | No       | WSDL `binding` name.                                                                            |
| `wsdl_target_namespace` | `string` | No       | Target namespace override for body generation.                                                  |
| `wsdl_element`          | `string` | No       | Root request element name, when it differs from the operation name.                             |

<Note>A WSDL binding requires `wsdl_operation` plus a resolved asset/version. Author either the by-name pair (`wsdl_asset` + optional `wsdl_version`) — which the platform rewrites to `wsdl_asset_id` / `wsdl_version_id` on save — or the stable IDs directly. Versions are immutable: a bound tool keeps calling its pinned version until you repoint it, so a WSDL update never silently changes behavior.</Note>

If a WSDL construct is unsupported, author a manual SOAP tool with an explicit `body` template instead — the binding fields and a manual body are mutually exclusive per tool.

### 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.

```yaml theme={null}
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 tools

MCP (Model Context Protocol) tools connect to external MCP servers that expose tools dynamically. The runtime handles protocol negotiation, transport, and tool discovery.

```yaml theme={null}
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                              |

### Dynamic tool discovery

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.

```yaml theme={null}
TOOLS:
  search(query: string) -> {results: object[]}
    description: "Search using Brave"
    type: mcp
    server: "brave-search"
    server_tool: "brave_web_search"
```

***

## Code tools (sandbox)

Code tools execute user-provided JavaScript or Python code in an isolated sandbox environment with resource limits and no network access.

```yaml theme={null}
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 new environment

### JavaScript runtime

JavaScript code tools have access to standard JavaScript built-ins. The code should return a value matching the declared return type.

```yaml theme={null}
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.

```yaml theme={null}
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

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.

```yaml theme={null}
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

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.

```yaml theme={null}
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

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 shouldn't run inside the stateless agent runtime.

```yaml theme={null}
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).   |

<Note>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.</Note>

***

## SearchAI tools

SearchAI tools query a SearchAI knowledge base (KB) index, letting an agent ground its answers in the indexed content.

```yaml theme={null}
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. |

<Note>SearchAI tools are tenant-scoped; the tenant binding is applied by the platform. Do not hardcode a `tenant_id` in shared/exported definitions.</Note>

***

## Table tools

Table tools perform structured CRUD against an **Agent Table** — a project-, user-, or session-scoped datastore.

```yaml theme={null}
TOOLS:
  save_note(title: string, body: string) -> {id: string}
    description: "Store a customer note"
    type: table
    table: customer_notes
    scope: end_user
    operations: [get, query, insert, update]
```

### Table binding properties

| Property         | Type       | Required | Default                           | Description                                                                                                                |
| ---------------- | ---------- | -------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `type`           | `"table"`  | Yes      | --                                | Declares this as a table tool.                                                                                             |
| `table`          | `string`   | Yes      | --                                | Primary table slug (`^[a-z_][a-z0-9_]*$`). `table_name` is an alias.                                                       |
| `scope`          | `string`   | No       | --                                | `project`, `end_user`, or `session`. The scope key is derived from trusted session context, never authored in the binding. |
| `operations`     | `string[]` | No       | read-only (`get`/`query`/`count`) | Allowed operations: `get`, `query`, `count`, `insert`, `update`, `delete`, `upsert`, `bulkInsert`, `bulkUpsert`.           |
| `tables`         | `string[]` | No       | --                                | Additional tables to JOIN (max 8).                                                                                         |
| `query_template` | `string`   | No       | --                                | Optional query template.                                                                                                   |

***

## Tool file imports

You can organize the tool definitions into reusable `.tools.abl` files and import it into agent documents. This lets you share tool definitions across multiple agents.

### Tool file format

A `.tools.abl` file starts with a `TOOLS:` section that can include shared defaults:

```yaml theme={null}
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.

```yaml theme={null}
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`.

```yaml expandable=true theme={null}
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:

```yaml theme={null}
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
```

***

## Tool features

### 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).

```yaml theme={null}
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 can't 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 isn't 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.

```yaml theme={null}
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).

```yaml theme={null}
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.                     |
| `max_search_tokens`      | `number`   | Token budget for SearchAI knowledge-base result context sent to the LLM. |

### Input/output transforms (`process`)

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.

```yaml theme={null}
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.

```yaml theme={null}
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.

```yaml theme={null}
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                                                            |
| ---------- | ---------------------------------------------------------------------- |
| `original` | Tool can access the original, unredacted PII values (broadest access). |
| `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                                  |

### Secret scrubbing

An always-on scrubber masks credentials (API keys, bearer tokens, private keys, passwords) in a
tool's output. Set `scrub_secrets: false` to opt a specific tool out (for example, when the tool's
job is to return a token your flow needs). This is independent of `pii_access`, which governs PII
rather than credentials.

```yaml theme={null}
TOOLS:
  mint_token(scope: string) -> {token: string}
    type: http
    endpoint: "/api/token"
    method: POST
    scrub_secrets: false
```

### 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.

```yaml theme={null}
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]
```

<Warning>
  `context_access` is validated against your `MEMORY:` declarations. A tool that declares a `read`
  of a **write-only** memory path (or a `write` of a **read-only** path) now fails compilation, and
  at runtime a tool is blocked from executing if its declared memory is unavailable. Declare the
  matching `MEMORY:` access mode for every path a tool reads or writes.
</Warning>

### Store result

The `store_result:` property controls whether the raw tool result blob is stored in the session context. Defaults to `true`.

```yaml theme={null}
TOOLS:
  log_event(event: string) -> {logged: boolean}
    description: "Log an audit event"
    type: http
    endpoint: "/api/audit"
    method: POST
    store_result: false
```

### Reuse secrets across tools (SecretRef)

Some flows need a credential produced by one tool (a one-time token, session key, or OTP) to be sent to a later tool — without ever exposing the raw value to the LLM. SecretRef captures such values into an encrypted, session-scoped **secret vault** and restores them into downstream tool calls.

* **Producer** — the tool that returns the secret declares a `RESULT_SECRETS:` block. Each entry captures a result field into the vault under a key, in the form `<result_path> -> <vault_key> (options)`.
* **Consumer** — a downstream tool declares a `SECRET_ACCESS:` block listing the vault keys it may read, then references them with the `{{_secret.<key>}}` placeholder in its `headers` or `body_template`.

```yaml theme={null}
TOOLS:
  # Producer: capture the OTP token into the vault, never exposing it to the model
  request_otp(account_id: string) -> {otp_token: string, expires_in: number}
    type: http
    endpoint: "/api/otp/request"
    method: POST
    RESULT_SECRETS:
      otp_token -> txn_otp (consumers: [convert_transaction_to_emi], ttl: 300, single_use: true)

  # Consumer: restore the vaulted secret into a header — the model never sees it
  convert_transaction_to_emi(txn_id: string) -> {status: string}
    type: http
    endpoint: "/api/txn/convert"
    method: POST
    SECRET_ACCESS:
      READ: [txn_otp]
    headers:
      X-OTP-Token: "{{_secret.txn_otp}}"
```

#### `RESULT_SECRETS` entry options

| Option        | Type       | Description                                                                                          |
| ------------- | ---------- | ---------------------------------------------------------------------------------------------------- |
| `<path>`      | `string`   | Result field to capture (left of `->`).                                                              |
| `<vault_key>` | `string`   | Vault key to store it under (right of `->`).                                                         |
| `consumers`   | `string[]` | Tool names allowed to restore this secret. Omit to allow any consumer that declares `SECRET_ACCESS`. |
| `ttl`         | `number`   | Time-to-live in seconds before the vaulted secret expires.                                           |
| `single_use`  | `boolean`  | When `true`, the secret is consumed (invalidated) after its first use.                               |

<Note>SecretRef is **fail-closed**: the vault is invisible to the LLM, `{{_secret.X}}` resolves only in `headers` and `body_template` (never forwarded as a query/body param on its own), and an unresolved reference substitutes an empty string — the literal `{{_secret.X}}` placeholder is never sent upstream as a credential.</Note>

***

**Related articles:**

* [Language overview](/agent-platform/abl-reference/language-overview) -- file structure and syntax.
* [Agent declaration](/agent-platform/abl-reference/agent-declaration) -- `tool_timeout` and model settings in EXECUTION.
* [GATHER](/agent-platform/abl-reference/gather) -- information collection (often used alongside tools).
* [FLOW](/agent-platform/abl-reference/flow) -- `CALL` action for invoking tools within flow steps.
