---
title: "Update Tool"
method: PATCH
path: "/v1/agent/tools/{tool_id}"
tags: ["Agent Tools"]
---

# Update Tool

`PATCH /v1/agent/tools/{tool_id}`

## Request

- Base URL: `https://api.fish.audio`
- URL: `https://api.fish.audio/v1/agent/tools/{tool_id}`
- Auth: HTTP bearer

Patch tool fields; omitted fields keep their value (null is rejected —
send an empty string to clear a text field). `headers` replaces the header
list wholesale — include credential values again whenever you send it,
since reads never return them. Attached agents' drafts pick up the change
immediately; published versions stay frozen until re-published.

## Path parameters

- `tool_id` string, required

## Request body

- PublicAgentToolUpdatePayload
  - `name` string, nullable
  - `description` string, nullable
  - `arguments` AgentWebhookArgumentPayload[], nullable: Older shape of `parameters`: each entry becomes a required string parameter. Mutually exclusive with `parameters` in one request. Reads return both, `arguments` being the string parameters of the schema.
    - `name` string, required
    - `description` string
  - `parameters` object, nullable: Call parameters as a JSON Schema object (draft 2020-12): `type: object` (filled in when omitted), `properties`, `required`. Standard meaning throughout: `required` means the key must be present, `type: ["string", "null"]` allows null, `minLength: 1` makes a string non-empty, `enum` and `pattern` constrain the value, `default` fills a key the model left out. Mutually exclusive with `arguments` in one request. A tool created with `parameters` starts in `parameter_mode: strict`.
  - `parameter_mode` 'legacy' | 'strict', nullable: Whether the agent runtime checks each call's arguments against `parameters` before running the tool. `legacy` (the default for tools created with `arguments`, and every tool from before this field existed): no check, the model's arguments run as sent. `strict` (the default for tools created with `parameters`): a call that does not satisfy the schema is refused and the model is told to ask the caller for the missing information, and the LLM provider's constrained decoding is turned on where the model supports it (OpenAI models and a custom OpenAI-compatible endpoint receive the tool with `strict: true`, Gemini on the platform's native channel runs validated function calling). Changing `parameters` never changes the mode, and the mode can be changed on its own.
  - `method` 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', nullable
  - `url` string, nullable
  - `content_type` string, nullable
  - `body_template` string, nullable: Request body sent for non-GET calls. `{{argument}}`, `{{system.*}}` and custom session variable placeholders are filled in at call time; a missing value becomes empty. When the body's content type is JSON (the default `application/json`, any `+json` type, or a `Content-Type` header saying so), a placeholder inside a JSON string, such as `{"note": "{{note}}"}`, is JSON-escaped, so quotes, backslashes and newlines in the value keep the body valid JSON. A placeholder outside a string, such as `{"count": {{count}}}`, is inserted as is. Other content types are filled in as is.
  - `headers` AgentWebhookHeaderPayload[], nullable
    - `name` string, required
    - `value` string, required
    - `kind` 'custom' | 'authorization_bearer' | 'authorization_basic'
  - `timeout_seconds` integer, nullable
  - `error_handling` 'passthrough' | 'hide', nullable
  - `mock_responses` AgentWebhookMockResponsePayload[], nullable
    - `name` string
    - `status_code` integer
    - `content_type` string
    - `body` string
  - `expects_response` boolean, nullable
  - `execution_mode` 'blocking' | 'fire_and_forget' | 'background', nullable

## Response `200`

Request fulfilled, document follows

- object
  - `tool_id` string, required
  - `workspace_id` string, required
  - `name` string, required
  - `description` string
  - `tool_type` 'webhook' | 'client', required
  - `method` 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', required
  - `url` string, required
  - `used_by` integer: How many agents reference this tool in their draft configuration.
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `arguments` AgentWebhookArgumentPayload[]: Older shape of `parameters`: each entry becomes a required string parameter. Mutually exclusive with `parameters` in one request. Reads return both, `arguments` being the string parameters of the schema.
    - `name` string, required
    - `description` string
  - `parameters` object, required: Call parameters as a JSON Schema object (draft 2020-12): `type: object` (filled in when omitted), `properties`, `required`. Standard meaning throughout: `required` means the key must be present, `type: ["string", "null"]` allows null, `minLength: 1` makes a string non-empty, `enum` and `pattern` constrain the value, `default` fills a key the model left out. Mutually exclusive with `arguments` in one request. A tool created with `parameters` starts in `parameter_mode: strict`.
  - `parameter_mode` 'legacy' | 'strict': Whether the agent runtime checks each call's arguments against `parameters` before running the tool. `legacy` (the default for tools created with `arguments`, and every tool from before this field existed): no check, the model's arguments run as sent. `strict` (the default for tools created with `parameters`): a call that does not satisfy the schema is refused and the model is told to ask the caller for the missing information, and the LLM provider's constrained decoding is turned on where the model supports it (OpenAI models and a custom OpenAI-compatible endpoint receive the tool with `strict: true`, Gemini on the platform's native channel runs validated function calling). Changing `parameters` never changes the mode, and the mode can be changed on its own.
  - `content_type` string, required
  - `body_template` string
  - `headers` PublicToolHeader[]
    - `name` string, required
    - `kind` 'custom' | 'authorization_bearer' | 'authorization_basic', required
    - `value` string, nullable: Header value; null for credential kinds (authorization_bearer / authorization_basic), which are write-only.
    - `has_secret` boolean: Whether a credential value is stored; the value itself is never returned.
  - `timeout_seconds` integer, required
  - `error_handling` 'passthrough' | 'hide', required
  - `mock_responses` AgentWebhookMockResponsePayload[]
    - `name` string
    - `status_code` integer
    - `content_type` string
    - `body` string
  - `expects_response` boolean
  - `execution_mode` 'blocking' | 'fire_and_forget' | 'background'

## Other responses

- `400`: Bad request syntax or unsupported method
- `401`: No permission -- see authorization schemes
- `404`: Nothing matches the given URI
- `422`
- `503`: The server cannot process the request due to a high load

## Changes

- **2026-11-03** `42ac421f7a12`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/fish/apis/fishaudio-openapi/changes/v1/agent/tools/:tool_id/patch.md)

---

[API](https://skmtc.dev/fish/apis/fishaudio-openapi.md) - [All operations](https://skmtc.dev/fish/apis/fishaudio-openapi/llms.txt) - [OpenAPI document](https://skmtc.dev/fish/apis/fishaudio-openapi/revisions/42ac421f7a12?raw)
