Crux
API Reference@use-crux/core

@use-crux/core

The base Crux package, package overview, config, registry API, and shared utilities.

@use-crux/core is the base package, every Crux project depends on it. It contains all SDK-agnostic primitives organized into subpath exports. Pick the subpath page that matches what you need:

TypeScript compatibility

@use-crux/core is tested with TypeScript >=5.5 <7. Crux also runs a TypeScript 7 native-preview check with @typescript/native-preview / tsgo, but that is a preview signal rather than a stable support promise.

The public type surface is kept compatible with TypeScript 5.5 so projects do not need the newest compiler just to use Crux definitions.

Config

crux.config.ts options, defaults, stability, and runtime/tooling ownership.

Prompts

prompt, createPrompts, the Prompt type.

Contexts

context, when, match, createContexts.

Tools

tool and SDK-agnostic ToolDef authoring.

Tool Middleware

toolMiddleware, approvalMiddleware, resumable approvals.

Multimodal Content

ContentPart, media sources, text projection, and media errors.

Adapter Interface

defineSingleTurnProviderBundle, defineProviderRuntime, adapter IR, and conformance harnesses.

Cache

createSemanticCache and semantic cache policies.

Retrieval

knowledgeBase, retriever, retrievalRecipe, grounding, and retrieval tools.

Citations

grounding, citationConstraint, resolveCitations.

Indexing

indexer, corpus, canonical documents/chunks, write-time embedding.

Memory

memory, memoryBlock, recentMessages, workingState, episodes, facts, procedures.

Compaction

createSlidingWindow, createBudgetManager, summarizeMessages, extractKeyFacts.

Agent

agent, blackboard, handoff, delegate, compositions.

Flow

flow, signalFlow, cancelFlow, listFlows.

Runtime Engine

node, serverless, createRuntimeHandler, durableTask, runtime diagnostics, and testing helpers.

Plan

plan, plan handles, list, ref, and creation tools.

Tasks

tasks, task, task-ledger handles, and workers.

Skill

skill.inline, skill.fromRegistry, and Node file loading.

Safety

guardrail and constraint primitives for I/O safety and semantic validation.

Scoring

judge, prebuilt metrics, and Safety integration through constraint.judge.

Quality

quality, suite, expect, target, cassette, constraintScorer, and persisted local experiments.

Storage

RecordStore, VectorStore, AssetStore, and storage bundles.

Project Index

Design-plane definitions, relations, source locations, and diagnostics.

Index Lint

Lint config, findings, rule metadata, and suppressions.

Runtime Bridge

Local-dev command-plane schemas and helpers.

Devtools Plugin

withDevtools and enableDevtools.

Subpath imports

import {
  prompt,
  context,
  createPrompts,
  createContexts,
  config,
  when,
  match,
  contentText,
  hasMediaParts,
  messageText,
  textPart,
} from "@use-crux/core";
import { tool } from "@use-crux/core/tools";
import {
  toolMiddleware,
  approvalMiddleware,
} from "@use-crux/core/tool-middleware";
import {
  adapter,
  loopRuntimeAdapter,
  defineProviderRuntime,
  defineSingleTurnProviderBundle,
} from "@use-crux/core/adapter";
import {
  providerRuntimeConformance,
  transcriptCodecConformance,
} from "@use-crux/core/adapter/testing";
import { describeCruxAdapterConformance } from "@use-crux/core/adapter/testing/vitest";
import {
  memory,
  workingState,
  episodes,
  facts,
  procedures,
} from "@use-crux/core/memory";
import {
  createSlidingWindow,
  createBudgetManager,
  extractKeyFacts,
  summarizeMessages,
} from "@use-crux/core/compaction";
import { agent, blackboard, handoff, delegate } from "@use-crux/core/agent";
import {
  flow,
  signalFlow,
  cancelFlow,
  listFlows,
  createFlowId,
} from "@use-crux/core/flow";
import {
  node,
  serverless,
  createRuntimeHandler,
  durableTask,
} from "@use-crux/core/runtime";
import { plan } from "@use-crux/core/plan";
import { task, tasks } from "@use-crux/core/tasks";
import { skill } from "@use-crux/core/skill";
import { guardrail } from "@use-crux/core/safety";
import { constraint } from "@use-crux/core/safety";
import { judge, metrics } from "@use-crux/core/scoring";
import {
  constraintScorer,
  expect,
  quality,
  suite,
  target,
} from "@use-crux/core/quality";
import {
  createSemanticCache,
  semanticCachePolicies,
} from "@use-crux/core/cache";
import { embedding } from "@use-crux/core/embedding";
import {
  knowledgeBase,
  retriever,
  retrievalRecipe,
  retrieve,
  rerank,
} from "@use-crux/core/retrieval";
import { grounding, citationSchema } from "@use-crux/core/citations";
import { corpus, indexer } from "@use-crux/core/indexing";
import {
  CruxProvider,
  usePlan,
  useTasks,
  createSSETransport,
  createPollingTransport,
} from "@use-crux/react";
import { cruxSSEHandler } from "@use-crux/react/server";
import { withDevtools } from "@use-crux/core/observability";
import type { ProjectIndexSnapshot } from "@use-crux/core/project-index";
import { serializeProjectIndex } from "@use-crux/core/project-index/serializers";
import type {
  ContentPart,
  CruxIndexerConfig,
  CruxLintConfig,
  MessageContent,
  ToolModelOutput,
  ToModelOutputArgs,
} from "@use-crux/core";

Tooling Config

Use config() for Crux project policy and explicit runtime behavior: Quality discovery, Project Index lint, Indexer extensions, experimental indexer flags, persistence, generation hooks, devtools, observability, and plugins. Prompts, contexts, tools, agents, flows, registries, and skills remain normal TypeScript exports discovered from source.

See Config for the full crux.config.ts option reference, defaults, stability notes, and crux config inspect behavior.

TypeScript Guarantees

Crux APIs are designed to preserve inference across composition. Context input schemas merge into prompt() inputs, grounded retrieval composes through use, and retriever tool names are typed for common manual cases:

const brand = context({
  input: z.object({ brandVoice: z.string() }),
  system: ({ input }) => `Voice: ${input.brandVoice}`,
});

const answer = prompt({
  use: [brand],
  input: z.object({ question: z.string() }),
  system: ({ input }) => input.question,
});

answer.resolve({
  input: {
    question: "How do refunds work?",
    brandVoice: "Concise and direct",
  },
});

const tools = docs.asTools({
  prefix: "docs",
  include: ["search", "getSource"],
});

tools.docsSearch;
tools.docsGetSource;

@use-crux/core also has a package-local typecheck task that runs strict TypeScript plus compile-time API tests. New production any usage is blocked by an explicit-any checker; existing legacy entries are tracked as debt and should only shrink.

config(config)

The single entry point for configuring Crux project policy and explicit runtime behavior. It applies immediately when the config file is imported. Module caching ensures it runs once per process.

Prompt, context, tool, and registry definitions are authored in normal TypeScript modules and discovered from source by local tooling. They are not repeated in config().

For defaults, stability notes, and every nested option, see Config.

DomainTypeDescription
qualityQualityConfigLocal quality discovery, persistence root, redaction, and run defaults.
lintCruxLintConfigProject Index lint profile and rule overrides.
indexerCruxIndexerConfigExtension references, extension trust policy, and indexer rule options.
experimentalCruxExperimentalConfigUnstable opt-in tooling features such as the TypeScript-Go semantic indexer backend.
persistence.recordsRecordStoreExplicit runtime persistence for flows, plans, and bridge reads.
generation.middlewarePromptMiddlewareGlobal generate/stream wrapper.
generation.tokenizer(text: string) => numberCustom token counting.
generation.autoEscapebooleanAuto-escape top-level XML-like user input fields. Defaults to true.
generation.securityWarningsbooleanWarn on suspicious input patterns. Defaults to development-only.
devtoolsCruxDevtoolsConfigNon-default local, tunnel, remote, or Runtime Bridge behavior.
observabilityCruxObservabilityConfigExplicit observability export, capture policy, or custom transport behavior.
pluginsCruxPlugin[]Composable runtime extensions.

Returns: Crux, exposes the raw .config, lifecycle .dispose(), and compatibility registry methods. Source-discovered projects should use their authored prompt/context exports directly rather than looking them up through config().

config() is one-config-per-process. Calling it again replaces the previous active installation before applying the new one, which keeps hot reload from stacking middleware or duplicating plugin hook fan-out. dispose() restores only the hook layer installed by that config; independent layers such as imperative devtools remain active.

MemberDescription
.configReadonly<CruxConfig>
.dispose()Tear down the Runtime Bridge and restore this config's hooks, plugins, and observability

Observability capture controls live under observability:

config({
  observability: {
    recordInputs: false,
    recordOutputs: false,
  },
});

Both default to true. When disabled, matching artifacts keep sizeBytes and hash but omit inline previews.

Plugin system

import type { CruxPlugin, CruxHooks, CruxPluginResult } from "@use-crux/core";
import { mergeHooks, applyPlugins } from "@use-crux/core";

CruxPlugin

FieldTypeDescription
namestringUnique plugin name for debugging
install(hooks: Readonly<CruxHooks>) => CruxPluginResultInstall hooks into the hook store

CruxPluginResult extends Partial<CruxHooks> with optional dispose?: () => void.

Built-in pluginPackage
withDevtools(options)@use-crux/core/observability, name 'crux:devtools'
withTelemetry(options?)@use-crux/otel, name 'crux:otel'

mergeHooks(base, patch)

Compose two hook states with fan-out semantics:

  • Hooks: both handlers fire for every event
  • Middleware: patch wraps base
  • Collector: last-write-wins

applyPlugins(plugins, initialHooks)

Process an ordered list of plugins. Returns { hooks, dispose }.

Observability context

import { observe } from "@use-crux/core/observability";
import { withSession, createSessionId, createFlowId } from "@use-crux/core";

withSession(sessionId, fn)

Groups all generate() calls within fn under a single session ID for devtools correlation.

createSessionId() / createFlowId()

Generate unique IDs for cross-boundary correlation.

observe.captureContext() / observe.withContext(ctx, fn)

Snapshot and restore observability context across async boundaries. In Convex, prefer @use-crux/convex/server and ctx.crux.runAction() so the boundary helper handles propagation.

Captured observability context

FieldTypeDescription
runIdCruxRunIdCurrent run ID
traceIdCruxTraceIdCurrent trace correlation ID
spanStackCruxSpanId[]Active span stack, deepest last
currentSpanIdCruxSpanId?Deepest open span

Model fallback

import {
  fallback,
  isFallback,
  classifyError,
  shouldAttemptFallback,
} from "@use-crux/core";

fallback(models, options?)

Wraps multiple models into a single reference that tries each in order on qualifying failure.

const model = fallback([gpt4o, claudeSonnet]);
const model = fallback([gpt4o, claudeSonnet], {
  on: ["rate_limit", "timeout"],
  timeout: { attempt: 10_000, firstToken: 2_000 },
});
OptionTypeDescription
idstring?Stable id for Project Index and trace joins
descriptionstring?Human-readable label for docs/devtools
onErrorCategory[]?Which categories trigger fallback (default: all)
shouldFallback(error: Error) => boolean?Custom error predicate (takes priority over on)
when(result) => boolean | Promise<boolean>Successful-result predicate that triggers invalid_response fallback when it returns true
timeout{ attempt?, firstToken? }?Per-attempt and stream first-token budgets in ms
onFallback(info) => void | Promise<void>Called before moving from a failed model to the next one

ErrorCategory = 'rate_limit' | 'timeout' | 'server_error' | 'connection_error' | 'auth_error' | 'invalid_response'

classifyError(error)

Classifies an error into an ErrorCategory or null.

ErrorCategory
HTTP 429rate_limit
HTTP 500–599server_error
HTTP 401/403auth_error
TimeoutError, ETIMEDOUT, AbortErrortimeout
ECONNREFUSED, ENOTFOUNDconnection_error
invalid response predicateinvalid_response
HTTP 400, unknownnull (no fallback)

Validation retry

import {
  ValidationExhaustedError,
  isValidationExhaustedError,
  repairJsonText,
} from "@use-crux/core";
import type { ValidationRetryOptions } from "@use-crux/core";

ValidationRetryOptions

FieldTypeDescription
maxRetriesnumber?Default 3. Each consumes a step from maxSteps.
onRetry(attempt, zodError) => void?Per-retry hook
onExhausted(attempts, lastError) => void?Final-failure hook

ValidationExhaustedError

Thrown when validation retries exhaust. Properties: lastRawOutput, zodErrors, attempts, maxAttempts, promptId.

repairJsonText(text)

Zero-cost JSON text repair. Returns repaired text or null if unfixable.

See the Validation retry guide.

Security utilities

import {
  safe,
  raw,
  limit,
  wrap,
  escapeXml,
  truncate,
  userContent,
  detectSuspiciousPatterns,
} from "@use-crux/core";
FunctionSignatureDescription
escapeXml(text)string → stringEscape <>&"'
truncate(text, max?)string → stringTruncate (default max: 10,000)
safe\...``tagged templateAuto-escape interpolated values
raw(text)string → SafeWrapperSkip escaping inside safe templates
limit(text, max?)string → SafeWrapperTruncate + escape inside safe templates
wrap(text, opts?)string → SafeWrapperEscape + wrap in <user-input>
userContent(text)string → stringStandalone escape + wrap
detectSuspiciousPatterns(text)string → { suspicious, patterns[] }Scan for prompt injection patterns

Embedding

import { embedding } from "@use-crux/core/embedding";

Creates a reusable dense or sparse embedding primitive with built-in batching, governance, and concurrency control. See the Embeddings guide for usage.

Think of embedding() as provider policy, not search policy:

const dense = embedding({ kind: 'dense', ... }) // semantic vector
const sparse = embedding({ kind: 'sparse', ... }) // keyword vector

indexer({ dense, sparse })   // write vectors
retriever({ dense, sparse }) // query vectors

Hybrid search uses both embeddings through retriever() or VectorStore.search(). It is not kind: 'hybrid'.

FieldTypeDescription
kind'dense' | 'sparse'Vector type
namestringEmbedding model name
dimensionsnumber?Required for 'dense'
maxInputTokensnumberHard limit per text
batch{ maxSize?, concurrency? }?Batch behavior
preprocessEmbeddingPreprocessor | EmbeddingPreprocessor[]?Normalization before cache/provider calls
truncate{ strategy: 'fail' } | { strategy: 'chars'; maxChars: number }?Input-limit policy
retry{ maxAttempts; baseDelayMs?; maxDelayMs?; shouldRetry? }?Provider batch retry policy
cacheEmbeddingCache?Policy-aware per-text vector cache
rateLimit{ concurrency: number }?Cross-call provider concurrency cap
countTokens(text) => numberOptional tokenizer for maxInputTokens checks
embed(texts) => Promise<{ embeddings }>Provider call

Hybrid retrieval is composed above this layer through stores or retrievers.

import {
  embedding,
  embeddingCache,
  normalizeText,
} from "@use-crux/core/embedding";

const dense = embedding({
  kind: "dense",
  name: "docs-embedding",
  dimensions: 1536,
  maxInputTokens: 8191,
  batch: { maxSize: 100, concurrency: 3 },
  preprocess: normalizeText({ trim: true, collapseWhitespace: true }),
  truncate: { strategy: "fail" },
  retry: { maxAttempts: 3, baseDelayMs: 250 },
  cache: embeddingCache({ store, namespace: "embed-cache" }),
  rateLimit: { concurrency: 3 },
  embed: async (texts) => ({ embeddings: await provider.embedMany(texts) }),
});

Retrieval

import {
  knowledgeBase,
  retriever,
  retrievalRecipe,
  retrieve,
  rerank,
} from "@use-crux/core/retrieval";

Creates a query-first retriever that turns text into scored hits, prompt context, and query tools. See the Retrieval guide for the full architecture.

Use retriever() as the app-facing search object:

const docs = retriever({
  id: "docs",
  namespace: "product-docs",
  records,
  vectors,
  dense,
  sparse,
  search: { mode: "hybrid" },
});

const hits = await docs.retrieve("refund policy");

const answer = prompt({
  use: [docs],
  system: "Answer from the retrieved docs.",
});
FieldTypeDescription
idstringStable retriever identifier
indexerIdstring?Writer indexer id when it differs from id
namespacestringRequired corpus boundary
recordsRecordStore?JSON record hydration for record-backed retrieval
vectorsVectorStore?Dense, sparse, or hybrid vector search
denseDenseEmbedding?Dense query embedding
sparseSparseEmbedding?Sparse query embedding
retrieve(query, options) => Promise<RetrieverHit[]>?Fully custom retrieval path

Retrievers expose:

  • retrieve(query, options?)
  • inject: 'context' | 'tool' | 'both' when used in prompt({ use })
  • asContext() and asTools() for advanced/manual integrations

Use retrievalRecipe() with the rerank() step when retrieved candidates need model-backed ordering before they reach a prompt, tool, or grounding flow.

Use grounding() from @use-crux/core/citations when retrieval context must become a cited answer contract.

Indexing

import { indexer } from "@use-crux/core/indexing";

Creates the write-time document indexing primitive. It owns chunking, transforms, embedding at write time, and store writes.

FieldTypeDescription
idstringStable indexer identifier
namespacestringRequired corpus boundary
recordsRecordStoreChunk, parent, and corpus record storage
vectorsVectorStore?Dense, sparse, or hybrid vector index
denseDenseEmbedding?Dense write-time embedding
sparseSparseEmbedding?Sparse write-time embedding
chunkerChunker?Override default chunker
transformsChunkTransform[]?Transform chunks before write

Indexers expose:

  • chunk()
  • indexDocuments()
  • indexChunks()
  • deleteSource()
  • clear()

Routing

@use-crux/core/routing exports router, split, retry, fallback, cascade, their type guards, routing receipt helpers, and resolveModel. Stable id fields are optional for execution but recommended for index and trace joins. See the Routing guide for full coverage.

Internal orchestration

@use-crux/core exports orchestration primitives (orchestrateGenerate, orchestrateStream, resolveModel, wrapStreamIterable, withBudget) used by adapter packages. They're stable for adapter authors but not intended for general application code. See Building custom adapters.

Types

import type {
  Prompt,
  AnyPrompt,
  Context,
  PromptConfig,
  ContextDef,
  PromptResolution,
  ResolvedPrompt,
  SystemBlock,
  InspectResult,
  InspectPart,
  DroppedContext,
  GenerationSettings,
  PromptAdaptation,
  ProviderAdaptations,
  ModelInfo,
  PromptHooks,
  PrepareHookArgs,
  GenerateHookArgs,
  ErrorHookArgs,
  PromptMiddleware,
  MergedInput,
  Message,
  FallbackOptions,
  ErrorCategory,
  CruxConfig,
  Crux,
  PromptRegistry,
  FlowScope,
  FlowResult,
  FlowSnapshot,
  FlowSummary,
  StepOptions,
  SuspendOptions,
} from "@use-crux/core";

PromptResolution, SystemBlock, ResolvedPrompt, ModelInfo, and AnyPrompt are re-exported from @use-crux/core for adapter authors who consume .resolve() output directly. Adapter packages constrain their context tuple as readonly Context<z.ZodType>[] (rather than Context<any>[]) so MergedInput<TOwnInput, TContexts> carries through generate() / stream() without explicit type arguments at the call site.

  • Guide: Foundations, mental model and primitives tour
  • Reference: Adapters, execution layer
  • Reference: Storage, persistent RecordStore, VectorStore, and AssetStore implementations

On this page