docsPackagescortex — Agent Runtime

cortex

cortex is the function-calling agent loop behind SmartChats. It runs an LLM with tools, executes the code the model writes in an injected sandbox, and reports progress as events. It also holds the model registry, agent presets and the voice catalog that the other packages read.

The production agent runs in the browser. The core has no DOM references: the sandbox and the LLM call are passed in, so the same loop runs under Node in the package’s own tests.

The pieces

                ┌─────────────────────────────┐
                │           Cortex            │  run loop, message history
                └──────┬──────────────────────┘
                       │
        ┌──────────────┼────────────────┐
        ▼              ▼                ▼
   ┌─────────┐  ┌──────────────┐  ┌───────────────┐
   │ Runner  │  │ SystemContext│  │ ProcessManager│
   │ (LLM    │  │   Manager    │  │  (child       │
   │  call + │  │  (prompt     │  │   agents and  │
   │  parse) │  │   modules)   │  │   processes)  │
   └─────────┘  └──────────────┘  └───────────────┘
        │
        ▼
   ┌──────────────┐
   │  Sandbox     │  runs generated code (SandboxExecutor)
   │  Executor    │
   └──────────────┘

Quick orientation

import { Cortex, StreamingRunnerV3, SystemContextManager, createIntroModule, createStreamingCodeGenModule } from 'cortex';
 
const scm = new SystemContextManager();
scm.add_module(createIntroModule('SmartChats'));
scm.add_module(createStreamingCodeGenModule());
 
const cortex = new Cortex({
  model: 'claude-haiku-5-5',
  name: 'my-agent',
  sandbox: mySandboxExecutor,   // implements SandboxExecutor
  scm,
  llmCallFn: myLlmCall,         // non-streaming call, used by child processes
});
 
cortex.setRunner(new StreamingRunnerV3({ streamingLlmCallFn: myStreamingCall }));
 
cortex.on('event', (evt) => console.log(evt.type, evt));
 
const reply = await cortex.chat('add 2 + 2');

CortexOps

FieldNotes
modelRegistry key
nameAgent name
sandboxA SandboxExecutor. Required
scmA SystemContextManager. When set, it replaces functions and additional_system_msg
functions, additional_system_msgRequired when scm is not given
providerOptional. Otherwise read from the registry
llmCallFn({ model, input, schema?, schema_name?, signal?, effort? }) => Promise<any>
runnerDefault SynchronousRunner
insightsTelemetry client (optional)
utilitiesPlatform helpers passed to generated code
apiBaseUrlOptional API base URL

Cortex

Cortex extends EventEmitter and emits one event name, 'event', with a type field. Types include turn_start, turn_complete, thought, thought_chunk, response_chunk, response_complete, stream_chunk, stream_end, context_status and workspace_update. With a process manager it also forwards process_spawned, process_output, process_state_change, process_complete, process_agent_event, process_needs_input and process_idle_batch.

Commonly used methods:

MethodDoes
chat(text, maxLoops = 4)Adds the user text and runs the runner. Resolves with the reply
run_llm(loop = 6)Runs the runner on the current history
setRunner(runner)Swaps the runner and rebuilds the system prompt for its output format
cancel()Aborts the running turn
add_user_text_input(text)Appends a user turn
snapshot() / restore(s)Save and restore the context (ContextSnapshot)
getContextStatus()Token use against the model’s context window
getUsage() / resetUsage()Accumulated UsageStats (tokens, costUsd, callCount)
initProcessManager(sandboxFactory)Enables child processes

Runners

A runner owns the LLM call and parses the model output into spoken text, code and thoughts.

RunnerFormatUsed by
StreamingRunnerV3JSON, parsed while it streams by JsonStreamParserThe app’s main agent
StreamingRunnerDelimited text (<<<RESPONSE>>>, <<<CODE>>>, <<<THOUGHTS>>>), parsed by StreamParserEarlier streaming protocol
SynchronousRunnerStructured JSON (CodeOutput schema), parsed after the full responseDefault when no runner is given

Child processes forked by ProcessManager run an internal non-streaming runner (SynchronousRunnerV2, not exported) that uses the delimited protocol through llmCallFn.

StreamingRunnerV3 takes { streamingLlmCallFn }, a function that receives { model, input, max_tokens?, temperature?, effort?, text_format?, signal? } and returns { stream, data }. Because the response field streams first, the voice layer can start speaking before the model finishes writing code.

SystemContextManager

The system prompt is built from context modules. Each module has an id, name and position (0 to 100), and any of system_msg, functions, output_instructions, output_structure, state and a beforeBuild hook.

import { SystemContextManager, createIntroModule, createCodeGenModule, createKnowledgeGraphModule } from 'cortex';
 
const scm = new SystemContextManager();
scm.add_module(createIntroModule('SmartChats'));
scm.add_module(createCodeGenModule());
scm.add_module(createKnowledgeGraphModule());
scm.add_module({
  id: 'my_tools',
  name: 'My Tools',
  position: 50,
  system_msg: 'You can use these tools.',
  functions: [/* Function objects */],
});
 
const { system_prompt, functions, output_structure } = scm.build();

Methods: add_module, remove_module, update_module, update_state, get_module, list_modules, has_module, clone, get_usage, build and build_messages(conversation). build_messages calls each module’s beforeBuild and appends module state as a trailing message.

Module factories:

FactoryArguments
createIntroModule(agentName?, model?)
createCodeGenModulenone
createStreamingCodeGenModulenone
createDynamicFunctionsModulenone
createKnowledgeGraphModulenone
createResponseGuidanceModule(guidance?)
createCodeOutputModulenone
createStreamingOutputModulenone

Sandbox

SandboxExecutor is an interface:

interface SandboxExecutor {
  execute(code: string, context: Record<string, any>, timeout: number): Promise<SandboxResult>;
  initializePersistent(): Promise<void>;
  reset(): Promise<void>;
  destroy(): void;
  abort?(reason: string): void;
  setupEventStream?(handler: (event: SandboxRuntimeEvent) => void): () => void;
  syncWorkspace?(workspace: Record<string, any>): void;
}

SandboxResult has ok, data, error, executionId, logs and events. DEFAULT_SANDBOX_TIMEOUT is exported. The app ships an iframe implementation (apps/smartchats/app/src/IframeSandbox.ts). The package itself ships none.

ProcessManager

initProcessManager(sandboxFactory) lets the agent run work that outlives one turn: child agents and background code. The class is internal (only its types are exported). It forks with fork, lists with ps, reads output with read, stops with kill and forwards input with sendInput.

In the app, the agent reaches these through the functions fork_process, ps, read_process, kill_process and send_process_input, defined in apps/smartchats/app/modules/process.ts.

Model registry

MODEL_REGISTRY covers Anthropic, OpenAI, Google Gemini, xAI and Together-hosted models: context window, max output, dated price periods, effort levels, tier, release and shutdown dates.

import { getModelInfo, calculateCost } from 'cortex';
 
const info = getModelInfo('claude-haiku-5-5');
// { id, provider, contextWindow, maxOutputTokens, prices, effort?, inputPricePer1M, outputPricePer1M, cachedInputPricePer1M, cacheWritePricePer1M, ... }
 
const usd = calculateCost('claude-haiku-5-5', { input_tokens: 1000, output_tokens: 500 });

Prices are USD per million tokens. The flat *PricePer1M fields are the base rates in force now. Billing uses calculateCost(model, usage, provider?, at?, opts?) or getPricesAt, which apply the price period for a date and long-context tiers. usage takes input_tokens, output_tokens, cached_input_tokens and cache_creation_input_tokens.

Other registry exports: getRegisteredModels, getModelsByProvider, getModelByTier, listTieredModels, getSelectableModels, isSelectableModel, resolveSelectableModel, isModelRetired, isModelDisabled, getEffortSpec, supportsEffort, EFFORT_ORDER, getModelMaker, isThirdPartyHosted, modelsReleasedSince, and GPT4O_MINI_TTS_PRICING with estimateGpt4oMiniTtsCost.

Presets, voices and catalog

  • AGENT_PRESETS, DEFAULT_PRESET_ID, getPreset, getPresetOrDefault, findMatchingPreset, resolvePresetIdForAvailability. An AgentPreset bundles aiModel, ttsProvider ('openai' | 'azure') and ttsVoice.
  • VOICE_CATALOG, listVoicesForProvider, listVoiceIdsForProvider, findVoice, listAllVoices.
  • describeModel, listModelCatalog, MODEL_STRENGTHS: the agent-facing view of the registry.
  • Token counting: countTokens, countTokensEstimate, countMessageTokens, getTokenBreakdown.

See also