Skip to content

Conversations and interaction

Conversation state, snapshots, stores, and projected events are portable contracts. Execution is explicit through InteractionSession, which requires a prepared definition and an injected AgentRunner.

ts
import type { ConversationEvent } from "@geekist/llm-core/conversation";
import { createInteractionSession } from "@geekist/llm-core/interaction";
import type { CreateInteractionSessionOptions } from "@geekist/llm-core/interaction";

declare const options: CreateInteractionSessionOptions;
declare const render: (event: ConversationEvent) => void;

const session = createInteractionSession(options);
const projection = await session.load();

for (const event of projection.value.projection.events) {
  render(event);
}
ts
import { createInteractionSession } from "@geekist/llm-core/interaction";
import { createAiSdkUiProjectionMapper } from "@geekist/llm-core/adapters/ai-sdk-ui";
import type {
  ConversationStore,
  InteractionSessionIdentityPort,
} from "@geekist/llm-core/interaction";
import type { AgentRunner, PreparedAgentDefinition } from "@geekist/llm-core/agent/runtime";
import type { ConversationId, InvocationContext } from "@geekist/llm-core/contracts";
import type { AiSdkUiProjectionChunk } from "@geekist/llm-core/adapters/ai-sdk-ui";

declare const conversationId: ConversationId;
declare const agent: PreparedAgentDefinition;
declare const runner: AgentRunner;
declare const store: ConversationStore;
declare const identity: InteractionSessionIdentityPort;
declare const invocationContext: InvocationContext;
declare const uiStream: {
  write(chunk: AiSdkUiProjectionChunk): Promise<void>;
};

const session = createInteractionSession({
  conversationId,
  agent,
  runner,
  store,
  identity,
});
const interactionRun = await session.send({
  input: { prompt: "hello" },
  invocationContext,
});
const project = createAiSdkUiProjectionMapper();

for await (const event of interactionRun.events()) {
  for (const chunk of project(event)) {
    await uiStream.write(chunk);
  }
}

await interactionRun.result();

The session never constructs a runner. It reserves conversation state before execution, sends work through the supplied adapter, reduces normalized events, and persists the resulting snapshot.

A ConversationSnapshot is not a resumable runtime checkpoint. Provider continuity remains an opaque ProviderSessionRef, and live reconnection remains process-local.