---
url: >-
  https://adk.nht.io/api/@nhtio/adk/batteries/orchestration/templates/functions/instantiateTemplate.md
---

# Function: instantiateTemplate()

```ts
function instantiateTemplate(
  store: PlanStore,
  tpl: PlanTemplate,
  args: Record<string, EncodableValue>,
  actorId: string,
): Promise<InstantiateResult>;
```

Defined in: [src/batteries/orchestration/templates.ts:437](https://github.com/NHTIO/ADK/blob/v1.20260906.0/src/src/batteries/orchestration/templates.ts#L437)

Instantiate a template into a fresh, ordinary `editable` plan.

## Parameters

| Parameter | Type                                                                                                                                                                    | Description                                                                   |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `store`   | [`PlanStore`](../../interfaces/PlanStore.md)                                                                                                                            | The plan store to write into.                                                 |
| `tpl`     | [`PlanTemplate`](../../types/interfaces/PlanTemplate.md)                                                                                                                | The registered template to materialise.                                       |
| `args`    | [`Record`](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type)<`string`, [`EncodableValue`](../../types/type-aliases/EncodableValue.md)> | The concrete values, keyed by declared param `path`, to substitute for holes. |
| `actorId` | `string`                                                                                                                                                                | The identity under which the minted ops are authored.                         |

## Returns

`Promise`<[`InstantiateResult`](../../types/type-aliases/InstantiateResult.md)>

The instantiation result.

## Remarks

A template holds **op inputs without identity**: a `PlanOp` requires `opId`/`actorId`/`lamport`/
`at`, and no static literal can carry those — the same reason bounds are a fold seed rather than
an implied op. So instantiation **mints** that identity here, under the passed `actorId`, with a
monotonic lamport.

The steps, in order:

1. **Validate `args` against `params`** — types (plus `maxBytes` on strings) and enum
   membership. On failure it returns `{ok: false, reason: 'invalid_args', detail}` naming the
   offending param and what was expected, rather than minting a broken plan.
2. **`store.createPlan(planId, {provenance: {kind: 'template', template: tpl.id, args}})`** — the
   provenance is persisted by the store and returned by `readProvenance`, for the renderer and
   for audit. It is **not** a taint mechanism (see the module TSDoc).
3. **Substitute every `ParamRef`** with the corresponding argument value, then append
   `add_node` / `add_edge` / `set_bounds` ops.

The result is an **ordinary `editable` plan**: no inherited approval, no special state, nothing
downstream needs to know it came from a template. Two instantiations of one template yield
independent plans with different ids and digests.

`planId` is minted (not a parameter), because a fresh plan needs a fresh id — a caller does not
pre-choose one. If the mint races a duplicate, an error is thrown rather than returning a broken
or mislabelled result.
