diff --git a/docs/tools/api/index.md b/docs/tools/api/index.md index dd872e23c..1c7ffb9ad 100644 --- a/docs/tools/api/index.md +++ b/docs/tools/api/index.md @@ -48,6 +48,16 @@ agents: ## Properties +The `api` toolset accepts the following toolset-level fields in addition to the `api_config` block: + +| Property | Type | Required | Description | +| ------------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `api_config` | object | ✓ | The HTTP tool definition. See the table below. | +| `timeout` | int | ✗ | HTTP client timeout in seconds (default: `30`). Applies to every call the generated tool makes. | +| `allow_private_ips` | boolean | ✗ | Opt in to dialling **non-public** IP addresses (loopback, RFC1918, link-local — including the cloud-metadata endpoint at `169.254.169.254` — multicast and the unspecified address). Set to `true` only when the configured endpoint legitimately targets internal services. See [Reaching internal services](#reaching-internal-services). | + +### `api_config` + | Property | Type | Required | Description | | --------------- | ------ | -------- | ------------------------------------------------ | | `name` | string | ✓ | Tool name (how the agent references it) | @@ -56,8 +66,8 @@ agents: | `instruction` | string | ✗ | Description shown to the agent | | `args` | object | ✗ | Parameter definitions (JSON Schema properties) | | `required` | array | ✗ | List of required parameter names | -| `headers` | object | ✗ | HTTP headers to include | -| `output_schema` | object | ✗ | JSON Schema for the response (for documentation) | +| `headers` | object | ✗ | HTTP headers to include. Values support `${env.VAR}` and `${headers.NAME}` placeholders (the latter forwards a header from the caller's incoming request, useful when docker agent is itself exposed as an HTTP server). | +| `output_schema` | object | ✗ | JSON Schema for the response. Used by MCP / Code Mode consumers; tool responses are still returned to the model as raw strings. | ## HTTP Methods @@ -120,7 +130,7 @@ Use `${param}` syntax to insert parameter values into URLs: endpoint: "https://api.example.com/users/${user_id}/posts/${post_id}" ``` -Parameter values are URL-encoded automatically. +Parameter values are inserted as strings by the template expansion. Add URL encoding in the template when needed (for example, `${encodeURIComponent(city)}`). ## Headers @@ -209,9 +219,30 @@ agents: - Only supports GET and POST methods - Response body is limited to 1MB -- 30 second timeout per request +- Default 30-second timeout per request (override with the `timeout` field) - Only HTTP and HTTPS URLs are supported - No support for file uploads or multipart forms +- By default, requests to non-public IP ranges (loopback, RFC1918, link-local, the cloud-metadata endpoint, multicast, the unspecified address) are refused at dial time — even when DNS for an otherwise-public host resolves there. Set `allow_private_ips: true` to disable that check. + +## Reaching internal services + +```yaml +toolsets: + - type: api + timeout: 60 + allow_private_ips: true + api_config: + name: get_local_status + method: GET + endpoint: "http://localhost:8080/health" + instruction: Check the local service health +``` + +
+
SSRF +
+

Setting allow_private_ips: true re-exposes the SSRF surface for this tool. Only enable it when the configured endpoint is a trusted internal service — a prompt-injected agent cannot redirect the call elsewhere because the endpoint is fixed in config, but redirects from the configured host can still reach unexpected places.

+
For Complex APIs diff --git a/docs/tools/fetch/index.md b/docs/tools/fetch/index.md index b7ba5bd6e..2638a5557 100644 --- a/docs/tools/fetch/index.md +++ b/docs/tools/fetch/index.md @@ -15,7 +15,7 @@ The fetch tool lets agents retrieve content from one or more HTTP/HTTPS URLs. It
GET only
-

The fetch tool does not support POST, PUT, DELETE or other methods, and does not expose request bodies or custom headers. To call REST endpoints with other verbs, use the API tool or an OpenAPI toolset.

+

The fetch tool does not support POST, PUT, DELETE or other methods, and does not expose request bodies or per-call custom headers (the toolset can still attach static credential headers to every request). To call REST endpoints with other verbs, use the API tool or an OpenAPI toolset.

@@ -34,6 +34,7 @@ toolsets: | `allowed_domains` | array[string] | _none_ | Allow-list of hosts the tool may fetch. When set, every URL whose host is **not** in the list is rejected before any network call is made. Mutually exclusive with `blocked_domains`. | | `blocked_domains` | array[string] | _none_ | Deny-list of hosts the tool must not fetch. URLs whose host matches one of these patterns are rejected before any network call (including `robots.txt`) is made. Mutually exclusive with `allowed_domains`. | | `allow_private_ips` | boolean | `false` | Opt in to dialling **non-public** IP addresses (loopback, RFC1918, link-local — including the cloud-metadata endpoint at `169.254.169.254` — multicast, and the unspecified address). Required to reach `localhost` / internal services. See [SSRF protection](#ssrf-protection-and-reaching-localhost) below. | +| `headers` | map[string]string | _none_ | Static HTTP headers attached to **every** request the toolset issues (including `robots.txt`). Values support `${env.VAR}` for secrets. Caller-supplied entries override the default `User-Agent` and the format-driven `Accept` header. Headers are stripped on cross-host redirects so credentials never leak to a third-party host. See [Custom headers](#custom-headers) below. | ### Domain matching @@ -64,6 +65,26 @@ toolsets: timeout: 60 ``` +### Custom headers + +Attach static headers — typically credentials — to every request. Values support `${env.VAR}` interpolation so secrets stay out of YAML, and headers are dropped on cross-host redirects so a redirect chain cannot leak them to a third-party host: + +```yaml +toolsets: + - type: fetch + allowed_domains: + - docs.internal.example.com + headers: + Authorization: "Bearer ${env.INTERNAL_DOCS_TOKEN}" + X-Internal-Client: "docker-agent" +``` + +
+
Pair credential headers with an allow-list +
+

When headers carries credentials (e.g. Authorization), set allowed_domains to the specific hosts that should receive them. Stdlib already strips a small allow-list (Authorization, Cookie, WWW-Authenticate) on cross-domain redirects, and the fetch tool additionally strips every operator-supplied header on cross-host redirects — but an allow-list is the strongest guarantee against accidental exfiltration.

+
+ ### Restrict to specific domains ```yaml diff --git a/docs/tools/openapi/index.md b/docs/tools/openapi/index.md index 9ce6e111e..f4abcd05d 100644 --- a/docs/tools/openapi/index.md +++ b/docs/tools/openapi/index.md @@ -33,12 +33,36 @@ toolsets: X-Custom-Header: "my-value" ``` +### Custom timeout + +Override the default 30-second HTTP timeout (applies both to fetching the spec and to the generated tool calls): + +```yaml +toolsets: + - type: openapi + url: "https://api.example.com/openapi.json" + timeout: 60 +``` + +### Reaching internal services + +By default the OpenAPI tool refuses connections to non-public IP addresses, blocking SSRF attempts even when DNS resolves an otherwise-public host to an internal range. Opt in with `allow_private_ips` when the spec or its `servers` entries legitimately target localhost or your internal network: + +```yaml +toolsets: + - type: openapi + url: "http://localhost:8080/openapi.json" + allow_private_ips: true +``` + ## Properties -| Property | Type | Required | Description | -| --------- | ----------------- | -------- | --------------------------------------------------------------------------- | -| `url` | string | ✓ | URL of the OpenAPI specification (JSON format) | -| `headers` | map[string]string | | Custom HTTP headers sent with every request. Values support `${env.VAR}` and `${headers.NAME}` placeholders. | +| Property | Type | Required | Description | +| ------------------- | ----------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `url` | string | ✓ | URL of the OpenAPI specification (JSON format). Supports `${env.VAR}` interpolation. | +| `headers` | map[string]string | ✗ | Custom HTTP headers sent with every request — both the spec fetch and every generated tool call. Values support `${env.VAR}` and `${headers.NAME}` placeholders (the latter forwards a header from the caller's incoming request when docker agent is exposed as a server). | +| `timeout` | int | ✗ | HTTP client timeout in seconds (default: `30`). Applies to both the spec fetch and the generated tools' requests. | +| `allow_private_ips` | boolean | ✗ | Opt in to dialling **non-public** IP addresses (loopback, RFC1918, link-local — including the cloud-metadata endpoint at `169.254.169.254` — multicast and the unspecified address). Set to `true` only when the spec or its servers legitimately target internal services. By default such addresses are refused at dial time, after DNS resolution, so DNS rebinding cannot bypass the check. | ## How it works