@elsium-ai/agents

Agent orchestration, memory, guardrails, and multi-agent patterns for ElsiumAI.

Install

npm install @elsium-ai/agents @elsium-ai/core

What’s Inside

Category Exports Description
Agent defineAgent, Agent, AgentDependencies Define and run a single agent with tools, memory, and guardrails
Types AgentConfig, AgentResult, AgentRunOptions, AgentHooks, GuardrailConfig, StateDefinition, StateHistoryEntry, StateMachineResult Core type definitions used across the package
Memory createMemory, Memory, MemoryConfig, MemoryStrategy Conversation history management with configurable retention strategies
Multi-Agent runSequential, runParallel, runSupervisor, MultiAgentConfig Orchestrate multiple agents in sequence, parallel, or supervisor patterns
Semantic Guardrails createSemanticValidator, SemanticGuardrailConfig, SemanticCheck, SemanticCheckResult, SemanticValidationResult, SemanticValidator Hallucination detection, relevance checking, and grounding validation
Security createAgentSecurity, AgentSecurityConfig, AgentSecurityResult Prompt injection detection, jailbreak prevention, and secret redaction
Confidence createConfidenceScorer, ConfidenceConfig, ConfidenceResult Score agent output confidence with heuristic and semantic signals
State Machine executeStateMachine Run an agent through a finite state machine of states and transitions
Approval Gates createApprovalGate, shouldRequireApproval, ApprovalRequest, ApprovalDecision, ApprovalCallback, ApprovalGateConfig, ApprovalGate Human-in-the-loop approval for high-stakes operations

Agent

defineAgent

Create a new agent instance from a configuration object and a set of dependencies.

function defineAgent(config: AgentConfig, deps: AgentDependencies): Agent
ParameterTypeDescription
configAgentConfigFull agent configuration (name, system prompt, tools, guardrails, etc.)
depsAgentDependenciesExternal dependencies the agent requires (currently an LLM completion function)

Returns: Agent

import { defineAgent } from '@elsium-ai/agents'

const agent = defineAgent(
  {
    name: 'assistant',
    system: 'You are a helpful assistant.',
    model: 'claude-sonnet-4-6',
  },
  { complete: (req) => llm.complete(req) },
)

const result = await agent.run('Explain circuit breakers in distributed systems.')
console.log(result.message.content)

Reproducibility (seed)

Set AgentConfig.seed to forward a seed to every CompletionRequest the agent issues (both the tool loop and streaming). Override it per call with AgentRunOptions.seed; the per-run value falls back to the agent-level one when omitted.

const agent = defineAgent({ name: 'extractor', system: '...', seed: 42 })

const a = await agent.run('Extract the fields')
const b = await agent.run('Extract the fields', { seed: 7 }) // per-run override

Caveat: seed is only effective if the provider honors it (forwarded where supported, e.g. OpenAI and Google; absent on Anthropic). It does not, on its own, make a hosted model deterministic. Use @elsium-ai/testing’s assertDeterministic to measure run-to-run variance (it measures variance, it does not enforce it). See examples/reproducible-run.

Agent

The object returned by defineAgent. Provides methods for running the agent and managing memory.

interface Agent {
  readonly name: string
  readonly config: AgentConfig
  run(input: string, options?: AgentRunOptions): Promise<AgentResult>
  chat(messages: Message[], options?: AgentRunOptions): Promise<AgentResult>
  resetMemory(): void
}
MethodDescription
run(input, options?)Run the agent with a single string input. If states and initialState are configured, the agent runs in state-machine mode.
chat(messages, options?)Run the agent with an array of Message objects for multi-turn conversations.
resetMemory()Clear the agent’s conversation memory.

AgentDependencies

Dependencies injected into an agent at creation time.

interface AgentDependencies {
  complete: (request: CompletionRequest) => Promise<LLMResponse>
}

Types

AgentConfig

Top-level configuration for creating an agent.

interface AgentConfig {
  name: string
  model?: string
  system: string
  tools?: Tool[]
  memory?: MemoryConfig
  guardrails?: GuardrailConfig
  hooks?: AgentHooks
  confidence?: boolean | ConfidenceConfig
  states?: Record<string, StateDefinition>
  initialState?: string
  seed?: number
}

AgentResult

The result returned after an agent run completes.

interface AgentResult {
  message: Message
  usage: {
    totalInputTokens: number
    totalOutputTokens: number
    totalTokens: number
    totalCost: number
    iterations: number
  }
  toolCalls: Array<{
    name: string
    arguments: Record<string, unknown>
    result: ToolExecutionResult
  }>
  traceId: string
  confidence?: ConfidenceResult
}

AgentRunOptions

Optional parameters passed to agent.run() or agent.chat().

interface AgentRunOptions {
  signal?: AbortSignal
  traceId?: string
  metadata?: Record<string, unknown>
  seed?: number
}

AgentHooks

Lifecycle hooks that fire at various points during the agent loop.

interface AgentHooks {
  onMessage?: (message: Message) => void | Promise<void>
  onToolCall?: (call: { name: string; arguments: Record<string, unknown> }) => void | Promise<void>
  onToolResult?: (result: ToolExecutionResult) => void | Promise<void>
  onError?: (error: Error) => void | Promise<void>
  onComplete?: (result: AgentResult) => void | Promise<void>
  onApprovalRequired?: ApprovalCallback
}

GuardrailConfig

Configuration for input/output validation, semantic checks, security, and approval gates.

interface GuardrailConfig {
  maxIterations?: number
  maxTokenBudget?: number
  inputValidator?: (input: string) => boolean | string
  outputValidator?: (output: string) => boolean | string
  semantic?: SemanticGuardrailConfig
  security?: AgentSecurityConfig
  approval?: ApprovalGateConfig
}

StateDefinition

Defines a single state within a state-machine agent.

interface StateDefinition {
  system?: string
  tools?: Tool[]
  guardrails?: GuardrailConfig
  transition: (result: AgentResult) => string
  terminal?: boolean
}

StateHistoryEntry

A record of a single state execution and its transition.

interface StateHistoryEntry {
  state: string
  result: AgentResult
  transitionedTo: string | null
}

StateMachineResult

Extends AgentResult with state-machine-specific data.

interface StateMachineResult extends AgentResult {
  stateHistory: StateHistoryEntry[]
  finalState: string
}

Memory

createMemory

Create a memory instance that manages conversation history with a configurable retention strategy.

function createMemory(config: MemoryConfig): Memory
ParameterTypeDescription
configMemoryConfigStrategy and limits for memory retention

Returns: Memory

import { createMemory } from '@elsium-ai/agents'

const memory = createMemory({
  strategy: 'sliding-window',
  maxMessages: 50,
})

memory.add({ role: 'user', content: 'Hello' })
memory.add({ role: 'assistant', content: 'Hi there!' })

console.log(memory.getMessages())       // [{ role: 'user', ... }, { role: 'assistant', ... }]
console.log(memory.getTokenEstimate())   // approximate token count

Memory

The memory interface returned by createMemory.

interface Memory {
  readonly strategy: MemoryStrategy
  add(message: Message): void
  getMessages(): Message[]
  clear(): void
  getTokenEstimate(): number
}
MethodDescription
add(message)Append a message. Automatically trims based on the configured strategy.
getMessages()Return a copy of all stored messages.
clear()Remove all messages from memory.
getTokenEstimate()Return an approximate token count across all stored messages.

MemoryConfig

Configuration for a memory instance.

interface MemoryConfig {
  strategy: MemoryStrategy
  maxTokens?: number
  maxMessages?: number
}
FieldTypeDefaultDescription
strategyMemoryStrategy—Retention strategy to use
maxTokensnumber128000Maximum estimated tokens (used by token-limited)
maxMessagesnumber100Maximum number of messages (used by sliding-window)

MemoryStrategy

The available memory retention strategies.

type MemoryStrategy = 'sliding-window' | 'token-limited' | 'unlimited'
StrategyBehavior
sliding-windowKeeps the most recent maxMessages messages, dropping the oldest first
token-limitedKeeps messages within maxTokens, dropping the oldest first when the budget is exceeded
unlimitedRetains all messages without any trimming

Multi-Agent

runSequential

Run multiple agents in sequence, piping the text output of each agent as the input to the next.

function runSequential(
  agents: Agent[],
  input: string,
  options?: AgentRunOptions,
): Promise<AgentResult[]>
ParameterTypeDescription
agentsAgent[]Ordered list of agents to run
inputstringInitial input for the first agent
optionsAgentRunOptionsShared run options for all agents

Returns: Promise<AgentResult[]> — one result per agent, in order.

import { defineAgent, runSequential } from '@elsium-ai/agents'

const researcher = defineAgent(
  { name: 'researcher', system: 'Research the topic thoroughly.' },
  { complete: (req) => llm.complete(req) },
)
const writer = defineAgent(
  { name: 'writer', system: 'Write a polished article from the research.' },
  { complete: (req) => llm.complete(req) },
)

const results = await runSequential([researcher, writer], 'Quantum computing basics')
const finalArticle = results[1].message.content

runParallel

Run multiple agents concurrently on the same input. Uses Promise.allSettled internally so that partial results are returned even if some agents fail.

function runParallel(
  agents: Agent[],
  input: string,
  options?: AgentRunOptions,
): Promise<AgentResult[]>
ParameterTypeDescription
agentsAgent[]Agents to run in parallel
inputstringInput provided to every agent
optionsAgentRunOptionsShared run options

Returns: Promise<AgentResult[]> — results from all agents that completed successfully. Throws the first error only if all agents fail.

import { defineAgent, runParallel } from '@elsium-ai/agents'

const optimist = defineAgent(
  { name: 'optimist', system: 'Present the optimistic perspective.' },
  { complete: (req) => llm.complete(req) },
)
const critic = defineAgent(
  { name: 'critic', system: 'Present a critical analysis.' },
  { complete: (req) => llm.complete(req) },
)

const results = await runParallel([optimist, critic], 'Should we adopt microservices?')

runSupervisor

Run a supervisor agent that coordinates a set of worker agents. The supervisor receives descriptions of all workers and the user request, and decides how to delegate.

function runSupervisor(
  supervisor: Agent,
  workers: Agent[],
  input: string,
  options?: AgentRunOptions,
): Promise<AgentResult>
ParameterTypeDescription
supervisorAgentThe coordinating agent
workersAgent[]Available worker agents (their names and system prompts are provided to the supervisor)
inputstringUser request to delegate
optionsAgentRunOptionsShared run options

Returns: Promise<AgentResult> — the supervisor’s synthesized response.

import { defineAgent, runSupervisor } from '@elsium-ai/agents'

const supervisor = defineAgent(
  { name: 'supervisor', system: 'Coordinate workers to answer the user.' },
  { complete: (req) => llm.complete(req) },
)
const coder = defineAgent(
  { name: 'coder', system: 'Write code solutions.' },
  { complete: (req) => llm.complete(req) },
)
const reviewer = defineAgent(
  { name: 'reviewer', system: 'Review code for bugs and improvements.' },
  { complete: (req) => llm.complete(req) },
)

const result = await runSupervisor(supervisor, [coder, reviewer], 'Build a rate limiter in TypeScript')

MultiAgentConfig

Configuration type for multi-agent orchestration (useful when building higher-level abstractions).

interface MultiAgentConfig {
  agents: Agent[]
  strategy: 'sequential' | 'parallel' | 'supervisor'
  supervisor?: Agent
}

Streaming

agent.stream

agent.stream(input: string, options?: AgentRunOptions): AgentStream

Streams agent execution in real-time. Returns an AgentStream that yields AgentStreamEvent objects and provides a .result() method for the final AgentResult.

Requires a stream function in agent dependencies.

AgentStreamEvent types:

TypeFieldsDescription
text_deltatext: stringIncremental text from the LLM
tool_call_starttoolCall: { id, name }Tool call initiated
tool_call_deltatoolCallId, argumentsPartial tool arguments
tool_call_endtoolCallIdTool arguments complete
tool_resulttoolCallId, name, resultTool execution result
iteration_startiteration: numberNew loop iteration
iteration_enditeration: numberLoop iteration complete
agent_endresult: AgentResultAgent finished
errorerror: ErrorExecution error
const agent = defineAgent(
  { name: 'assistant', system: 'You are helpful.' },
  { complete: (req) => llm.complete(req), stream: (req) => llm.stream(req) },
)

const stream = agent.stream('Hello')
for await (const event of stream) {
  if (event.type === 'text_delta') process.stdout.write(event.text)
}
const result = await stream.result()

Threads

createThread

createThread(config: ThreadConfig): Thread

Creates a conversation thread that manages message history across multiple send() calls.

Config:

FieldTypeDescription
idstring?Custom thread ID (auto-generated if omitted)
agentAgentThe agent to use for this thread
metadataRecord?Custom metadata
storeThreadStore?Persistence adapter

Thread methods:

MethodReturnsDescription
send(input)Promise<AgentResult>Send a message and get a response
stream(input)AgentStreamStream a response
getMessages()Message[]Get full conversation history
addMessage(msg)voidManually add a message
fork(opts?)ThreadFork thread with full history
clear()voidClear all messages
save()Promise<void>Manually persist to store

loadThread

loadThread(threadId: string, config: { agent, store }): Promise<Thread | null>

Loads a thread from a store. Returns null if not found.

createInMemoryThreadStore

createInMemoryThreadStore(): ThreadStore

In-memory thread persistence. Data lost on process exit.


Async Agents

createAsyncAgent

createAsyncAgent(config: AsyncAgentConfig): AsyncAgent

Wraps an agent for background task execution with progress tracking and cancellation.

Config:

FieldTypeDescription
agentAgentThe agent to run tasks with
onProgress(task, event) => voidProgress callback
onComplete(task) => voidCompletion callback
onError(task, error) => voidError callback

AsyncAgent methods:

MethodReturnsDescription
submit(input, opts?)AgentTaskSubmit a task for execution
getTask(id)AgentTask | nullGet a task by ID
listTasks(filter?)AgentTask[]List tasks, optionally filtered by status
cancelAll()voidCancel all pending/running tasks

AgentTask:

Property/MethodDescription
idTask identifier
status'pending' | 'running' | 'completed' | 'failed' | 'cancelled'
resultAgentResult | null
errorError | null
wait()Promise<AgentResult> — resolves when task completes
cancel()Cancel the task
const asyncAgent = createAsyncAgent({ agent, onComplete: (t) => notify(t.id) })
const task = asyncAgent.submit('Research quantum computing')
const result = await task.wait()

Task Stores

Pass a TaskStore as AsyncAgentConfig.taskStore to persist every task transition, so submitted tasks survive process restarts. The package ships two reference adapters; for production durability implement TaskStore against your own backend.

createInMemoryTaskStore(): TaskStore
createJsonFileTaskStore(config: JsonFileTaskStoreConfig): TaskStore

createInMemoryTaskStore keeps PersistedTask records in a Map (lost on exit). createJsonFileTaskStore writes one <taskId>.json file per task under config.dir using atomic temp-file renames and per-id write serialization.

JsonFileTaskStoreConfig:

FieldTypeDescription
dirstringDirectory where task JSON files are written (created if missing)

TaskStore methods:

MethodReturnsDescription
save(task)Promise<void>Persist (upsert) a PersistedTask
load(taskId)Promise<PersistedTask | null>Load a task by ID
list(filter?)Promise<PersistedTask[]>List tasks, optionally filtered by status
delete(taskId)Promise<void>Remove a task record
import { createAsyncAgent, createJsonFileTaskStore } from '@elsium-ai/agents'

const taskStore = createJsonFileTaskStore({ dir: './data/tasks' })
const asyncAgent = createAsyncAgent({ agent, taskStore })

ReAct Agent

defineReActAgent

defineReActAgent(config: ReActConfig): ReActAgent

Creates an agent that follows the explicit ReAct (Reason + Act) loop — emitting Thought → Action → Action Input → Observation cycles until it produces a Final Answer. Unlike defineAgent, the result carries the full step-by-step reasoning trace, and the agent is wired directly to a gateway/provider rather than taking AgentDependencies.

ReActConfig:

FieldTypeDescription
namestringAgent identifier
toolsTool[]Tools available to the agent
modelstring?LLM model to use
systemstring?User system prompt, prepended to the built-in ReAct prompt
maxIterationsnumber?Maximum reasoning iterations (default: 10)
maxTokenBudgetnumber?Token budget across the run (default: 500000)
hooksReActConfig['hooks']?AgentHooks plus onThought, onAction, onObservation callbacks
providerstring | LLMProvider | ProviderMesh?Provider name, or an object exposing complete
apiKeystring?API key (required when provider is a name string)
baseUrlstring?Optional provider base URL

Provide either an LLMProvider/ProviderMesh object as provider, or a provider name string together with apiKey; otherwise construction throws.

ReActAgent exposes name and run(input, options?): Promise<ReActResult>.

ReActResult extends AgentResult with reasoning: ReActStep[], where each ReActStep is { iteration, thought, action?: { tool, input }, observation? }.

import { defineReActAgent } from '@elsium-ai/agents'

const agent = defineReActAgent({
  name: 'researcher',
  provider: 'openai',
  apiKey: process.env.OPENAI_API_KEY,
  model: 'gpt-4o',
  tools: [searchTool, calculatorTool],
  hooks: {
    onThought: (thought, i) => console.log(`[${i}] ${thought}`),
  },
})

const result = await agent.run('What is the population of France times 2?')
for (const step of result.reasoning) {
  console.log(step.thought, step.action, step.observation)
}

Semantic Guardrails

createSemanticValidator

Create a semantic validator that checks agent output for hallucinations, relevance, and grounding. When an llmComplete function is provided, checks use LLM-based evaluation; otherwise they fall back to word-overlap heuristics.

function createSemanticValidator(
  config: SemanticGuardrailConfig,
  llmComplete?: LLMComplete,
): SemanticValidator
ParameterTypeDescription
configSemanticGuardrailConfigWhich checks to enable and their thresholds
llmComplete(request: CompletionRequest) => Promise<LLMResponse>Optional LLM function for production-grade checks

Returns: SemanticValidator

import { createSemanticValidator } from '@elsium-ai/agents'

const validator = createSemanticValidator(
  {
    hallucination: { enabled: true, ragContext: ['The capital of France is Paris.'], threshold: 0.7 },
    relevance: { enabled: true, threshold: 0.5 },
  },
  (req) => llm.complete(req),
)

const result = await validator.validate(
  'What is the capital of France?',
  'The capital of France is Paris.',
)
console.log(result.valid)   // true
console.log(result.checks)  // [{ name: 'hallucination', passed: true, ... }, ...]

SemanticValidator

The validator object returned by createSemanticValidator.

interface SemanticValidator {
  validate(input: string, output: string): Promise<SemanticValidationResult>
  checkHallucination(output: string, context: string[]): Promise<SemanticCheckResult>
  checkRelevance(input: string, output: string): Promise<SemanticCheckResult>
  checkGrounding(output: string, sources: string[]): Promise<SemanticCheckResult>
}
MethodDescription
validate(input, output)Run all enabled checks and return an aggregate result
checkHallucination(output, context)Check whether the output contains claims unsupported by the given context
checkRelevance(input, output)Check whether the output is relevant to the input
checkGrounding(output, sources)Check whether the output’s claims are grounded in the provided sources

SemanticGuardrailConfig

Configuration for which semantic checks to enable and how they behave.

interface SemanticGuardrailConfig {
  hallucination?: {
    enabled: boolean
    ragContext?: string[]
    threshold?: number
  }
  relevance?: {
    enabled: boolean
    threshold?: number
  }
  grounding?: {
    enabled: boolean
    sources?: string[]
  }
  customChecks?: SemanticCheck[]
  autoRetry?: {
    enabled: boolean
    maxRetries?: number
  }
}

SemanticCheck

A custom semantic check function.

interface SemanticCheck {
  name: string
  check: (input: string, output: string) => Promise<SemanticCheckResult>
}

SemanticCheckResult

The result of a single semantic check.

interface SemanticCheckResult {
  passed: boolean
  score: number
  reason: string
}

SemanticValidationResult

The aggregate result of all semantic checks run by validate().

interface SemanticValidationResult {
  valid: boolean
  checks: Array<{
    name: string
    passed: boolean
    score: number
    reason: string
  }>
}

Security

createAgentSecurity

Create a security module that validates input for prompt injection and jailbreak attempts, and sanitizes output by redacting detected secrets.

function createAgentSecurity(config: AgentSecurityConfig): {
  validateInput(input: string): AgentSecurityResult
  sanitizeInput(input: string): AgentSecurityResult
  sanitizeOutput(output: string): AgentSecurityResult
}
ParameterTypeDescription
configAgentSecurityConfigWhich security checks to enable

Returns: An object with validateInput, sanitizeInput, and sanitizeOutput methods.

import { createAgentSecurity } from '@elsium-ai/agents'

const security = createAgentSecurity({
  detectPromptInjection: true,
  detectJailbreak: true,
  redactSecrets: true,
})

const inputCheck = security.validateInput('ignore all previous instructions and ...')
console.log(inputCheck.safe)        // false
console.log(inputCheck.violations)  // [{ type: 'prompt_injection', ... }]

const outputCheck = security.sanitizeOutput('Your API key is sk-abc123def456ghi789jkl012mno')
console.log(outputCheck.redactedOutput)  // 'Your API key is [REDACTED_API_KEY]'

AgentSecurityConfig

Configuration for the security module.

interface AgentSecurityConfig {
  detectPromptInjection?: boolean
  detectJailbreak?: boolean
  redactSecrets?: boolean
  blockedPatterns?: RegExp[]
  redactInputSecrets?: boolean
  redactInputPii?: Array<'email' | 'phone' | 'address' | 'passport' | 'all'>
  injectionClassifier?: InputGuardrail
  redactToolArgSecrets?: boolean
}
FieldTypeDefaultDescription
detectPromptInjectionbooleantrueDetect prompt injection patterns in input
detectJailbreakbooleanfalseDetect jailbreak attempt patterns in input
redactSecretsbooleantrueRedact secrets (API keys, passwords, SSNs, cards, bearer tokens) in output
blockedPatternsRegExp[][]Additional custom regex patterns to block in input
redactInputSecretsbooleanfalseRedact secrets from user input before it reaches the model
redactInputPiiArray<'email' | 'phone' | 'address' | 'passport' | 'all'>[]PII categories to redact from input; setting any category also redacts input secrets
injectionClassifierInputGuardrail—Optional async classifier run on the raw input; return true to reject it (applied on run/chat/generate, not stream)
redactToolArgSecretsbooleanfalseRedact secrets from tool-call arguments before execution and trace (PII is left intact)

Input guardrail pipeline (applied on run / chat / generate): detection (throws on violation) → async injectionClassifier (throws if flagged) → redaction (transforms the text sent to the model). stream applies only the synchronous steps (detection + redaction); the async classifier is skipped.

AgentSecurityResult

The result from an input validation or output sanitization check.

interface AgentSecurityResult {
  safe: boolean
  violations: Array<{
    type: string
    detail: string
    severity: 'low' | 'medium' | 'high'
  }>
  redactedOutput?: string
}

createLLMGuardrail

createLLMGuardrail(options: LLMGuardrailOptions): InputGuardrail

Returns a built-in InputGuardrail ((input: string) => boolean | Promise<boolean>, true = reject) backed by the gateway you already use — no extra install. Plug it into AgentSecurityConfig.injectionClassifier as a higher-precision alternative to the heuristic regex detector.

InputGuardrail is the extension port: pass createLLMGuardrail, or your own function wrapping an external tool (Lakera, NeMo Guardrails, Presidio, etc.). External integration is the caller’s choice, never a dependency.

LLMGuardrailOptions:

FieldTypeDefaultDescription
completeLLMComplete—Completion function — typically gateway.complete
modelstringgateway defaultModel override
instructionsstringbuilt-in promptOverride the classification system prompt
onError'allow' | 'block''allow''allow' fails open (do not block on classifier failure); 'block' fails closed
import { defineAgent, createLLMGuardrail } from '@elsium-ai/agents'

const agent = defineAgent({
  name: 'assistant',
  system: 'You are helpful.',
  guardrails: {
    security: {
      injectionClassifier: createLLMGuardrail({ complete: (req) => llm.complete(req) }),
    },
  },
})

Confidence

createConfidenceScorer

Create a confidence scorer that evaluates how reliable an agent’s output is. When semantic validation results are available they are used directly; otherwise heuristic word-overlap analysis is applied.

function createConfidenceScorer(config: ConfidenceConfig): {
  score(
    input: string,
    output: string,
    semanticResult?: SemanticValidationResult,
  ): Promise<ConfidenceResult>
}
ParameterTypeDescription
configConfidenceConfigWhich confidence signals to compute

Returns: An object with a score method.

import { createConfidenceScorer } from '@elsium-ai/agents'

const scorer = createConfidenceScorer({
  hallucinationRisk: true,
  relevanceScore: true,
  citationCoverage: false,
})

const confidence = await scorer.score(
  'What is TypeScript?',
  'TypeScript is a typed superset of JavaScript.',
)
console.log(confidence.overall)           // 0.0 - 1.0
console.log(confidence.hallucinationRisk) // 0.0 - 1.0 (lower is better)
console.log(confidence.relevanceScore)    // 0.0 - 1.0 (higher is better)

ConfidenceConfig

Configuration for the confidence scorer.

interface ConfidenceConfig {
  hallucinationRisk?: boolean
  relevanceScore?: boolean
  citationCoverage?: boolean
  customChecks?: Array<{
    name: string
    check: (input: string, output: string) => Promise<{ score: number; reason: string }>
  }>
}
FieldTypeDefaultDescription
hallucinationRiskbooleantrueCompute hallucination risk (higher score = higher risk)
relevanceScorebooleantrueCompute relevance to input (higher score = more relevant)
citationCoveragebooleanfalseCompute citation coverage against RAG context
customChecksArray[]Additional custom scoring functions

ConfidenceResult

The scored confidence output.

interface ConfidenceResult {
  overall: number
  hallucinationRisk: number
  citationCoverage: number
  relevanceScore: number
  checks: Array<{ name: string; score: number; reason: string }>
}

State Machine

executeStateMachine

Execute an agent through a finite state machine. Each state can override the system prompt, tools, and guardrails. The agent transitions between states based on the transition function defined on each StateDefinition until a terminal state is reached.

function executeStateMachine(
  baseConfig: AgentConfig,
  stateConfig: { states: Record<string, StateDefinition>; initialState: string },
  deps: AgentDependencies,
  input: string,
  options?: AgentRunOptions,
): Promise<StateMachineResult>
ParameterTypeDescription
baseConfigAgentConfigBase agent configuration (model, default system prompt, guardrails)
stateConfig{ states, initialState }State definitions and the name of the initial state
depsAgentDependenciesLLM completion function
inputstringUser input
optionsAgentRunOptionsOptional run options

Returns: Promise<StateMachineResult> — the final agent result plus the full state history.

import { defineAgent } from '@elsium-ai/agents'

const agent = defineAgent(
  {
    name: 'order-processor',
    system: 'You process customer orders.',
    initialState: 'intake',
    states: {
      intake: {
        system: 'Gather order details from the user.',
        transition: (result) => 'validate',
      },
      validate: {
        system: 'Validate the order details are complete.',
        transition: (result) => 'confirm',
      },
      confirm: {
        system: 'Confirm the order with the user.',
        terminal: true,
        transition: () => 'confirm',
      },
    },
  },
  { complete: (req) => llm.complete(req) },
)

const result = await agent.run('I want to order 3 widgets')
console.log(result.finalState)   // 'confirm'
console.log(result.stateHistory) // [{ state: 'intake', ... }, { state: 'validate', ... }, ...]

Note: You do not need to call executeStateMachine directly. When states and initialState are set on the AgentConfig, calling agent.run() or agent.chat() automatically delegates to the state machine.


Approval Gates

createApprovalGate

Create an approval gate that intercepts operations and requests human (or programmatic) approval before proceeding.

function createApprovalGate(config: ApprovalGateConfig): ApprovalGate
ParameterTypeDescription
configApprovalGateConfigCallback, filters, timeout, and timeout behavior

Returns: ApprovalGate

import { createApprovalGate } from '@elsium-ai/agents'

const gate = createApprovalGate({
  callback: async (request) => {
    console.log(`Approval needed: ${request.description}`)
    // In production, prompt a human or call an external approval service
    return {
      requestId: request.id,
      approved: true,
      reason: 'Auto-approved in development',
      decidedAt: Date.now(),
    }
  },
  requireApprovalFor: {
    tools: ['delete_record', 'send_email'],
    costThreshold: 1.0,
  },
  timeoutMs: 60_000,
  onTimeout: 'deny',
})

const decision = await gate.requestApproval(
  'tool_call',
  'Execute tool: delete_record',
  { toolName: 'delete_record', arguments: { id: '123' } },
)
console.log(decision.approved) // true

shouldRequireApproval

Determine whether a given operation should be gated behind approval based on the configured rules.

function shouldRequireApproval(
  config: ApprovalGateConfig['requireApprovalFor'],
  context: { toolName?: string; model?: string; cost?: number },
): boolean
ParameterTypeDescription
configApprovalGateConfig['requireApprovalFor']The approval rules (which tools, models, or cost thresholds require approval)
context{ toolName?, model?, cost? }The current operation context to check

Returns: boolean — true if the operation requires approval.

import { shouldRequireApproval } from '@elsium-ai/agents'

const needsApproval = shouldRequireApproval(
  { tools: ['delete_record'], costThreshold: 5.0 },
  { toolName: 'delete_record' },
)
console.log(needsApproval) // true

ApprovalRequest

Describes a pending approval request.

interface ApprovalRequest {
  id: string
  type: 'tool_call' | 'model_access' | 'budget_exceed' | 'custom'
  description: string
  context: Record<string, unknown>
  requestedAt: number
}

ApprovalDecision

The decision returned by the approval callback.

interface ApprovalDecision {
  requestId: string
  approved: boolean
  reason?: string
  decidedBy?: string
  decidedAt: number
}

ApprovalCallback

The function type called when approval is required.

type ApprovalCallback = (request: ApprovalRequest) => Promise<ApprovalDecision>

ApprovalGateConfig

Configuration for the approval gate.

interface ApprovalGateConfig {
  callback: ApprovalCallback
  requireApprovalFor?: {
    tools?: string[] | boolean
    models?: string[]
    costThreshold?: number
  }
  timeoutMs?: number
  onTimeout?: 'deny' | 'allow'
}
FieldTypeDefaultDescription
callbackApprovalCallback—Function invoked when approval is needed
requireApprovalForobject—Rules defining which operations require approval
requireApprovalFor.toolsstring[] | boolean—Tool names that require approval, or true for all tools
requireApprovalFor.modelsstring[]—Model identifiers that require approval
requireApprovalFor.costThresholdnumber—Cost threshold above which approval is required
timeoutMsnumber300000Milliseconds to wait for approval before timing out
onTimeout'deny' | 'allow''deny'Behavior when the approval request times out

ApprovalGate

The approval gate object returned by createApprovalGate.

interface ApprovalGate {
  requestApproval(
    type: ApprovalRequest['type'],
    description: string,
    context: Record<string, unknown>,
  ): Promise<ApprovalDecision>
  readonly pendingCount: number
}

createApprovalChain / createInMemoryApprovalStore

createApprovalChain(config: ApprovalChainConfig): ApprovalChain
createInMemoryApprovalStore(): ApprovalStore

Multi-stage human-in-the-loop approval. A request flows through ordered ApprovalStages; each stage decides whether it applies (enter), who approves it (approver), and what happens on timeout. callback approvers are auto-invoked; role/user approvers pause the chain until resolved externally via store.resolveStage(...). The package ships only the in-memory store; implement ApprovalStore against your own backend for durability.

ApprovalChainConfig:

FieldTypeDescription
stagesreadonly ApprovalStage[]Ordered stages (at least one; names must be unique)
storeApprovalStorePersistence adapter for approval state
notifierApprovalNotifier?Optional hook called when a stage is entered (Slack/email/PagerDuty)

ApprovalStage:

FieldTypeDescription
namestringUnique stage name
enter(req: ApprovalRequest) => booleanReturns true if the stage applies; false skips it
approverApproverSpec{ type: 'role' | 'user', target: string } or { type: 'callback', target: ApprovalCallback }
timeoutMsnumber?Stage timeout (default: 300000)
onTimeout'deny' | 'escalate' | 'allow'?Action when the timeout fires (default: 'deny')

ApprovalChain methods:

MethodReturnsDescription
request(req)Promise<ApprovalState>Start a chain (req omits id/requestedAt); advances through auto-resolvable stages
resume(requestId)Promise<ApprovalState>Re-advance a pending chain (e.g. after an external resolveStage)
cancel(requestId, reason)Promise<ApprovalState>Deny all pending stages and mark the chain denied
storeApprovalStoreThe backing store

ApprovalState reports status ('pending' | 'approved' | 'denied' | 'expired'), currentStage, and per-stage StageState[].

import { createApprovalChain, createInMemoryApprovalStore } from '@elsium-ai/agents'

const chain = createApprovalChain({
  store: createInMemoryApprovalStore(),
  stages: [
    {
      name: 'manager',
      enter: (req) => (req.context?.amount as number) > 1000,
      approver: { type: 'role', target: 'manager' },
      timeoutMs: 60_000,
      onTimeout: 'escalate',
    },
    {
      name: 'auto-policy',
      enter: () => true,
      approver: { type: 'callback', target: (req) => ({
        requestId: req.id, approved: true, decidedAt: Date.now(),
      }) },
    },
  ],
})

let state = await chain.request({ type: 'tool_call', description: 'Wire funds', context: { amount: 5000 } })
// A role/user stage waits — the approving UI resolves it, then resume:
await chain.store.resolveStage(state.request.id, 'manager', {
  requestId: state.request.id, approved: true, decidedBy: 'alice', decidedAt: Date.now(),
})
state = await chain.resume(state.request.id)

askHuman / resolveAskHuman / createInMemoryAskHumanStore

askHuman<TOption>(options: AskHumanOptions<TOption> & { timeoutMs?: string | number }): Promise<AskHumanDecision<TOption>>
resolveAskHuman(store: AskHumanStore, requestId: string, decision: Omit<AskHumanDecision, 'decidedAt'>): Promise<void>
createInMemoryAskHumanStore(config?: InMemoryAskHumanStoreConfig): AskHumanStore

Durable, option-based human-in-the-loop primitive. askHuman poses a question with a fixed set of options and resolves either through a responder callback or by polling a store until a human resolves it via resolveAskHuman. The same capability is also available pre-bound on every agent as agent.askHuman(options).

AskHumanOptions:

FieldTypeDescription
questionstringThe question to ask (required, non-empty)
optionsreadonly TOption[]Allowed answer options (at least one)
contextRecord?Arbitrary context attached to the request
timeoutMsstring | number?Timeout; accepts ms or a duration string like '2h', '1d' (default: 24h)
onTimeout'reject' | 'timeout'?Status used when the timeout fires (default: 'timeout')
storeAskHumanStore?Store to persist/poll the request
responderAskHumanResponder<TOption>?Callback that resolves the request directly
requestIdstring?Custom request ID

Either a responder or a store must be supplied. AskHumanDecision is { status: 'approved' | 'rejected' | 'timeout' | 'custom', option?, reason?, decidedBy?, decidedAt }.

import { askHuman, createInMemoryAskHumanStore, resolveAskHuman } from '@elsium-ai/agents'

const store = createInMemoryAskHumanStore()

// Worker A: pauses until a human resolves the request (or 2h elapse)
const pending = askHuman({
  question: 'Approve the refund?',
  options: ['approve', 'deny'] as const,
  timeoutMs: '2h',
  store,
  requestId: 'refund-42',
})

// Worker B (the UI / webhook): resolve it
await resolveAskHuman(store, 'refund-42', {
  status: 'custom', option: 'approve', decidedBy: 'ops',
})

const decision = await pending // { status: 'custom', option: 'approve', ... }

Verification (VAG)

Verification-Augmented Generation: generate, validate against one or more Validators, and automatically re-generate with a repair prompt until the output passes or the repair budget is exhausted.

runWithVerification

runWithVerification<T>(generate: GenerateFn<T>, config: VerificationConfig<T>): Promise<VerificationOutcome<T>>

Runs the generate → validate → repair loop. generate(repair?) produces a candidate (receiving a RepairContext with a ready-made repairPrompt on retries); validators run in 'all' mode (every validator must pass). Throws if config.validators is empty.

VerificationConfig:

FieldTypeDescription
validatorsValidator<T>[]Validators to apply (all must pass)
maxRepairsnumber?Max repair attempts after the first try (default from package)
formatRepairPrompt(failures, previousValue) => string?Custom repair-prompt builder
onAttempt(attempt: VerificationAttempt<T>) => void?Called after each attempt
onAbort(abort: VerificationAbort<T>) => void?Called when the loop gives up

VerificationOutcome is either { status: 'ok' | 'repaired', value, attempts, history } or { status: 'aborted', lastValue, attempts, history, reason }.

A Validator<T> is { name, validate(value, context): ValidationOutcome | Promise<ValidationOutcome> }, where ValidationOutcome is { valid, failures: ValidationFailure[] }. Built-in validator factories are exported for common cases: zodValidator / schemaValidator, regexValidator, judgeValidator, semanticAdapter, externalValidator, and composeValidators.

import { runWithVerification, zodValidator } from '@elsium-ai/agents'
import { z } from 'zod'

const schema = z.object({ title: z.string().max(60), tags: z.array(z.string()).min(1) })

const outcome = await runWithVerification(
  async (repair) => llm.completeJson(repair?.repairPrompt ?? 'Summarize the article'),
  { validators: [zodValidator(schema)], maxRepairs: 2 },
)

if (outcome.status !== 'aborted') {
  console.log(outcome.value, `passed in ${outcome.attempts} attempt(s)`)
}

withVerifiers

withVerifiers(base: Agent, verifiers: Validator<AgentResult>[], policy?: AgentRetryPolicy): Agent

Wraps an Agent so that run and generate automatically retry through runWithVerification against the supplied AgentResult verifiers. Failed verification throws an ElsiumError after exhausting the retry budget. The fluent equivalents agent.withVerifier(validator) and agent.withRetryPolicy(policy) are available on every agent returned by defineAgent.

AgentRetryPolicy:

FieldTypeDescription
maxAttemptsnumber?Total attempts including the first (default: 3)
semanticboolean?Enable semantic repair behavior (default: true)
import { defineAgent, judgeValidator } from '@elsium-ai/agents'

const agent = defineAgent({ name: 'writer', system: 'Write concise summaries.' })

const verified = agent
  .withVerifier(judgeValidator({
    rubric: 'The summary must be under 3 sentences and factually grounded.',
    judge: (rubric, value) => myLLMJudge(rubric, value), // { passed, score }
  }))
  .withRetryPolicy({ maxAttempts: 4 })

const result = await verified.run('Summarize the quarterly report')

Confidence (CAG)

Confidence-Augmented Generation voters aggregate multiple samples of the same generation into a single winner plus a confidence score. They plug into selfConsistency({ voter }) (and are usable standalone).

createMajorityVoter / createSimilarityVoter

createMajorityVoter<T>(): Voter<T>
createSimilarityVoter<T>(options: SimilarityVoterOptions<T>): Voter<T>

createMajorityVoter picks the most frequent sample using a canonicalized deep-equality key (order-insensitive for object keys); confidence is the winner’s share of the votes. createSimilarityVoter clusters samples with a caller-supplied similarity function and returns the largest cluster’s representative; confidence is that cluster’s share.

SimilarityVoterOptions:

FieldTypeDescription
similarity(a: T, b: T) => number | Promise<number>Pairwise similarity in [0, 1]
thresholdnumber?Minimum similarity to join a cluster (default: 0.85)

A Voter<T> is { name, vote(samples): VoteResult<T> | Promise<VoteResult<T>> }, where VoteResult is { winner, confidence, details? }.

import { selfConsistency, createMajorityVoter, createSimilarityVoter } from '@elsium-ai/agents'

// Exact-match majority across 5 samples
const exact = selfConsistency({ samples: 5, voter: createMajorityVoter() })
const r1 = await exact.score(async () => ({ value: await classify(input) }))

// Cluster free-text answers by embedding similarity
const fuzzy = selfConsistency({
  voter: createSimilarityVoter({
    similarity: (a, b) => cosineSim(embed(a), embed(b)),
    threshold: 0.9,
  }),
})
const r2 = await fuzzy.score(async () => ({ value: await answer(input) }))
console.log(r2.value, r2.confidence)

Structured Output

agent.generate

agent.generate<T>(input: string, schema: z.ZodType<T>, options?: AgentRunOptions): Promise<AgentGenerateResult<T>>

Runs the full agent loop (tools, guardrails, memory) and parses the final response into a typed object validated against a Zod schema. Throws ElsiumError if the response is not valid JSON or doesn’t match the schema.

AgentGenerateResult<T>

FieldTypeDescription
dataTParsed and validated data
resultAgentResultFull agent execution result
import { z } from 'zod'

const schema = z.object({
  answer: z.string(),
  confidence: z.number(),
  sources: z.array(z.string()),
})

const { data } = await agent.generate('What causes rain?', schema)
// data is fully typed: { answer: string, confidence: number, sources: string[] }

Channels

createWebhookChannel

createWebhookChannel(config: WebhookChannelConfig): ChannelAdapter & { receive(msg): void }

Creates a webhook-based channel adapter. Call receive() to inject incoming messages (e.g., from an HTTP webhook handler).

Config:

FieldTypeDescription
namestringChannel identifier
onSend(userId, message) => voidCallback when agent sends a response

ChannelAdapter

interface ChannelAdapter {
  readonly name: string
  start(): Promise<void>
  stop(): Promise<void>
  send(userId: string, message: OutgoingMessage): Promise<void>
  onMessage(handler: (message: IncomingMessage) => void): void
}

Implement this interface to create custom adapters for messaging platforms (WhatsApp, Telegram, Discord, Slack, etc.).

IncomingMessage:

FieldTypeDescription
channelNamestringWhich channel the message came from
userIdstringUser identifier on the platform
textstringMessage text
attachmentsChannelAttachment[]?Optional attachments
metadataRecord?Platform-specific metadata
rawunknown?Raw platform message

createChannelGateway

createChannelGateway(config: ChannelGatewayConfig): ChannelGateway

Connects channel adapters to agents via a session router. Incoming messages are routed to the correct session, processed by the agent, and responses are sent back through the originating channel.

Config:

FieldTypeDescription
adaptersChannelAdapter[]Channel adapters to connect
routerSessionRouterSession router for thread management
agentAgentDefault agent for all channels
resolveAgent(msg) => Agent?Dynamic agent selection per message
onError(error, msg) => voidError callback
import {
  createWebhookChannel, createChannelGateway,
  createSessionRouter, defineAgent,
} from '@elsium-ai/agents'

const webhook = createWebhookChannel({
  name: 'api',
  onSend: (userId, msg) => sendPushNotification(userId, msg.text),
})

const agent = defineAgent({ name: 'assistant', system: 'You are helpful.' })
const router = createSessionRouter({ defaultAgent: agent })

const gateway = createChannelGateway({
  adapters: [webhook],
  router,
  agent,
})

await gateway.start()

// In your HTTP handler:
webhook.receive({ userId: 'user-123', text: 'Hello!' })

Session Router

createSessionRouter

createSessionRouter(config: SessionRouterConfig): SessionRouter

Maps (channel, userId) pairs to persistent conversation threads with concurrency control.

Config:

FieldTypeDescription
defaultAgentAgentAgent used when none specified
storeThreadStore?Optional persistence for threads
concurrency'serial' | 'parallel'Concurrency mode (default: 'serial')
sessionTimeoutnumber?Auto-expire sessions after ms of inactivity
onSessionCreated(session) => voidCallback on new session
onSessionExpired(session) => voidCallback on session expiry

SessionRouter methods:

MethodReturnsDescription
resolve(opts)Promise<Thread>Get or create a thread for channel+user
getSession(channel, userId)SessionInfo | nullGet session info
listSessions()SessionInfo[]List all active sessions
endSession(channel, userId)booleanEnd a specific session
endAllSessions()voidEnd all sessions and cleanup
import { createSessionRouter, defineAgent, createInMemoryThreadStore } from '@elsium-ai/agents'

const agent = defineAgent({ name: 'support', system: 'You help users.' })
const store = createInMemoryThreadStore()

const router = createSessionRouter({
  defaultAgent: agent,
  store,
  concurrency: 'serial',
  sessionTimeout: 30 * 60 * 1000, // 30 minutes
  onSessionCreated: (s) => console.log(`New session: ${s.sessionId}`),
  onSessionExpired: (s) => console.log(`Expired: ${s.sessionId}`),
})

const thread = await router.resolve({ channelName: 'slack', userId: 'U12345' })
const result = await thread.send('Help me reset my password')

Scheduler

createScheduler

createScheduler(config: SchedulerConfig): Scheduler

Cron-based task scheduler for recurring agent tasks.

Config:

FieldTypeDescription
agentAgentDefault agent for scheduled tasks
resolveAgent(task) => Agent?Dynamic agent selection per task
onComplete(task, result) => voidCallback on successful run
onError(task, error) => voidCallback on failed run
tickIntervalMsnumberCheck interval in ms (default: 60000)

Scheduler methods:

MethodReturnsDescription
schedule(cron, input, opts?)ScheduledTaskSchedule a recurring task
unschedule(taskId)booleanRemove a scheduled task
getTask(taskId)ScheduledTask | nullGet task by ID
listTasks()ScheduledTask[]List all tasks
pause(taskId)booleanPause a task
resume(taskId)booleanResume a paused task
start()voidStart the scheduler tick loop
stop()voidStop the scheduler

parseCronExpression / cronMatchesDate / getNextCronDate

parseCronExpression(expression: string): CronFields | null
cronMatchesDate(fields: CronFields, date: Date): boolean
getNextCronDate(fields: CronFields, after: Date): Date

Cron utilities. Standard 5-field cron syntax: minute hour dayOfMonth month dayOfWeek. Supports *, ranges (1-5), steps (*/15), and comma-separated values (0,30).

import { createScheduler, defineAgent } from '@elsium-ai/agents'

const agent = defineAgent({ name: 'reporter', system: 'Generate a daily summary.' })

const scheduler = createScheduler({
  agent,
  onComplete: (task, result) => sendSlackMessage(result.message.content),
  onError: (task, error) => alertOps(error),
})

// Every day at 9am
scheduler.schedule('0 9 * * *', 'Generate the daily metrics report')

// Every 30 minutes on weekdays
scheduler.schedule('*/30 * * * 1-5', 'Check for critical alerts', {
  name: 'alert-check',
})

scheduler.start()

Agent Identity

Cryptographic agent identity with HMAC-SHA256 signing, replay protection, and cross-agent verification.

createAgentIdentity

createAgentIdentity(config: AgentIdentityConfig): Promise<AgentIdentity>

Creates a cryptographic identity for an agent. Each identity has a unique keypair, can sign payloads with HMAC-SHA256, and verify signatures with timing-safe comparison and replay protection.

Config:

FieldTypeDescription
agentIdstringUnique agent identifier
secretstring?HMAC secret (auto-generated if omitted)
replayWindowMsnumber?Replay protection window (default: 5 min)
import { createAgentIdentity } from '@elsium-ai/agents'

const identity = await createAgentIdentity({ agentId: 'researcher' })

const signed = await identity.sign({ action: 'tool_call', tool: 'search' })

const result = await identity.verify(signed)
// { valid: true }

createIdentityRegistry

createIdentityRegistry(): IdentityRegistry

Central registry for managing and verifying agent identities across a multi-agent system.

import { createAgentIdentity, createIdentityRegistry } from '@elsium-ai/agents'

const registry = createIdentityRegistry()

const researcher = await createAgentIdentity({ agentId: 'researcher' })
const reviewer = await createAgentIdentity({ agentId: 'reviewer' })

registry.register(researcher)
registry.register(reviewer)

const signed = await researcher.sign({ data: 'findings' })
const verification = await registry.verifySignedPayload(signed)
// { valid: true }

Runtime Policy Enforcement

Enforce policies at agent runtime — before each tool call, not just at the HTTP layer.

createRuntimePolicyEnforcer

createRuntimePolicyEnforcer(config: RuntimePolicyConfig): RuntimePolicyEnforcer

Creates a policy enforcer that checks RBAC, tool access, and custom policies before each tool execution inside the agent loop.

Config:

FieldTypeDescription
policiesPolicySetPolicy set from @elsium-ai/core
actorstring?Actor identity for policy context
rolestring?Role for policy evaluation
allowedToolsstring[]?Whitelist of allowed tool names
deniedToolsstring[]?Blacklist of denied tool names
import { createPolicySet, tokenLimitPolicy } from '@elsium-ai/core'
import { defineAgent, createRuntimePolicyEnforcer, toolAccessPolicy } from '@elsium-ai/agents'

const policies = createPolicySet([
  tokenLimitPolicy(10_000),
  toolAccessPolicy(['search', 'read_file']),
])

const agent = defineAgent({
  name: 'restricted-agent',
  system: 'You are a read-only assistant.',
  guardrails: {
    runtimePolicy: {
      policies,
      role: 'viewer',
      allowedTools: ['search', 'read_file'],
      deniedTools: ['delete_file', 'write_file'],
    },
    maxDurationMs: 30_000,
  },
})

Built-in Policy Factories

FactoryDescription
toolAccessPolicy(tools: string[])Restricts tool execution to a whitelist
iterationLimitPolicy(max: number)Limits agent iteration count via policy

Memory Integrity

SHA-256 hash-chained memory stores that detect tampering.

createSecureMemoryStore

createSecureMemoryStore(inner: MemoryStore): SecureMemoryStore

Wraps any MemoryStore with a SHA-256 hash chain. Every message gets a hash binding it to the previous message, forming a tamper-evident chain.

import { createInMemoryMemoryStore, createSecureMemoryStore } from '@elsium-ai/agents'

const inner = createInMemoryMemoryStore()
const secure = createSecureMemoryStore(inner)

await secure.save('agent-1', messages)

const integrity = await secure.verifyIntegrity('agent-1')
// { valid: true, totalMessages: 5, chainComplete: true }

Utility Functions

FunctionDescription
computeMessageHash(msg, index, previousHash)Compute SHA-256 hash for a single message in the chain
verifyMessageChain(messages, hashes)Verify integrity of a complete message chain

Part of ElsiumAI

This package is the agent orchestration layer of the ElsiumAI framework. See the Getting Started guide or the Fundamentals for comprehensive coverage of every feature.

License

MIT