# Tool

> A tool definition.

`@kindgi/specs/tool.schema.json`, schema version 1.4.0.

A tool definition. Authored once; the runtime picks transport (native in-process for tools built into the runtime, MCP over the wire for cross-process / cross-org / third-party tools). Every tool declares its typed I/O, its context needs (typed DI), and its side-effects — enabling policy enforcement and parallel scheduling by the kernel.

- `id` (string, required): Unique tool identifier. Convention: '\<pack>.\<tool>' (e.g. 'acme.verify-citation') or a bare id for tools built into Kindgi.

- `description` (string, required): Human- and LLM-readable description of what this tool does. Load-bearing: this is what the LLM sees when deciding to call the tool.

- `version` (string, required)

- `input` (object, required): JSON Schema for the tool input. MUST validate under Draft 2020-12, except on an MCP server's tool (`transport: "mcp"`), whose schemas are in the dialect their `$schema` declares: draft-06, draft-07, 2019-09 or 2020-12.

- `output` (object, required): JSON Schema for the tool output. MUST validate under Draft 2020-12, except on an MCP server's tool (`transport: "mcp"`), whose schemas are in the dialect their `$schema` declares: draft-06, draft-07, 2019-09 or 2020-12.

- `needs` (array of [Need](https://docs.kindgi.com/v0.5.0/reference/schemas/tool.md#need)): Typed context requirements — named slots (e.g. `tenant`, `run`, `blob`, `memory:facts`) the runtime injects via `ToolContext`. Declarative: not checked when a flow is loaded. `needsSpec` is the typed, discriminated form.

- `effects` (array of [Effect](https://docs.kindgi.com/v0.5.0/reference/schemas/tool.md#effect)): Declared side-effects. Enables policy enforcement (can this tool run in this workspace?), safe parallelization (are two calls conflicting?), and causal provenance.

- `transport` (`"auto"` | `"native"` | `"mcp"`): Transport hint. 'auto' (default) lets the runtime pick native when possible, MCP otherwise. 'native' requires in-process execution. 'mcp' requires MCP execution. Deployment-time concern; authoring is unchanged.

- `mcpEndpoint` (string): If transport = 'mcp' (or resolved to MCP by 'auto'), the MCP endpoint URI. Format: 'mcp+stdio://\<command>', 'mcp+http\://\<url>', 'mcp+sse://\<url>'.

- `metadata` (map of any): Free-form annotations (author, docs URL, tags). Not interpreted by the kernel.

- `sandbox` (`"none"` | `"context-isolated"` | `"strict"`): Isolation posture the runtime enforces around the handler. Optional additive field.

- `mutating` (boolean): Semantic marker: `true` when this tool causes observable side effects (writes state, calls external APIs with mutations, sends messages). Read-only tools set `false`. Absent defaults to `true`. Consumed by the HITL default classifier — a read-only tool passes straight through, a mutating tool asks on first use. It also decides what runs together: calls to read-only tools that a model step asks for one after another run at the same time, up to 8 at once, unless the agent sets `parallelToolCalls: false`; a call to a mutating tool runs on its own, and so does a call to a read-only tool that pauses or declares connections, since it may wait.

- `needsApprovalWhenUnattended` (boolean): `true` when a person must say yes to every call of this tool in a run no person started (a schedule, a webhook, an event, a mail or a service account's key started it). In such a run an agent's call waits for a person's yes whatever the agent's approval rules say, and a flow's tool step that calls it is refused. A webhook trigger, a schedule or a mail trigger whose `toolsAllowedUnattended` names the tool (a project admin's to set) lifts that, in its own runs only. A tool that uses a person's connection, reads included, counts as declaring it, whatever this or `mutating` says. In a run a mail started, so does a tool that isn't `mutating: false`, and one that uses the run's own mailbox. Absent means `false`. Optional additive field.

- `pauses` (boolean): `true` when the tool may make its run wait for another system's answer: each call gets a wait token, hands its link to that system, and answers `pause`; the system's answer, valid against `output`, becomes the call's result. The run waits at most 24 days (24 hours by default) and fails the call when the time passes. Only a pack tool with a handler can pause: not one with a declarative `spec`, nor an MCP tool. Absent means `false`. Optional additive field.

- `resultIsOutsideData` (boolean): `true` when the tool's results are text from outside that nobody checked, such as a mail someone sent or a page a search found: an agent reads each result as data, not instructions, in this turn and in every later turn's history. It changes what the model is told, not what the tool may do. Absent means `false`. Optional additive field.

- `storesFiles` (boolean): `true` when the tool may store files it fetches, such as a mail's attachments, as files its run owns (schema-version 1.4.0, pack protocol 2.10.0). Each call's handler gets `files.store`: the runtime checks the bytes and answers a file value, which the tool returns in its result's top-level `files`, or why it stored nothing. At most 10 files a call. Only a pack tool with a handler can store files: not one with a declarative `spec`, nor an MCP tool. Absent means `false`. Optional additive field.

- `readsFiles` (boolean): `true` when the tool may read stored files' bytes, such as a PDF an agent was given, to parse it (schema-version 1.4.0, pack protocol 2.10.0). Each call's handler gets `files.read`, which answers the bytes of a file the call's run may be shown, by its file value's `artifactId`, or why there are none. Only a pack tool with a handler can read files: not one with a declarative `spec`, nor an MCP tool. Absent means `false`. Optional additive field.

- `limits` (object): Sandbox-enforced resource caps at dispatch. Optional additive field.

  - `memMB` (integer, required)
  - `cpuMs` (integer, required)

- `network` (one of the objects below): Network egress policy. Optional additive field. Discriminated on `kind`.

  - an object
    - `kind` (`"none"` | `"unrestricted"`, required)

  - an object

    - `kind` (`"allowlist"`, required)
    - `hosts` (array of string, required)

- `needsSpec` (object): Typed discriminated needs (env / secrets / config / capabilities / bindings / connections). Optional additive field.

  - `env` (map of object)
  - `secrets` (map of object)
  - `config` (map of object)
  - `capabilities` (array of string)
  - `bindings` (array of string)
  - `connections` (map of [ConnectionNeed](https://docs.kindgi.com/v0.5.0/reference/schemas/tool.md#connectionneed)): Accounts at other apps the tool acts with, by the tool's own name for each (`mail`). The runtime resolves them per call into the context's `connections`.

- `codeArtifactRef` (one of the objects below): Handler-artifact pointer. Discriminated on `kind`: `oci` is the deploy-pipeline shape (image + module path + artifactVersion); `filesystem` is the local-development shape — absolute host path at the pack's on-disk handler file. Production servers SHOULD reject `filesystem`.

  - an object

    - `kind` (`"oci"`, required)
    - `imageRef` (string, required)
    - `modulePath` (string, required)
    - `artifactVersion` (string, required)

  - an object

    - `kind` (`"filesystem"`, required)
    - `modulePath` (string, required)

- `spec` ([HttpToolSpec](https://docs.kindgi.com/v0.5.0/reference/schemas/tool.md#httptoolspec)): Declarative handler spec. Discriminated on `kind`; the framework's synthesizer registry maps kind → runtime handler. Mutually exclusive with an imperative handler at author time.

## Definitions

### Need

- `name` (string, required): The named context slot (e.g. 'tenant', 'db', 'run', 'provenance', 'memory:facts', 'blob').
- `optional` (boolean)

### Effect

- `kind` (`"reads"` | `"writes"` | `"deletes"` | `"network"` | `"spawns-run"` | `"emits-event"` | `"external-side-effect"` | `"sensitive-data-egress"`, required)
- `resource` (string): Resource identifier (e.g. 'memory:facts', 'blob:\*', 'external:api.example.com'). Used by the policy engine to authorize the effect.
- `notes` (string)

### ToolSecretRef

- `envName` (string, required)
- `name` (string, required)

### HttpHeaderSpec

- `name` (string, required)
- `value` (string, required)

### ConnectionNeed

- `app` (string, required): The app's entry id: `google`, `github`.
- `permissions` (array of string, required): The entry's permission keys the call needs: `gmail.send`.
- `as` (`"person"` | `"company"`, required): Whose connection: `person`, the run's person (the one it acts for, who started it or owns its trigger); `company`, the workspace's.

### HttpAuthSpec

One of:

- an object

  - `kind` (`"bearer"`, required)
  - `secretRef` ([ToolSecretRef](https://docs.kindgi.com/v0.5.0/reference/schemas/tool.md#toolsecretref), required)

- an object

  - `kind` (`"header"`, required)
  - `headerName` (string, required)
  - `secretRef` ([ToolSecretRef](https://docs.kindgi.com/v0.5.0/reference/schemas/tool.md#toolsecretref), required)

- an object: A connection the tool declares in `needsSpec.connections`, by its name there: sent as `Authorization: Bearer <access token>`.

  - `kind` (`"connection"`, required)
  - `connection` (string, required)

### HttpRequestBodySpec

One of:

- an object
  - `kind` (`"json-input"`, required)

- an object
  - `kind` (`"input-passthrough"`, required)

- an object

  - `kind` (`"text"`, required)
  - `template` (string, required)

### HttpToolSpec

Declarative HTTP-invocation spec. Attached to `ToolManifest.spec` under the discriminant `kind: 'http'`. The runtime `Tool.handler` is synthesized by the 'http' spec synthesizer to perform URL-template substitution, secret-ref resolution via `ToolContext.resolveSecret`, and the outbound fetch. All fields serialize cleanly to JSON.

- `kind` (`"http"`, required)

- `method` (`"GET"` | `"POST"` | `"PUT"` | `"PATCH"` | `"DELETE"`, required)

- `urlTemplate` (string, required): URL template with `{param}` placeholders substituted from the tool's input at invoke time.

- `headers` (array of [HttpHeaderSpec](https://docs.kindgi.com/v0.5.0/reference/schemas/tool.md#httpheaderspec))

- `authorization` ([HttpAuthSpec](https://docs.kindgi.com/v0.5.0/reference/schemas/tool.md#httpauthspec))

- `requestBody` ([HttpRequestBodySpec](https://docs.kindgi.com/v0.5.0/reference/schemas/tool.md#httprequestbodyspec))

- `timeoutMs` (integer): Wall-clock timeout in ms. Default 30000.

- `parseJson` (boolean): When true (default), the response body is parsed as JSON before returning to the invoker.

- `successStatus` (object)

  - `min` (integer, required)
  - `max` (integer, required)
