Developers

Integration

The engine is an async generator. Hand it a case and its dependencies, then read events as each criterion resolves.

Run a case in a dozen lines

Dependencies are injected, so the engine never reads an env var or touches the network itself.

run-a-case.ts
import { runEngine } from "@/lib/engine";
import { getLlmClient } from "@/lib/llm/client";
import { createTrace } from "@/lib/trace";
import { loadCase } from "@/lib/fixtures";

const input = loadCase("aetna-0743-lumbar");
const trace = createTrace({ caseId: input.caseId });

for await (const event of runEngine(input, {
  llm: getLlmClient(),
  trace: trace.sink,
})) {
  if (event.type === "criterion_resolved") {
    const { criterion, verdict, cite } = event.result;
    console.log(criterion.id, verdict, cite?.quote ?? "no span");
  }
}

await trace.flush();

Three seams

Inject the model

Pass any client that satisfies the LlmClient interface. The engine is provider-agnostic.

Inject the trace

Give it a trace sink and every span is recorded. Leave it out and the run still works.

Stream the events

Consume the generator directly on the server or forward the events to the browser.