API Reference

Until Types

Type definitions for termination predicates, verdicts, snapshots, and combinators in Noetic.

Until

A termination predicate function. Called after each loop iteration to decide whether to stop.

type Until = (snapshot: Snapshot) => Verdict | Promise<Verdict>;

Snapshot

The state visible to an Until predicate at the end of each iteration.

interface Snapshot {
  stepCount: number;
  tokens: {
    input: number;
    output: number;
    total: number;
  };
  elapsed: number;
  cost: number;
  lastOutput: unknown;
  lastText: string;
  history: unknown[];
  depth: number;
  lastStepMeta?: StepMeta | null;
}
FieldTypeDescription
stepCountnumberNumber of iterations completed
tokens.inputnumberTotal input tokens consumed
tokens.outputnumberTotal output tokens generated
tokens.totalnumberTotal tokens (input + output)
elapsednumberElapsed time in milliseconds
costnumberAccumulated cost in USD
lastOutputunknownRaw output from the last iteration
lastTextstringText output from the last iteration
historyunknown[]All previous outputs
depthnumberExecution nesting depth
lastStepMetaStepMeta | nullMetadata from the last step (optional)

Verdict

The return value from an Until predicate.

interface Verdict {
  stop: boolean;
  reason?: string;
  feedback?: string;
}
FieldTypeRequiredDescription
stopbooleanyesWhether to stop the loop
reasonstringnoHuman-readable reason for stopping
feedbackstringnoFeedback to pass to prepareNext for the next iteration

Built-in Predicates

The until object provides factory functions for common predicates:

until.maxSteps(n)

Stops after n iterations.

const stop: Until = until.maxSteps(10);

until.maxCost(usd)

Stops when accumulated cost reaches the USD limit.

const stop: Until = until.maxCost(1.0);

until.maxDuration(ms)

Stops when elapsed time reaches the millisecond limit.

const stop: Until = until.maxDuration(60_000);

until.noToolCalls()

Stops when the LLM responds without making any tool calls. Skips the first iteration (step count < 1).

const stop: Until = until.noToolCalls();

until.verified(fn)

Stops when the verify function returns { pass: true }. Feedback from failed verification is available in the verdict.

declare const verify: VerifyFn;
const stop: Until = until.verified(verify);

until.converged(opts)

Stops when the output text is identical to the previous iteration's output.

const stop: Until = until.converged({ threshold: 1 });

until.outputContains(marker)

Stops when the output text contains the given marker string.

const stop: Until = until.outputContains('DONE');

until.custom(fn)

Wraps any Until function (identity passthrough for documentation purposes).

declare const fn: Until;
const stop: Until = until.custom(fn);

VerifyFn

The verification function used by until.verified():

type VerifyFn = (output: unknown) => Promise<{
  pass: boolean;
  feedback?: string;
}>;
FieldTypeDescription
passbooleanWhether verification succeeded
feedbackstringFeedback for the next iteration (optional)

ConvergeConfig

interface ConvergeConfig {
  threshold?: number;
  embed?: EmbedFn;
  cache?: StorageAdapter;
}
FieldTypeDefaultDescription
thresholdnumber1Similarity threshold. At 1 (default), uses exact string equality. When embed is provided and threshold < 1, uses cosine similarity.
embedEmbedFnEmbedding function. When provided with threshold < 1, enables semantic convergence detection.
cacheStorageAdapterPersist the previous output vector across ephemeral invocations (e.g., Cloudflare Workers).

Combinators

any(...predicates)

Returns an Until that stops when any predicate returns { stop: true }.

declare function anySig(...predicates: Until[]): Until;

all(...predicates)

Returns an Until that stops when all predicates return { stop: true }. Reasons from all predicates are joined with '; '.

declare function allSig(...predicates: Until[]): Until;

Example: Combining Predicates

import { all, any, until } from '@noetic/core';
import type { VerifyFn } from '@noetic/core';

declare const myVerifyFn: VerifyFn;

const stopEarly = any(until.maxSteps(10), until.maxCost(1.0), until.noToolCalls());

const strictStop = all(until.verified(myVerifyFn), until.maxSteps(3));

On this page