---
url: 'https://adk.nht.io/api/@nhtio/adk/forge/classes/ToolRegistry.md'
description: 'A mutable, turn-scoped collection of {@link @nhtio/adk!Tool} instances.'
---

# Class: ToolRegistry

Defined in: [lib/classes/tool\_registry.ts:43](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L43)

A mutable, turn-scoped collection of [@nhtio/adk!Tool](Tool.md) instances.

## Remarks

Each `TurnRunner.run()` call constructs a fresh `ToolRegistry` from the runner's configured
baseline tools, so middleware edits are isolated to the current turn and cannot bleed across
concurrent or subsequent turns.

`Tool` instances are immutable, so `all()` returns a fresh array without deep-cloning.

`register()` throws [@nhtio/adk!E\_TOOL\_ALREADY\_REGISTERED](../../exceptions/variables/E_TOOL_ALREADY_REGISTERED.md) if a tool with the same name is already
present — pass `overwrite: true` to replace it explicitly.

## Constructors

### Constructor

```ts
new ToolRegistry(tools?: Tool<SpooledArtifact>[]): ToolRegistry;
```

Defined in: [lib/classes/tool\_registry.ts:61](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L61)

#### Parameters

| Parameter | Type                                                                                          | Description                                                                                                                                                                                                       |
| --------- | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tools?`  | [`Tool`](Tool.md)<[`SpooledArtifact`](../../spooled_artifact/classes/SpooledArtifact.md)>\[] | Optional initial tools. Insertion order is preserved. Duplicate names throw [@nhtio/adk!E\_TOOL\_ALREADY\_REGISTERED](../../exceptions/variables/E_TOOL_ALREADY_REGISTERED.md) — ensure each tool has a unique name. |

#### Returns

`ToolRegistry`

#### Throws

[@nhtio/adk!E\_TOOL\_ALREADY\_REGISTERED](../../exceptions/variables/E_TOOL_ALREADY_REGISTERED.md) when two tools in `tools` share a name.

## Methods

### all()

```ts
all(): Tool<SpooledArtifact>[];
```

Defined in: [lib/classes/tool\_registry.ts:120](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L120)

Returns a fresh array of all registered tools in insertion order.

#### Returns

[`Tool`](Tool.md)<[`SpooledArtifact`](../../spooled_artifact/classes/SpooledArtifact.md)>\[]

#### Remarks

Since [@nhtio/adk!Tool](Tool.md) instances are immutable, no deep-cloning is needed.

***

### bindContext()

```ts
bindContext(ctx: DispatchContext): () => void;
```

Defined in: [lib/classes/tool\_registry.ts:171](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L171)

Binds this registry to a [@nhtio/adk!DispatchContext](../../types/interfaces/DispatchContext.md) so that [pruneEphemeral](#pruneephemeral) runs
automatically when the context is acked.

#### Parameters

| Parameter | Type                                                           | Description                                                     |
| --------- | -------------------------------------------------------------- | --------------------------------------------------------------- |
| `ctx`     | [`DispatchContext`](../../types/interfaces/DispatchContext.md) | The execution context whose `ack` event should trigger pruning. |

#### Returns

An unsubscribe function — calling it before `ctx.ack()` prevents pruning. Rarely
useful outside of tests.

() => `void`

#### Remarks

The handler does NOT fire on [@nhtio/adk!DispatchContext.nack](../../types/interfaces/DispatchContext.md#nack) — failed executor runs leave
any forged tools in place so the consumer can inspect what was registered when debugging the
failure. Subscriptions are short-lived and die with the context regardless.

Forgetting this call after merging in `Subclass.forgeTools(ctx)` output means ephemeral tools
accumulate across executor invocations, and subsequent `forgeTools(ctx)` calls in later
iterations will see a stale `callId` enum that excludes new tool calls. The plan-documented
pattern is:

```ts
const executor: DispatchExecutorFn = async (ctx) => {
  const forged = SpooledArtifact.forgeTools(ctx)
  const merged = ToolRegistry.merge([main, forged])
  main.bindContext(ctx)
  const result = await llm.invoke({ tools: merged.all(), ... })
  ctx.ack()
}
```

#### See

* [@nhtio/adk!SpooledArtifact.forgeTools](../../spooled_artifact/classes/SpooledArtifact.md#forgetools)
* [@nhtio/adk!DispatchContext.onAck](../../types/interfaces/DispatchContext.md#onack)

***

### get()

```ts
get(name: string):
  | Tool<SpooledArtifact>
  | undefined;
```

Defined in: [lib/classes/tool\_registry.ts:101](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L101)

Returns the tool registered under `name`, or `undefined` if not present.

#### Parameters

| Parameter | Type     | Description               |
| --------- | -------- | ------------------------- |
| `name`    | `string` | The tool name to look up. |

#### Returns

| [`Tool`](Tool.md)<[`SpooledArtifact`](../../spooled_artifact/classes/SpooledArtifact.md)>
| `undefined`

***

### has()

```ts
has(name: string): boolean;
```

Defined in: [lib/classes/tool\_registry.ts:110](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L110)

Returns `true` if a tool with the given name is registered.

#### Parameters

| Parameter | Type     | Description            |
| --------- | -------- | ---------------------- |
| `name`    | `string` | The tool name to test. |

#### Returns

`boolean`

***

### pruneEphemeral()

```ts
pruneEphemeral(): void;
```

Defined in: [lib/classes/tool\_registry.ts:132](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L132)

Removes every tool whose [@nhtio/adk!Tool.ephemeral](Tool.md#property-ephemeral) flag is `true`.

#### Returns

`void`

#### Remarks

Synchronous and idempotent — calling it twice in a row is a no-op the second time. The
canonical caller is [ToolRegistry.bindContext](#bindcontext), which schedules this method to run
at [@nhtio/adk!DispatchContext.ack](../../types/interfaces/DispatchContext.md#ack). Non-ephemeral tools are left untouched.

***

### register()

```ts
register(tool: Tool, overwrite?: boolean): void;
```

Defined in: [lib/classes/tool\_registry.ts:77](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L77)

Adds a tool to the registry.

#### Parameters

| Parameter    | Type              | Description                                                                              |
| ------------ | ----------------- | ---------------------------------------------------------------------------------------- |
| `tool`       | [`Tool`](Tool.md) | The tool to register.                                                                    |
| `overwrite?` | `boolean`         | When `true`, silently replaces an existing tool with the same name. Defaults to `false`. |

#### Returns

`void`

#### Throws

[@nhtio/adk!E\_TOOL\_ALREADY\_REGISTERED](../../exceptions/variables/E_TOOL_ALREADY_REGISTERED.md) when a tool with the same name is already registered
and `overwrite` is not `true`.

***

### unregister()

```ts
unregister(name: string): void;
```

Defined in: [lib/classes/tool\_registry.ts:92](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L92)

Removes the tool with the given name from the registry.

#### Parameters

| Parameter | Type     | Description                     |
| --------- | -------- | ------------------------------- |
| `name`    | `string` | The name of the tool to remove. |

#### Returns

`void`

#### Remarks

No-ops if no tool with that name is registered.

***

### isToolRegistry()

```ts
static isToolRegistry(value: unknown): value is ToolRegistry;
```

Defined in: [lib/classes/tool\_registry.ts:52](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L52)

Returns `true` if `value` is a ToolRegistry instance.

#### Parameters

| Parameter | Type      | Description        |
| --------- | --------- | ------------------ |
| `value`   | `unknown` | The value to test. |

#### Returns

`value is ToolRegistry`

`true` when `value` is a ToolRegistry instance.

***

### merge()

```ts
static merge(registries: ToolRegistry[], options?: MergeOptions): ToolRegistry;
```

Defined in: [lib/classes/tool\_registry.ts:200](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/classes/tool_registry.ts#L200)

Combines multiple ToolRegistry instances into a fresh registry without mutating any
input.

#### Parameters

| Parameter    | Type                                                      | Description                                                           |
| ------------ | --------------------------------------------------------- | --------------------------------------------------------------------- |
| `registries` | `ToolRegistry`\[]                                          | Registries to merge, in priority order (left-to-right insertion).     |
| `options?`   | [`MergeOptions`](../../common/interfaces/MergeOptions.md) | Merge-level collision policy. Defaults to `{ onCollision: 'throw' }`. |

#### Returns

`ToolRegistry`

A fresh ToolRegistry containing the resolved union of all inputs.

#### Remarks

Iteration is left-to-right across `registries` and then in each registry's insertion order.
Collisions are resolved by consulting the **incoming** tool's [@nhtio/adk!Tool.onCollision](Tool.md#property-oncollision) first:

* `'replace'` (per-tool): the incoming tool wins, replacing the existing entry.
* `'keep'` (per-tool): the existing entry wins; the incoming tool is dropped.
* `'throw'` (per-tool, the default): fall back to the merge-level `options.onCollision`.

The merge-level `options.onCollision` defaults to `'throw'`, which mirrors [register](#register).

The result is a brand-new registry; no input is mutated and no event subscription is
propagated. Each `Tool`'s `ephemeral` flag carries through unchanged — the flag lives on the
tool, not the registry, so `bindContext(ctx)` on the merged registry will prune the forged
tools as expected.

#### Throws

[@nhtio/adk!E\_TOOL\_ALREADY\_REGISTERED](../../exceptions/variables/E_TOOL_ALREADY_REGISTERED.md) when the resolved collision policy is `'throw'`
and a collision occurs.
