# @paradoc/ai-tools API

The framework-neutral Paradoc tool contract, with schemas, execute functions, and a registry client

Canonical URL: https://docs.paradoc.dev/ai-tools/api/

`@paradoc/ai-tools` is the contract every Paradoc AI adapter wraps. It has the ten tool definitions, their Zod input and output schemas, an execute function per tool, and a registry client. To start using it, see [Use another framework](/ai/other-frameworks).

```bash
npm install @paradoc/ai-tools
```

## Tool definitions

`toolDefinitions` maps each tool name to its definition:

```typescript
import { toolDefinitions } from "@paradoc/ai-tools"

const { name, description, input_schema, output_schema, execute } = toolDefinitions.render
```

| Key             | Description                                |
| --------------- | ------------------------------------------ |
| `name`          | The snake\_case tool name, same as the key |
| `description`   | Model-facing description                   |
| `input_schema`  | Zod schema for the input                   |
| `output_schema` | Zod schema for the output                  |
| `execute`       | `(input, config?) => Promise<output>`      |

`operationNames` lists the ten names in order: `get_registry`, `get_artifact`, `inspect_artifact`, `validate_artifact`, `validate_input`, `fill`, `get_fill_state`, `update_fill`, `render`, `extract`. The `OperationName` type is their union.

An adapter maps each definition to its framework's tool type. See [Write an adapter](/ai/other-frameworks#write-an-adapter) and the [Adapters](/ai-tools/adapters) reference.

## Execute functions

Each tool has an execute function. They take the tool's snake\_case input and an optional [`ParadocToolsConfig`](#configuration):

| Function                                  | Tool                                               |
| ----------------------------------------- | -------------------------------------------------- |
| `executeGetRegistry(input?, config?)`     | [`get_registry`](/ai-tools/get-registry)           |
| `executeGetArtifact(input, config?)`      | [`get_artifact`](/ai-tools/get-artifact)           |
| `executeInspectArtifact(input, config?)`  | [`inspect_artifact`](/ai-tools/inspect-artifact)   |
| `executeValidateArtifact(input, config?)` | [`validate_artifact`](/ai-tools/validate-artifact) |
| `executeValidateInput(input, config?)`    | [`validate_input`](/ai-tools/validate-input)       |
| `executeFill(input, config?)`             | [`fill`](/ai-tools/fill)                           |
| `executeGetFillState(input, config?)`     | [`get_fill_state`](/ai-tools/get-fill-state)       |
| `executeUpdateFill(input, config?)`       | [`update_fill`](/ai-tools/update-fill)             |
| `executeRender(input, config?)`           | [`render`](/ai-tools/render)                       |
| `executeExtract(input, config?)`          | [`extract`](/ai-tools/extract)                     |

The execute functions do not throw for tool failures. They return a result with an `error` object (`code`, `message`, and optional `path` and `retryable`).

An artifact read from a URL or a registry must carry the current dated `$schema`. An inline artifact may omit it, but one it declares must be current. Otherwise the error code is `missing-version`, `outdated-version`, or `unknown-version`, and the message names the current version and `paradoc migrate`. See [loading rules](/schemas#loading-rules).

The execute functions parse their input with the tool's Zod schema. Pass the snake\_case field names shown on each tool page. [Use another framework](/ai/other-frameworks#call-the-tools-from-your-code) has a full example.

## Resolving a source

`resolveSource(input, config?)` loads the artifact for a [source](/ai-tools#sources). It returns a `ResolvedSource`: `{ artifact, base_url?, artifact_url? }`. The tools use it internally; use it when an adapter needs the artifact itself.

## Request context

`createToolExecutionContext(options?)` makes a `ToolExecutionContext` that caches registry responses and carries an abort signal for one request or tool turn. Pass it as `config.context`. Options are `signal` and `maxCacheEntries` (default 32).

```typescript
import { createToolExecutionContext, executeGetArtifact } from "@paradoc/ai-tools"

const context = createToolExecutionContext({ signal: request.signal })

const result = await executeGetArtifact(
  { registry_url: "https://public.paradoc.dev", artifact_name: "pet-addendum" },
  { context },
)
```

Create a new context for each request. The package never shares a cache between requests, so cached data cannot cross users or credentials.

## Registry client

These helpers fetch from a Paradoc registry with the same URL and size checks the tools use:

| Export                                             | Description                                                                                                 |
| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `safeFetch`                                        | Fetch with URL validation, a size limit, a timeout, and validated redirects                                 |
| `validateFetchUrl`                                 | Check a URL against the fetch policy (HTTPS, local addresses, `approvedOrigins`)                            |
| `fetchRegistryIndex`, `fetchRegistryIndexResponse` | Fetch and parse `registry.json`                                                                             |
| `fetchRegistryItem`, `fetchRegistryItemResponse`   | Fetch one artifact from a registry                                                                          |
| `buildArtifactItemUrl`                             | Build an artifact URL from a registry URL and item                                                          |
| `resolveRelativeUrl`                               | Resolve an instruction or item path against a base URL. Layer files are read with `@paradoc/resolvers/http` |
| `bytesToBase64`, `bytesToText`                     | Encode fetched bytes                                                                                        |

## Model output

The adapters use these helpers to bound the copy of a result that goes to the model. An adapter for another framework uses them the same way.

| Export                                              | Description                                                                                                         |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `configForExecution(config, signal?)`               | Return a per-call config that joins `signal`, `context.signal`, and the framework's abort signal                    |
| `boundModelValue(output, maxBytes?)`                | Return `output` with its `content` cut to `maxBytes` and marked `truncated: true`. Other results return unchanged.  |
| `toModelOutput(output, maxBytes?)`                  | `boundModelValue` wrapped as `{ type: "json", value }`                                                              |
| `attachModelOutputSerialization(output, maxBytes?)` | Give `output` a `toJSON` that returns the bounded copy, for frameworks that serialize results with `JSON.stringify` |
| `truncateContent(content, encoding, maxBytes)`      | Cut text at a whole UTF-8 character, or base64 at a whole 4-character group                                         |
| `DEFAULT_MODEL_OUTPUT_MAX_BYTES`                    | 16,384                                                                                                              |

## Schemas and types

The package exports every input and output schema, such as `FillInputSchema` and `FillOutputSchema`, and the types inferred from them, such as `FillInput` and `FillOutput`. It also exports `SourceSchema` (the source union), `SourceOperationSchema`, `ToolErrorSchema`, `ValidationIssueSchema`, `FillTargetSchema` and `FillItemStateSchema` (the targets in a [`get_fill_state`](/ai-tools/get-fill-state) result), and the `ToolDefinitions` type.

## Configuration

Every execute function and every adapter accepts `ParadocToolsConfig`:

```typescript
paradocTools({
  defaultRegistryUrl: "https://public.paradoc.dev",
  fetch: customFetchWithAuth,
  approvedOrigins: ["https://public.paradoc.dev"],
  maxOutputBytes: 200_000,
})
```

| Option                  | Type                   | Description                                                                                                                  |
| ----------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `defaultRegistryUrl`    | `string`               | Registry used when a call omits `registry_url`. An explicit input always wins.                                               |
| `fetch`                 | `typeof fetch`         | Custom fetch for auth headers or test mocks                                                                                  |
| `allowLocalDevelopment` | `boolean`              | Allow loopback and private-network hosts, including over HTTP. Off by default; otherwise only public HTTPS URLs are fetched. |
| `approvedOrigins`       | `string[]`             | Origin allowlist for every registry, artifact, instruction, and layer request                                                |
| `maxRedirects`          | `number`               | Maximum validated redirects per request. Default `3`.                                                                        |
| `context`               | `ToolExecutionContext` | Request-scoped cache and signal. Create one per request with `createToolExecutionContext()`.                                 |
| `signal`                | `AbortSignal`          | Abort all work for the call                                                                                                  |
| `maxOutputBytes`        | `number`               | Maximum content bytes sent to the model; defaults to 16,384                                                                  |

`approvedOrigins` matches complete origins, including scheme and port. `allowLocalDevelopment` permits loopback and private hosts; plain HTTP remains limited to local hosts.

Every adapter combines the framework's abort signal with `signal` and `context.signal`, returns the complete result to application code, and bounds the model-facing copy with `maxOutputBytes`.
