Class: ToolRegistry
Defined in: src/lib/classes/tool_registry.ts:51
A mutable, turn-scoped collection of @nhtio/adk!Tool 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 if a tool with the same name is already present — pass overwrite: true to replace it explicitly.
Tools can be hidden — registered and callable, but excluded from the default tool list rendered to the model. This is useful for discovery patterns where an agent has a tool that enumerates available tools, and the model picks one to call by name in a subsequent iteration. Hidden state is a property of the registry, not the tool: the same tool can be visible in one registry and hidden in another. See hide, visible, hidden.
Constructors
Constructor
new ToolRegistry(tools?: Tool<SpooledArtifact>[]): ToolRegistry;Defined in: src/lib/classes/tool_registry.ts:70
Parameters
| Parameter | Type | Description |
|---|---|---|
tools? | Tool<SpooledArtifact>[] | Optional initial tools. Insertion order is preserved. Duplicate names throw @nhtio/adk!E_TOOL_ALREADY_REGISTERED — ensure each tool has a unique name. |
Returns
ToolRegistry
Throws
@nhtio/adk!E_TOOL_ALREADY_REGISTERED when two tools in tools share a name.
Methods
[ENCODE_METHOD]()
ENCODE_METHOD: unknown;Defined in: src/lib/classes/tool_registry.ts:349
Serialise this ToolRegistry into an @nhtio/encoder snapshot.
Returns
unknown
A { tools, hidden } snapshot.
Remarks
Emits the live @nhtio/adk!Tool instances (the encoder recurses into each — so every tool's handler-closure caveat from Tool.[ENCODE_METHOD] applies) plus the hidden-set names. Both @nhtio/adk!Tool and @nhtio/adk!ArtifactTool entries round-trip to their correct subtype. Round-trips via ToolRegistry.[DECODE_METHOD].
all()
all(): Tool<SpooledArtifact>[];Defined in: src/lib/classes/tool_registry.ts:135
Returns a fresh array of all registered tools in insertion order.
Returns
Remarks
Includes both visible and hidden tools. Use visible to get only non-hidden tools, or hidden to get only hidden tools.
Since @nhtio/adk!Tool instances are immutable, no deep-cloning is needed.
bindContext()
bindContext(ctx: DispatchContext): () => void;Defined in: src/lib/classes/tool_registry.ts:267
Binds this registry to a @nhtio/adk!DispatchContext so that pruneEphemeral runs automatically when the context is acked.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctx | DispatchContext | 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 — 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.
ARTIFACT READERS ARE FORGED BY THE CORE. As of the core-forge change, the DispatchRunner forges artifact-reader tools from prior-turn SpooledArtifact results into ctx.tools (and calls ctx.tools.bindContext(ctx)) once per iteration, BEFORE the input pipeline — so a battery executor no longer forges or binds; it reads the already-forged ctx.tools for both representation (rendering the tool declarations) and resolution (looking up an incoming call by name). The lifecycle is unchanged: ephemeral readers are still pruned on ack, and the core re-forges each iteration (prune-then-forge) so the callId enum never goes stale.
bindContext remains the public seam for a CUSTOM consumer that forges its own ephemeral tools outside the core path. If you forge into a long-lived registry yourself, bind it (or prune manually) or the ephemeral tools accumulate and later forgeTools(ctx) calls see a stale callId enum. The pattern for a hand-rolled forge is:
// Custom forge (the core already does this for artifact readers on ctx.tools):
const forged = SpooledArtifact.forgeTools(ctx);
for (const tool of forged.all()) ctx.tools.register(tool, true);
ctx.tools.bindContext(ctx); // prune the ephemeral readers when the dispatch acksSee
clearHidden()
clearHidden(): void;Defined in: src/lib/classes/tool_registry.ts:209
Unhides every tool in the registry.
Returns
void
get()
get(name: string):
| Tool<SpooledArtifact>
| undefined;Defined in: src/lib/classes/tool_registry.ts:113
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<SpooledArtifact> | undefined
has()
has(name: string): boolean;Defined in: src/lib/classes/tool_registry.ts:122
Returns true if a tool with the given name is registered.
Parameters
| Parameter | Type | Description |
|---|---|---|
name | string | The tool name to test. |
Returns
boolean
hidden()
hidden(): Tool<SpooledArtifact>[];Defined in: src/lib/classes/tool_registry.ts:158
Returns a fresh array of registered tools that are hidden, in insertion order.
Returns
Remarks
The converse of visible. Useful for discovery tools that enumerate all available tools, and for propagating hidden state across merge.
hide()
hide(...names: string[]): void;Defined in: src/lib/classes/tool_registry.ts:172
Marks one or more registered tools as hidden.
Parameters
| Parameter | Type | Description |
|---|---|---|
...names | string[] | One or more tool names to hide. |
Returns
void
Remarks
Hidden tools remain registered and callable via get, but are excluded from visible (and therefore from the LLM tool list). No-ops for any name that is not currently registered — the end result (the tool is not visible) matches the intent.
pruneEphemeral()
pruneEphemeral(): void;Defined in: src/lib/classes/tool_registry.ts:222
Removes every tool whose @nhtio/adk!Tool.ephemeral flag is true.
Returns
void
Remarks
Also removes pruned tool names from the hidden set. Synchronous and idempotent — calling it twice in a row is a no-op the second time. The canonical caller is ToolRegistry.bindContext, which schedules this method to run at @nhtio/adk!DispatchContext.ack. Non-ephemeral tools are left untouched.
register()
register(tool: Tool, overwrite?: boolean): void;Defined in: src/lib/classes/tool_registry.ts:87
Adds a tool to the registry.
Parameters
| Parameter | Type | Description |
|---|---|---|
tool | Tool | 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 when a tool with the same name is already registered and overwrite is not true.
setHidden()
setHidden(...names: string[]): void;Defined in: src/lib/classes/tool_registry.ts:202
Replaces the entire hidden set with the given tool names.
Parameters
| Parameter | Type | Description |
|---|---|---|
...names | string[] | The complete set of tool names to hide. |
Returns
void
Remarks
Any previously hidden tool not in names becomes visible. Names that are not registered are silently ignored — they are added to the set but have no effect until a tool with that name is registered.
unhide()
unhide(...names: string[]): void;Defined in: src/lib/classes/tool_registry.ts:186
Unmarks one or more tools as hidden, making them visible again.
Parameters
| Parameter | Type | Description |
|---|---|---|
...names | string[] | One or more tool names to unhide. |
Returns
void
Remarks
No-ops for any name that is not currently hidden.
unregister()
unregister(name: string): void;Defined in: src/lib/classes/tool_registry.ts:103
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
Also removes the name from the hidden set if present. No-ops if no tool with that name is registered.
visible()
visible(): Tool<SpooledArtifact>[];Defined in: src/lib/classes/tool_registry.ts:147
Returns a fresh array of registered tools that are not hidden, in insertion order.
Returns
Remarks
This is the accessor LLM batteries should use when building the tool list for the model. Hidden tools are still callable (they resolve via get) but are excluded from the rendered tool definitions.
[DECODE_METHOD]()
static DECODE_METHOD: ToolRegistry;Defined in: src/lib/classes/tool_registry.ts:362
Reconstruct a ToolRegistry from a ToolRegistry.[ENCODE_METHOD] snapshot.
Parameters
| Parameter | Type | Description |
|---|---|---|
data | unknown | The snapshot produced by ToolRegistry.[ENCODE_METHOD]. |
Returns
ToolRegistry
A fresh ToolRegistry with the same tools and hidden set.
isToolRegistry()
static isToolRegistry(value: unknown): value is ToolRegistry;Defined in: src/lib/classes/tool_registry.ts:61
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()
static merge(registries: ToolRegistry[], options?: MergeOptions): ToolRegistry;Defined in: src/lib/classes/tool_registry.ts:299
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 | 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 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-leveloptions.onCollision.
The merge-level options.onCollision defaults to 'throw', which mirrors 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.
Hidden state is also propagated: a tool that is hidden in any source registry remains hidden in the merged result, provided it survives collision resolution.
Throws
@nhtio/adk!E_TOOL_ALREADY_REGISTERED when the resolved collision policy is 'throw' and a collision occurs.