> ## Documentation Index
> Fetch the complete documentation index at: https://docs.avocadostudio.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Native Tools

> Tool contract and onboarding flow for connecting external services (PIM, DAM, search, AI image generation) to the AI planner.

This page is for the developer connecting an external service (a PIM, a DAM, a search index) to the AI planner as a tool. It defines the tool contract and how to register one. See [How It Works](/how-it-works) for how tools fit into the editing pipeline.

## Scope

* Provider path: the Anthropic and Gemini planners offer registered tools to the model. The OpenAI planner does not call tools today.
* Built-in tools:
  * `unsplash.search` — licensed photo search (see schema below). Registered by default.
  * `image.generate` — AI image generation via OpenAI (`gpt-image-1-mini` for draft, `gpt-image-2` for final) or Google Gemini (`gemini-3.1-flash-lite-image`). Registered when `OPENAI_API_KEY` or `GOOGLE_GENAI_API_KEY` is set. Full reference: [Asset Manager & AI Images](/features/asset-picker#imagegenerate-tool-chat-pipeline-path).
  * `gdrive.browse` — images from a Google Drive folder. Registered when `GOOGLE_DRIVE_FOLDER_ID` is set.
* The standalone server registers the built-ins at startup. In library mode they are opt-in: `createOrchestrator({ builtinTools: true })` for the same env-gated defaults, or a subset such as `builtinTools: ["unsplash-search"]`.

## Internal Tool Contract

Every tool is registered with a `ToolManifest`:

* `name`: unique id (for example `unsplash.search`, `pim.getProduct`)
* `description`: natural-language purpose
* `inputSchema`: JSON Schema for tool input
* `outputSchema`: JSON Schema for tool output
* `capability`: `read` or `write`
* `timeoutMs`: per-call timeout
* `retryPolicy`: `{ maxAttempts, backoffMs? }`
* `idempotent`: whether identical calls can be replayed safely

Execution context passed to tools:

* `siteId`
* `sessionId`
* `userId` (optional)
* `traceId`
* `plannerProvider`

Result envelope returned by runtime:

* `ok`
* `data` (on success)
* `error` `{ code, message, retryable }` (on failure)
* `latencyMs`
* `attempts`

## Default Governance Policy

* Read tools auto-run.
* Write tools require approval (runtime blocks direct auto execution).

## Anthropic Adapter Behavior

Planner exposes tools as Anthropic `tools[]` with `input_schema`.
The planner loop supports:

1. model requests tool call (`tool_use`)
2. orchestrator executes tool server-side
3. orchestrator returns `tool_result`
4. model continues until `submit_edit_plan`

`submit_edit_plan` is still validated by existing normalizer + `editPlanSchema`.

## Unsplash Tool

`unsplash.search` input:

```json theme={null}
{ "query": "mountain sunset", "limit": 3 }
```

`unsplash.search` output:

```json theme={null}
{
  "items": [
    {
      "id": "...",
      "imageUrl": "https://...",
      "thumbUrl": "https://...",
      "alt": "...",
      "author": "Unsplash",
      "sourceUrl": "https://..."
    }
  ]
}
```

Photos served via `unsplash.search` are covered by the
[Unsplash License](https://unsplash.com/license). `author` and `sourceUrl`
are returned so adopters can render photographer + Unsplash attribution
alongside each used image. See
[Asset Manager & AI Images → Unsplash: licensing & attribution](/features/asset-picker#unsplash-licensing-attribution)
for the full rules (attribution, prohibited uses, download tracking).

## Registering a remote tool

Set `ORCHESTRATOR_TOOL_MANIFEST_PATH` to a JSON file. The orchestrator reads it once, at startup, in both the standalone server and library mode. There is no registration endpoint.

```json theme={null}
{
  "tools": [
    {
      "manifest": { "name": "dam.searchAssets", "description": "...", "inputSchema": {"type":"object"}, "outputSchema": {"type":"object"}, "capability": "read", "timeoutMs": 5000, "retryPolicy": {"maxAttempts": 2}, "idempotent": true },
      "endpoint": "https://vendor.example.com/site-editor/tools/dam/searchAssets",
      "staticHeaders": { "x-api-key": "***" }
    }
  ]
}
```

## Remote Tool HTTP Contract

Orchestrator calls remote endpoints with:

```json theme={null}
{
  "toolName": "pim.getProduct",
  "arguments": { "sku": "SKU-123" },
  "context": {
    "siteId": "...",
    "sessionId": "...",
    "userId": "...",
    "traceId": "...",
    "plannerProvider": "anthropic"
  }
}
```

Expected response:

```json theme={null}
{ "data": { "...": "..." } }
```

On non-2xx responses, runtime returns normalized tool error to the model loop.

A missing file is logged as a warning and skipped, and a file that does not parse is logged as an error; in both cases the orchestrator starts with no remote tools. Check the startup log for `Loaded remote tool registrations` and its `count`.

## PIM Skeleton Example

* Tool name: `pim.getProduct`
* Input schema: `{ sku: string }`
* Output schema: `{ sku: string, title: string, description?: string, imageUrl?: string, price?: string }`
* Capability: `read`

## DAM Skeleton Example

* Tool name: `dam.searchAssets`
* Input schema: `{ query: string, limit?: integer }`
* Output schema: `{ items: [{ id: string, url: string, alt?: string, mimeType?: string }] }`
* Capability: `read`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.