# Runtime Guide

The `Runtime` orchestrates multi-agent conversations, manages session state, and streams output events.

## Core Responsibilities

- Route messages to the active agent
- Maintain session history and collected state
- Emit stream parts for text, tools, handoffs, and lifecycle events
- Apply guardrails, processors, and stop conditions

## Stream Events

`Runtime.stream(...)` yields `HarnessStreamPart` items. Typical UI usage only renders `text-delta`.

Common types:
- `text-delta`
- `tool-call`, `tool-result`, `tool-error`
- `handoff`
- `node-enter`, `flow-transition`, `flow-end`
- `custom` (flow/runtime emitted app events)
- `agent-start`, `agent-end`
- `turn-end`, `done`, `error`

Internal events can expose operational details. Treat them as privileged data.

## Stream Callback (Persistence Defaults)

Use `streamCallback` when sending runtime events to file/webhook/DB/queue sinks.

Default behavior is message-oriented:
- emits: `input`, `done`, `error`, `tripwire`, `tool-call`, `tool-result`, `tool-error`, `flow-transition`, `handoff`
- does not emit `text-delta` tokens unless enabled
- attaches final assistant text as `fullText` on terminal events
- if no sink is configured, adapter is a no-op

```ts
import { createFunctionStreamSink } from '@ariaflowagents/core';

const runtime = new Runtime({
  agents,
  defaultAgentId: 'triage',
  streamCallback: {
    sinks: [createFunctionStreamSink(async payload => writeToDb(payload))],
    eventMode: 'message',
    emitToolEvents: true,
    emitTransitionEvents: true,
    emitTextDeltas: false,
    emitFinalText: true,
  },
});
```

To include token deltas:

```ts
streamCallback: {
  sinks: [...],
  eventMode: 'all',
  emitTextDeltas: true,
}
```

## Session Semantics

- Sessions are keyed by `sessionId` and persisted via a `SessionStore`.
- The runtime tracks `activeAgentId`, `currentAgent`, and `handoffHistory`.
- Flow agents snapshot structured progress into `session.workingMemory.flowStateByAgent[agentId]`
  so other agents can see latest `currentNode` and `collectedData` after handoffs.
- Runtime stores replay-oriented turn events in `session.workingMemory.runtimeEventLog`
  (`user`, `assistant_final`, `tool_call`, `tool_result`, `tool_error`, `transition`).
- `contextManager` can compact history before each turn.
- `contextManager.beforeTurn(...)` can be synchronous or asynchronous.

## Prompt Memory Hygiene

To prevent internal runtime state from leaking into the model's context window:
- **Filtering**: Keys like `runtimeEventLog` are automatically redacted from the prompt.
- **Allowlisting**: Individual agents can specify `promptMemoryAllowlist: string[]` to restrict which piece of working memory they can "see".

```ts
const agent = {
  id: 'billing',
  promptMemoryAllowlist: ['invoice_status', 'billing_address']
};
```

## Durability Hardening

Runtime checkpoints session state automatically on critical events:
- `tool-result`
- `tool-error`
- `flow-transition`
- handoff state updates (after `activeAgentId`/`currentAgent` mutation)

For external side effects, tools receive a stable `idempotencyKey` in
`options.experimental_context` so downstream systems can de-duplicate writes.

## Fail-Closed Operations

Critical tool failures block the "success" path. If a tool fails:
1. The assistant's generated response is suppressed.
2. A `failure-recovery` event is emitted.
3. The turn ends with an error status to prevent inconsistent state.

## Routing & Handoffs

- `TriageAgent` can hand off to specialists.
- Production default: non-triage agents only get the handoff tool if `canHandoffTo` is set.

```ts
const support: AgentConfig = {
  id: 'support',
  type: 'llm',
  systemPrompt: 'General support',
  model,
  canHandoffTo: ['billing', 'booking'],
};
```

## Runtime Configuration

```ts
const runtime = new Runtime({
  agents,
  defaultAgentId: 'triage',
  defaultModel,
  maxSteps: 20,
  maxHandoffs: 10,
  alwaysRouteThroughTriage: true,
  triageAgentId: 'triage',
  contextManager,
  sessionStore,
  inputProcessors,
  outputProcessors,
  outputProcessorMode: 'stream',
  outputRedaction: [
    { pattern: /\b\d{16}\b/, replacement: '[redacted]' },
  ],
  hooks: {
    onStreamPart: async (ctx, part) => {
      if (part.type === 'error') console.error(part.error);
    },
  },
});
```

## Hooks

Use hooks for logging, metrics, and audit trails without polluting prompts.

```ts
const runtime = new Runtime({
  agents,
  defaultAgentId: 'triage',
  hooks: loggingHooks(),
});
```

## Abort & Interrupt

`Runtime.abortSession(sessionId)` cancels an in-flight turn and emits `interrupted`.
`Runtime.stream({ abortSignal })` also propagates cancellation into model/tool calls.
