Skip to main content

API Reference

The dialai library provides functions for creating sessions, registering specialists, and managing the decision cycle. For the conceptual foundation, see Concepts.

Quick Reference

FunctionPurpose
createSessionCreate a new session instance
getSessionRetrieve a session by ID
getSessionsList all sessions
registerProposerRegister a proposer specialist
submitProposalSubmit a state transition proposal
registerArbiterRegister an arbiter specialist
submitArbitrationEvaluate consensus and optionally execute
evaluateConsensusCheck if consensus is reached
executeTransitionExecute a state transition
runSessionRun a machine to completion
tickGlobal heartbeat — sweep all active sessions
getProposersList proposers for a machine
getArbiterGet arbiter for a machine
enableSpecialistRe-enable a disabled specialist
disableSpecialistDisable a specialist (preserves history)
getCollapseMetricsProgressive collapse monitoring
getProposalsForRoundList proposals in a round

Session Functions

createSession

Creates a new session instance from a machine definition.

import { createSession } from "dialai";

const session = await createSession(machine);
// Or with metadata:
// const session = await createSession(machine, { puzzleSize: 3 });
// session.sessionId → "a1b2c3d4-..."
// session.currentState → machine.initialState
// session.history → []

Signature:

createSession(machine: MachineDefinition, metaJson?: Record<string, unknown>): Promise<Session>

getSession

Retrieves a session by its ID.

import { getSession } from "dialai";

const session = await getSession("a1b2c3d4-...");

Signature:

getSession(sessionId: string): Promise<Session>

Throws if the session is not found.

getSessions

Returns all stored sessions.

import { getSessions } from "dialai";

const sessions = await getSessions();

Signature:

getSessions(): Promise<Session[]>

Specialist Functions

registerProposer

Registers a proposer specialist for a machine.

import { registerProposer } from "dialai";

const proposer = await registerProposer({
specialistId: "ai-proposer-1",
machineName: "my-task",
strategyFn: async (ctx) => ({
transitionName: Object.keys(ctx.transitions)[0],
toState: Object.values(ctx.transitions)[0],
reasoning: "First available transition",
}),
});

Signature:

registerProposer(opts: {
specialistId: string;
machineName: string;
isHuman?: boolean;
strategyFn?: (ctx: ProposerContext) => Promise<ProposerStrategyResult>;
strategyFnName?: string;
strategyWebhookUrl?: string;
contextFn?: (ctx: ProposerContext) => Promise<string>;
contextWebhookUrl?: string;
modelId?: string;
webhookTokenName?: string;
threshold?: number;
}): Promise<Proposer>

See Registering Specialists for execution mode details.

Human Specialists:

// Register a human specialist
const humanReviewer = await registerProposer({
specialistId: "human-reviewer",
machineName: "my-task",
isHuman: true, // Enables forced arbitration
strategyFnName: "firstAvailable", // Execution mode still required
});

Human specialists are identified by isHuman: true, which grants:

  • Human proposals always win consensus
  • Ability to force transitions via submitArbitration

An execution mode is still required at registration. Use strategyFnName as a fallback, or provide a strategyFn encoding human preferences. When submitting proposals directly with transitionName, the strategy is bypassed.

registerArbiter

Registers an arbiter specialist for a machine. Arbiters evaluate consensus among proposals.

import { registerArbiter } from "dialai";

const arbiter = await registerArbiter({
specialistId: "consensus-arbiter",
machineName: "my-task",
strategyFnName: "alignmentMargin",
threshold: 0.5,
});

Signature:

registerArbiter(opts: {
specialistId: string;
machineName: string;
strategyFn?: (ctx: ArbiterContext) => Promise<ArbiterStrategyResult>;
strategyFnName?: string; // "alignmentMargin"
strategyWebhookUrl?: string;
webhookTokenName?: string;
threshold?: number;
}): Promise<Arbiter>

See registerArbiter for full documentation including built-in strategies.

ArbiterContext:

The context passed to a custom arbiter strategy function:

interface ArbiterContext {
sessionId: string;
roundId: string;
currentState: string;
prompt: string;
machineName: string;
proposals: Proposal[];
alignmentScores?: Record<string, number>;
humanGoldExamples?: HumanGoldExample[];
history: TransitionRecord[];
threshold?: number;
metaJson?: Record<string, unknown>;
}

Example custom arbiter using alignment margin logic on proposals:

const arbiter = await registerArbiter({
specialistId: "custom-arbiter",
machineName: "my-task",
strategyFn: async (ctx) => {
// Count proposals per transition
const counts: Record<string, number> = {};
for (const p of ctx.proposals) {
counts[p.transitionName] = (counts[p.transitionName] || 0) + 1;
}
const sorted = Object.entries(counts).sort((a, b) => b[1] - a[1]);
const leader = sorted[0];
const runnerUp = sorted[1]?.[1] ?? 0;
if (leader[1] - runnerUp >= ctx.threshold) {
const winning = ctx.proposals.find(p => p.transitionName === leader[0]);
return {
consensusReached: true,
winningProposalId: winning!.proposalId,
reasoning: `${leader[0]} ahead by ${leader[1] - runnerUp}`,
};
}
return { consensusReached: false, reasoning: "No transition ahead by threshold" };
},
threshold: 2,
});

Decision Functions

submitProposal

Creates and stores a proposal. If transitionName is omitted, invokes the specialist's registered strategy.

import { submitProposal } from "dialai";

// Strategy invocation (AI specialists)
const proposal = await submitProposal({
sessionId: session.sessionId,
specialistId: "ai-proposer-1",
roundId: session.currentRoundId, // omit to use current round
});

// Direct submission with all parameters
const proposal = await submitProposal({
sessionId: session.sessionId,
specialistId: "ai-proposer-1",
roundId: session.currentRoundId,
transitionName: "approve",
reasoning: "Looks good to me",
metaJson: { source: "review" },
costUSD: 0.003,
latencyMsec: 200,
numInputTokens: 150,
numOutputTokens: 50,
});

Signature:

submitProposal(opts: SubmitProposalOptions): Promise<Proposal>

SubmitProposalOptions:

FieldTypeRequiredDescription
sessionIdstringYesSession identifier
specialistIdstringYesWho is submitting
roundIdstringNoOmit to use current round; provide to target a specific round (enables staleness detection)
transitionNamestringNoTransition to propose (invokes strategy if omitted)
reasoningstringNoExplanation for the proposal
metaJsonobjectNoArbitrary client metadata
costUSDnumberNoCost in USD to generate this proposal
latencyMsecnumberNoTime in milliseconds to generate
numInputTokensnumberNoInput tokens used
numOutputTokensnumberNoOutput tokens used

Cost tracking fields enable measuring the economic cost of AI delegation.

evaluateConsensus

Evaluates whether consensus has been reached for a session.

import { evaluateConsensus } from "dialai";

const result = await evaluateConsensus(session.sessionId);

if (result.consensusReached) {
console.log("Winner:", result.winningProposalId);
} else {
console.log("No consensus:", result.reasoning);
}

Signature:

evaluateConsensus(sessionId: string): Promise<ConsensusResult>

ConsensusResult:

interface ConsensusResult {
consensusReached: boolean;
winningProposalId?: string;
reasoning: string;
}

submitArbitration

Evaluates consensus and optionally executes the winning transition. Combines consensus evaluation with transition execution in a single call. Supports human override for forcing transitions.

import { submitArbitration } from "dialai";

// Check for consensus and auto-execute if found
const result = await submitArbitration({
sessionId: session.sessionId,
});

if (result.executed) {
console.log("Transitioned to:", result.toState);
} else {
console.log("No consensus:", result.guardReason);
}

// Human override with cost tracking
const result = await submitArbitration({
sessionId: session.sessionId,
specialistId: "human-reviewer",
transitionName: "approve",
reasoning: "Manager approved",
metaJson: { approvedBy: "jane" },
costUSD: 0.0,
latencyMsec: 5000,
numInputTokens: 0,
numOutputTokens: 0,
});

Signature:

submitArbitration(opts: SubmitArbitrationOptions): Promise<ArbitrationResult>

SubmitArbitrationOptions:

FieldTypeRequiredDescription
sessionIdstringYesSession identifier
roundIdstringNoOmit to use current round; if provided, enables staleness detection
specialistIdstringNoWho is calling (required for override)
transitionNamestringNoForce this transition (human only)
reasoningstringNoExplanation for the decision
metaJsonobjectNoArbitrary client metadata
costUSDnumberNoCost in USD for this arbitration
latencyMsecnumberNoTime in milliseconds
numInputTokensnumberNoInput tokens used
numOutputTokensnumberNoOutput tokens used

See submitArbitration for full documentation.

executeTransition

Executes a state transition, updating the session and recording history.

import { executeTransition } from "dialai";

const updated = await executeTransition(
session.sessionId,
"approve", // transitionName
"approved", // toState
"Consensus reached" // reasoning
);

console.log(updated.currentState); // "approved"
console.log(updated.history); // [..., { transitionName, reasoning, ... }]

Signature:

executeTransition(
sessionId: string,
transitionName: string,
toState: string,
reasoning?: string
): Promise<Session>

Throws if the transition is invalid from the current state.

Engine

runSession

Runs a machine to its goal state. Creates a session, registers a built-in proposer, and loops through the decision cycle until the goal state is reached.

import { runSession } from "dialai";

const session = await runSession(machine);
// session.currentState === machine.goalState

Signature:

runSession(machine: MachineDefinition): Promise<Session>

Behavior:

  1. Creates a session in the initial state
  2. Registers machine-level and per-state specialists from the machine definition
  3. Registers a default proposer (firstAvailable) if no proposers are specified
  4. Registers a default arbiter (firstProposal) if no arbiter is specified
  5. Loops tick() until the session reaches its goal state or needs human intervention
  6. Returns the session (completed or waiting for human)

Store

The store is accessed through exported functions:

import { getStore, setStore, clear } from "dialai";

// Access the current store (default: in-memory)
const store = getStore();

// Reset all state (useful for tests)
await clear();

// Use a custom store (e.g., PostgreSQL)
import { createPostgresStore } from "dialai/store-postgres";
setStore(createPostgresStore(pool));
ExportTypeDescription
getStore() => StoreReturns the current store instance
setStore(store: Store) => voidReplaces the store implementation
clear() => Promise<void>Clears all data in the current store

Orchestration

tick

Global heartbeat. Sweeps all active sessions, performing one atomic step per session.

import { tick } from "dialai";

const results = await tick();
for (const r of results) {
console.log(`${r.sessionId}: ${r.status}${r.currentState}`);
}

Signature:

tick(): Promise<TickResult[]>

Per-session behavior:

  • If a proposer hasn't submitted yet → solicit that one proposer (status: 'solicited')
  • If all proposers submitted and consensus reached → execute transition (status: 'advanced')
  • If all proposers submitted but no consensus → report (status: 'needs_human')
  • Terminal sessions are omitted from results

Specialist Management

getProposers

Returns all proposers registered for a machine.

import { getProposers } from "dialai";
const proposers = await getProposers("my-task");

Signature:

getProposers(machineName: string): Promise<Proposer[]>

getArbiter

Returns the arbiter registered for a machine, or undefined if none.

import { getArbiter } from "dialai";
const arbiter = await getArbiter("my-task");

Signature:

getArbiter(machineName: string): Promise<Arbiter | undefined>

enableSpecialist

Re-enables a previously disabled specialist.

import { enableSpecialist } from "dialai";
await enableSpecialist("ai-proposer-1");

Signature:

enableSpecialist(specialistId: string): Promise<void>

disableSpecialist

Disables a specialist. The specialist stops receiving solicitations but its registration and alignment history are preserved.

import { disableSpecialist } from "dialai";
await disableSpecialist("ai-proposer-1");

Signature:

disableSpecialist(specialistId: string): Promise<void>

Monitoring

getCollapseMetrics

Returns progressive collapse metrics for a machine, optionally filtered by state.

import { getCollapseMetrics } from "dialai";
const metrics = await getCollapseMetrics("my-task");
console.log(`Collapse ratio: ${metrics.collapseRatio}`);

Signature:

getCollapseMetrics(machineName: string, state?: string): Promise<CollapseMetrics>

getProposalsForRound

Returns all proposals submitted in a specific round.

import { getProposalsForRound } from "dialai";
const proposals = await getProposalsForRound(session.sessionId, session.currentRoundId);

Signature:

getProposalsForRound(sessionId: string, roundId: string): Promise<Proposal[]>

Additional References