---
url: 'https://adk.nht.io/api/@nhtio/adk/turn_runner/classes/TurnRunner.md'
description: >-
  Executes a single agent turn through paired input and output middleware
  pipelines.
---

# Class: TurnRunner

Defined in: [lib/turn\_runner.ts:102](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/turn_runner.ts#L102)

Executes a single agent turn through paired input and output middleware pipelines.

## Remarks

Construction validates `config` eagerly and throws [@nhtio/adk!E\_INVALID\_TURN\_RUNNER\_CONFIG](../../exceptions/variables/E_INVALID_TURN_RUNNER_CONFIG.md) if it
does not satisfy the schema — fail-fast so misconfiguration surfaces before any turn runs.

Each call to [TurnRunner.run](#run) threads a [@nhtio/adk!TurnContext](../../types/interfaces/TurnContext.md) through the input pipeline,
invokes the model, then threads the result through the output pipeline. Middleware on each side
can read and mutate the context for pre- and post-processing (e.g. message normalisation, tool
call dispatch, response filtering).

**Two event buses:**

* Functional bus (`on` / `off` / `once`): `message`, `thought`, `toolCall` — pipeline-affecting
  events that middleware raises throughout turn execution.
* Observability bus (`observe` / `unobserve` / `observeOnce`): `turnStart`, `turnEnd`,
  `turnGateOpen`, `turnGateClosed`, `error` — instrumentation-only events that monitor execution
  without participating in it.

Streaming content is surfaced via `message` and `thought` events; tool call lifecycle via
`toolCall`; non-fatal pipeline errors via the observability `error` event; gate lifecycle via
`turnGateOpen` and `turnGateClosed` — all throughout execution.

## Example

```ts
const runner = new TurnRunner({
  fetchMemoriesCallback: async (ctx) => memoryStore.query(ctx),
  fetchMessagesCallback: async (ctx) => messageStore.history(ctx),
  fetchThoughtsCallback: async (ctx) => thoughtStore.history(ctx),
  fetchToolCallsCallback: async (ctx) => toolCallStore.history(ctx),
});
// Functional bus — pipeline events
runner.on("message", (chunk) => process.stdout.write(chunk.aDelta));
// Observability bus — instrumentation
runner.observe("error", (err) => console.error(err.toString()));
runner.observe("turnStart", ({ turnId }) =>
  console.log("turn started", turnId),
);
runner.observe("turnGateOpen", (gate) => {
  if (gate.reason === "tool_approval") {
    gate.resolve(true); // approve immediately for this example
  }
});
await runner.run({
  turnAbortController: new AbortController(),
  systemPrompt: "You are a helpful assistant.",
  standingInstructions: [],
});
```

## Constructors

### Constructor

```ts
new TurnRunner(config: TurnRunnerConfig): TurnRunner;
```

Defined in: [lib/turn\_runner.ts:126](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/turn_runner.ts#L126)

#### Parameters

| Parameter | Type                                                    | Description                                                               |
| --------- | ------------------------------------------------------- | ------------------------------------------------------------------------- |
| `config`  | [`TurnRunnerConfig`](../interfaces/TurnRunnerConfig.md) | Construction-time configuration validated against turnRunnerConfigSchema. |

#### Returns

`TurnRunner`

#### Throws

[@nhtio/adk!E\_INVALID\_TURN\_RUNNER\_CONFIG](../../exceptions/variables/E_INVALID_TURN_RUNNER_CONFIG.md) when `config` does not satisfy the schema.

## Methods

### observe()

```ts
observe<K>(event: TurnObservabilityEvent<K>, listener: TurnObservabilityEventListener<K>): this;
```

Defined in: [lib/turn\_runner.ts:224](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/turn_runner.ts#L224)

Registers a persistent observability listener for `event`.

#### Type Parameters

| Type Parameter |
| -------------- |
| `K`            |

#### Parameters

| Parameter  | Type                                                                                         | Description                            |
| ---------- | -------------------------------------------------------------------------------------------- | -------------------------------------- |
| `event`    | [`TurnObservabilityEvent`](../type-aliases/TurnObservabilityEvent.md)<`K`>                 | The event to observe.                  |
| `listener` | [`TurnObservabilityEventListener`](../type-aliases/TurnObservabilityEventListener.md)<`K`> | The function to call on each emission. |

#### Returns

`this`

`this` for chaining.

#### Remarks

Use the observability bus (`observe` / `unobserve` / `observeOnce`) for instrumentation:
turn lifecycle, gate lifecycle, and non-fatal errors. Use the functional bus (`on` / `off` /
`once`) for pipeline-affecting events: `message`, `thought`, `toolCall`.

***

### observeOnce()

```ts
observeOnce<K>(event: TurnObservabilityEvent<K>, listener: TurnObservabilityEventListener<K>): this;
```

Defined in: [lib/turn\_runner.ts:237](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/turn_runner.ts#L237)

Registers a one-time observability listener for `event` that is automatically removed after
the first emission.

#### Type Parameters

| Type Parameter |
| -------------- |
| `K`            |

#### Parameters

| Parameter  | Type                                                                                         | Description                                |
| ---------- | -------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `event`    | [`TurnObservabilityEvent`](../type-aliases/TurnObservabilityEvent.md)<`K`>                 | The event to observe once.                 |
| `listener` | [`TurnObservabilityEventListener`](../type-aliases/TurnObservabilityEventListener.md)<`K`> | The function to call on the next emission. |

#### Returns

`this`

`this` for chaining.

***

### off()

```ts
off<K>(event: TurnEvent<K>, listener: TurnEventListener<K>): this;
```

Defined in: [lib/turn\_runner.ts:165](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/turn_runner.ts#L165)

Removes a previously registered functional listener for `event`.

#### Type Parameters

| Type Parameter |
| -------------- |
| `K`            |

#### Parameters

| Parameter  | Type                                                               | Description                      |
| ---------- | ------------------------------------------------------------------ | -------------------------------- |
| `event`    | [`TurnEvent`](../type-aliases/TurnEvent.md)<`K`>                 | The event to stop listening to.  |
| `listener` | [`TurnEventListener`](../type-aliases/TurnEventListener.md)<`K`> | The listener function to remove. |

#### Returns

`this`

`this` for chaining.

***

### on()

```ts
on<K>(event: TurnEvent<K>, listener: TurnEventListener<K>): this;
```

Defined in: [lib/turn\_runner.ts:177](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/turn_runner.ts#L177)

Registers a persistent functional listener for `event`.

#### Type Parameters

| Type Parameter |
| -------------- |
| `K`            |

#### Parameters

| Parameter  | Type                                                               | Description                            |
| ---------- | ------------------------------------------------------------------ | -------------------------------------- |
| `event`    | [`TurnEvent`](../type-aliases/TurnEvent.md)<`K`>                 | The event to listen to.                |
| `listener` | [`TurnEventListener`](../type-aliases/TurnEventListener.md)<`K`> | The function to call on each emission. |

#### Returns

`this`

`this` for chaining.

***

### once()

```ts
once<K>(event: TurnEvent<K>, listener: TurnEventListener<K>): this;
```

Defined in: [lib/turn\_runner.ts:190](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/turn_runner.ts#L190)

Registers a one-time functional listener for `event` that is automatically removed after the
first emission.

#### Type Parameters

| Type Parameter |
| -------------- |
| `K`            |

#### Parameters

| Parameter  | Type                                                               | Description                                |
| ---------- | ------------------------------------------------------------------ | ------------------------------------------ |
| `event`    | [`TurnEvent`](../type-aliases/TurnEvent.md)<`K`>                 | The event to listen to.                    |
| `listener` | [`TurnEventListener`](../type-aliases/TurnEventListener.md)<`K`> | The function to call on the next emission. |

#### Returns

`this`

`this` for chaining.

***

### run()

```ts
run(context: RawTurnContext): Promise<void>;
```

Defined in: [lib/turn\_runner.ts:265](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/turn_runner.ts#L265)

Executes a single agent turn against the provided raw context.

#### Parameters

| Parameter | Type                                                         | Description                                                                                                              |
| --------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| `context` | [`RawTurnContext`](../../types/interfaces/RawTurnContext.md) | Raw input validated and wrapped into a [@nhtio/adk!TurnContext](../../types/interfaces/TurnContext.md) before execution. |

#### Returns

`Promise`<`void`>

#### Remarks

Returns `Promise<void>` intentionally — all meaningful output surfaces via events, not return
values. Register listeners before calling `run`: observability events (`turnStart`, `turnEnd`)
bracket execution; functional events (`message`, `thought`, `toolCall`) fire throughout;
observability `error` carries non-fatal pipeline failures; `turnGateOpen` and `turnGateClosed`
fire when middleware suspends via `ctx.waitFor()`. Awaiting this method only tells you the
pipeline has finished, not what it produced.

Constructs a validated [@nhtio/adk!TurnContext](../../types/interfaces/TurnContext.md) from `context` (throwing
[@nhtio/adk!E\_INVALID\_TURN\_CONTEXT](../../exceptions/variables/E_INVALID_TURN_CONTEXT.md) on failure), then runs the input middleware pipeline.
Abort signals are silently swallowed.

#### Throws

[@nhtio/adk!E\_INVALID\_TURN\_CONTEXT](../../exceptions/variables/E_INVALID_TURN_CONTEXT.md) when `context` does not satisfy the schema.

***

### unobserve()

```ts
unobserve<K>(event: TurnObservabilityEvent<K>, listener: TurnObservabilityEventListener<K>): this;
```

Defined in: [lib/turn\_runner.ts:204](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/turn_runner.ts#L204)

Removes a previously registered observability listener for `event`.

#### Type Parameters

| Type Parameter |
| -------------- |
| `K`            |

#### Parameters

| Parameter  | Type                                                                                         | Description                      |
| ---------- | -------------------------------------------------------------------------------------------- | -------------------------------- |
| `event`    | [`TurnObservabilityEvent`](../type-aliases/TurnObservabilityEvent.md)<`K`>                 | The event to stop observing.     |
| `listener` | [`TurnObservabilityEventListener`](../type-aliases/TurnObservabilityEventListener.md)<`K`> | The listener function to remove. |

#### Returns

`this`

`this` for chaining.

***

### isTurnRunner()

```ts
static isTurnRunner(value: unknown): value is TurnRunner;
```

Defined in: [lib/turn\_runner.ts:112](https://github.com/NHTIO/ADK/blob/v1.20260605.0/src/lib/turn_runner.ts#L112)

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

#### Parameters

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

#### Returns

`value is TurnRunner`

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

#### Remarks

Uses [@nhtio/adk!isInstanceOf](../../guards/functions/isInstanceOf.md) for cross-realm safety.
