> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.ada.cx/reference/tools/overview/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ada.cx/_mcp/server. # Tools API The Tools API is a single inventory of the HTTP tools (`api`) and code tools (`code`) configured on your AI Agent. Use it to list, fetch, create, update, and delete tools through one Platform API instead of a separate API per type. Download full OpenAPI spec ## Endpoints * **List tools** (`GET /v2/tools/`): Returns the Agent's tools in cursor-paginated pages. See [List tools](#list-tools). * **Get a tool** (`GET /v2/tools/{tool_id}`): Returns a single tool by its `id`, including the type-specific body. See [Get a tool](#get-a-tool). * **Create a tool** (`POST /v2/tools/`): Creates an `api` or `code` tool. See [Create a tool](#create-a-tool). * **Update a tool** (`PATCH /v2/tools/{tool_id}`): Partially updates a tool. Write rights depend on type. See [Update a tool](#update-a-tool). * **Delete a tool** (`DELETE /v2/tools/{tool_id}`): Soft-deletes an `api` or `code` tool. See [Delete a tool](#delete-a-tool). Read and write responses use the shared Tool envelope: `id`, `type`, `name`, `description`, `inputs`, `outputs`, `enabled`, `direct_use`, and `availability_rules`. Required fields that have no value are returned as `null` rather than omitted. ## Tool types | `type` | What it is | Type body on GET | | ------ | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | | `api` | An HTTP tool (an [Action](/docs/automation/tools/api-tools) that calls an external API). | `api` — URL, method, headers, and body. `Authorization` headers are never returned. | | `code` | A code tool that runs sandboxed Python. | `code` — source code and environment variables. | Code tools require the code tools product entitlement. Without it, they are omitted from the list, and `GET /v2/tools/{tool_id}` returns `404` for a code tool id. `POST` of a `code` tool also fails without the entitlement. ## Shared fields | Field | Type | Description | | -------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | string | The tool's unique identifier. | | `type` | string | One of `api` or `code`. | | `name` | string | The tool's name, as the model sees it. | | `description` | string | What the tool does, as the model sees it. | | `inputs` | array | The inputs the tool declares. | | `outputs` | array | The values the tool returns. | | `enabled` | boolean | Whether the tool is available to the Agent. This is the stored per-tool toggle. | | `direct_use` | boolean \| null | Whether the Agent may call this tool on its own, rather than only as a step inside a process. | | `availability_rules` | object \| null | The rule that gates when the tool is offered. `null` when the tool is always available. See [Availability rules](/reference/introduction/availability-rules). | ## List tools `GET /v2/tools/` returns `{ data, meta: { next_page_url } }`. List items use the same Tool envelope as GET-by-id **without** the type body. There is no `api` or `code` key on a list item. HTTP details and source code belong on a single-tool fetch. Results are returned in fixed source order: `api`, then `code`. Each source is ordered by `id`. ### Query parameters | Parameter | Description | | --------- | ---------------------------------------------------------------------------------------------------------- | | `type` | Restrict the list to one tool type: `api` or `code`. Omitted sources are not queried. | | `enabled` | Filter on the tool's own `enabled` flag. Same meaning for `api` and `code`: the stored per-tool toggle. | | `limit` | Maximum tools per page. Integer from `1` to `100`. Default `25`. Values outside that range return `400`. | | `cursor` | Opaque pagination token from a previous response's `meta.next_page_url`. Treat it as opaque, not as an id. | ### Pagination The list is cursor-paginated. Read `meta.next_page_url` from the response and replay it unchanged to fetch the next page. `next_page_url` is `null` on the last or empty page. See [Pagination](/reference/introduction/pagination). A cursor is bound to the Agent that minted it and to the `type` and `enabled` filters in effect. Changing those filters mid-walk, or presenting another Agent's cursor, returns `400`. ## Get a tool `GET /v2/tools/{tool_id}` returns one tool in the unified Tool shape. Shared fields sit at the top level; everything specific to how the tool runs is nested under the key matching `type` (`api` or `code`). * `Authorization` headers are stripped from `api.request.headers`. Other header values pass through, with variable references in `{var:|}` form. * An unknown id, an id from another Agent, or a malformed id returns `404` or `400`. ## Create a tool `POST /v2/tools/` creates an `api` or `code` tool and returns the created Tool (`201`). * `type`, `name`, and `description` are required. `type=api` requires an `api` body with `url`. `type=code` requires a `code` body with `source_code`. * A name that collides with a tool of the other type (`api` ↔ `code`) returns `409`. Reusing an `api` name among other `api` tools is not rejected. * `availability_rules` is the structured Knowledge rule object, not an internal DSL string. See [Availability rules](/reference/introduction/availability-rules). * `Authorization` headers on `api` tools are stored but stripped on every read. * `code.environment` is optional. `source` is one of `literal`, `variable`, `secret`, or `sensitive_value`. * `secret` takes the id of any secret-bearing variable: a sensitive variable, or a client-secret-scoped token. Which store it resolves from follows that variable's own scope. * `variable` takes a non-sensitive variable id only. Binding a sensitive variable or a token under it returns `422`. * If `source` is `sensitive_value`, GET returns an empty `value`. A GET-then-POST copy does not copy the stored secret. Send the value again. ## Update a tool `PATCH /v2/tools/{tool_id}` is a merge-patch. Omitted fields are preserved. Nested objects (`api`, `code`, `api.request`) merge key-by-key. Arrays (`inputs`, `outputs`, `headers`, `environment`) **replace** when the key is present. Send the complete list, including entries that are not changing. `availability_rules` is the one null-delete: omit it to leave the rule untouched, send an object to replace, send `null` to detach. Sending a different `type`, or a type body that does not match the tool (`api` on a `code` tool), returns `422`. An empty `{}` body is a no-op `200`. ### Write rights by type | | `api` | `code` | | -------------- | ---------------------------------------------------------------------- | -------------------------------------- | | Control | `enabled`, `direct_use`, `availability_rules` | Same | | Contract | `name`, `description`, `inputs`, `outputs` | Same | | Implementation | `api.url`, `api.request` (`method`, `content_type`, `body`, `headers`) | `code.source_code`, `code.environment` | ### Inputs and outputs GET returns `id` on every input and output. The value is `null` for `api` inputs. `id` is the identity of an output and of a `code` input. Other entities hold that id. `api` inputs stay name-keyed. * Send the stored `id` with a new `name` to rename an output or a `code` input. * A rename without `id` returns `422`. * An `api` input rename returns `422`. * Same `name` with a new `description`, `type`, `key`, `source`, `is_visible_to_llm`, or `variable.id` updates that row. * Adding a name while keeping existing names is allowed. Removing a name (send only what remains) is allowed. * Dropping a stored name and adding a different name in the same PATCH returns `422`. * If you omit `id` and keep the same `name`, the server matches by name. Redactions stay attached when `key` changes. Inputs on this API are `id`, `name`, `type`, and `description`. Omit `id` on create. The server mints one for `code` inputs and for every output. The bound variable for an output is `variable.id`, not `variable_id`. `required` on an input is ignored on write. GET always returns it. `api` and `code` tools return `null`. If `headers` is omitted from an `api` PATCH, stored headers, including `Authorization`, are left in place. `Authorization` stays stripped on read-back. If `code.environment` is present, the array replaces in full. For a `sensitive_value` row, an empty `value` leaves the stored secret unchanged. Remove the row to clear it. A name that collides with another `api` or `code` tool returns `409`. ## Delete a tool `DELETE /v2/tools/{tool_id}` soft-deletes an `api` or `code` tool and returns `204`. * An `api` tool that other entities still reference returns `409`. Code tools have no dependency check. ## Authentication Requests are authenticated with a Bearer API key. See [Authentication](/reference/introduction/authentication) for details on generating and using API keys. API keys use the same Platform API permission as other v2 APIs. There are no per-type scopes. One key lists every tool type the Agent is entitled to. > Overview