Loop-control and post-processing knobs.
How a citation quote is matched against its source document during citation verification.
At 1 only an exact normalized-substring match counts, identical to a plain includes()
check. Below 1 (the default 0.7), a quote that fails the exact check falls back to a
windowed string-similarity match and is accepted when the best-scoring document window meets
this threshold — recovering faithful quotes the model lightly reworded or re-punctuated
without accepting quotes whose words are simply absent.
Below this confidence (or with insufficient evidence) a pass/fail verdict is downgraded to needs_review.
Classify relative-date phrasing into a DateIntent, ground a facility-TZ window, and inject it into the agent prompt so the model never does calendar arithmetic. On by default.
The citation (abstain) gate: downgrade a pass/fail verdict to needs_review when it relied on
citations that could not be matched to their source document (or ended up with none). Independent of
enableCitationVerification: with verification on but this off, unverifiable citations are still
dropped but the verdict keeps its status. On by default; production callers may disable it via a flag.
Deterministically verify every citation quote against the authoritative document text before
returning. Fabricated/unverifiable citations are always dropped when this is on. On by default;
only turn off in tests that don't wire up document loading. Whether an unverifiable citation
also downgrades a pass/fail verdict to needs_review is a separate lever (enableCitationGate).
Name the evidence that would satisfy the criterion in the agent's seed turn, from decompose's
suggestedSearchQueries. NOT retrieval guidance — this path has no search tool; it tells the
agent what would count as sufficient. Produced before document selection, so it can name
evidence the selected set lacks, which is why the rendering disclaims absence.
When enableMetadataManifestOnly is on for a signature question, keep fetch_document as
an escape hatch so the agent can escalate to full text. Turn off to force the signatures +
time-tool path only. Default on; only consulted when the metadata-manifest path is active.
The grounding gate: downgrade a definitive verdict (pass/fail/not_applicable) to needs_review when the agent reached it without reading any source document. When off, an ungrounded verdict ships as-is. On by default; production callers may disable it via a flag.
Feed the classified (abstract) date intent into question decomposition so the planner
enumerates cadence steps correctly. AND-gated on enableCalendarAwareness at use sites.
On by default.
Treat an ellipsis (…, ..., [...]) or blank line (\n\n / \r\n\r\n) in a citation
quote as elided text: every fragment must be found in the source document, in document order.
Recovers faithful partial quotes that can never match contiguously. On by default; an eval
can disable it to run a baseline arm.
For signature/completion questions (needsSignature), send only the document listing into
the agent instead of inlining full text — the agent must use get_document_signatures (and
optionally fetch_document when enableFetchDocumentOnMetadata is on). Opt-in experiment;
default off so prod keeps the full-inline path until an eval arm wins.
Resolve a date window PER sub-claim for questions carrying two or more time criteria, instead
of injecting the single whole-question window (which applies one criterion authoritatively and
drops the rest). Falls back to the single window when a question isn't compound. AND-gated on
enableCalendarAwareness at use sites. On by default; exists so an eval can run both arms.
Abstain up front when the patient has no charts at all, instead of paying the preprocess calls and the tool loop to discover there was nothing to grade. Off by default: it changes the returned status for chartless patients.
Let a question's own additional_instructions note reach the prompts. Off by default, so
a note written while the feature was dark cannot start steering verdicts on its own.
Inline clinical synonyms into every search_chart query before embedding it, so a chart
phrasing that differs from the question's wording ("CIWA" vs "withdrawal") matches on the
first search. Trades precision for recall, so it ships off and is A/B'd.
Keep the system prompt run-constant by moving the per-question content (restated question, sub-claims, hints, date windows) into the seed turn AFTER the documents. Everything the provider can cache then precedes the first per-question byte, so the documents cache too across the questions of a run that select the same set. Pass/fail only — the summary agent keeps the per-question content in its system prompt. Ships off: it reorders the prompt, and the measured win is cache-rate, not yet a demonstrated cost saving.
Precompute the signatures on the selected documents — signer, capacity, and hours from admission — into the agent's opening turn, so it neither extracts them nor does the arithmetic. Elapsed hours only: the threshold lives in the question, and "upon admission" has no agreed tolerance to encode here.
Replace the single tool loop with a map-reduce: one gatherer agent per decomposed sub-claim, each in its own context, then one judge agent that writes the verdict from their pooled evidence. The judge keeps the full toolset because sub-claims are often relational — "signed within 72h of admission" is a comparison BETWEEN claims that no single gatherer can see.
Give each gatherer the document manifest without inlined text, so it must fetch_document
what it relies on. Handed the full text a gatherer skips the read, which leaves it looking
ungrounded — the grounding check counts tool reads, not inlined context.
The verification (abstain) gate: downgrade a pass/fail verdict to needs_review when the
self-critique verify pass found the evidence insufficient, disagreed the evidence supports the
status, or was below confidenceThreshold. When off, the verifier's adjusted status ships as-is
(the verify pass still runs). On by default; production callers may disable it via a flag.
Tool-loop bound for the judge. It starts with the gatherers' evidence in hand, so it needs far fewer turns than a cold loop; the cap is what stops it silently redoing the whole search and paying for the fan-out twice.
Upper bound on sub-claims that will fan out. Above this the reduce prompt bloats and cost stops being predictable, so the runner falls back to the single-agent loop. Fan-out also needs at least 2 claims to be worth anything — below that it is pure overhead.
Bounds the tool loop so a runaway agent can't spin forever.
Reranker model used by search_chart when tools.enableRerank is on (Pinecone Inference).
Only bge-reranker-v2-m3 is currently hosted.
Candidate chunk pool search_chart gathers across the vector stores before reranking down to
limit. Only consulted when tools.enableRerank is on; a wider pool gives the reranker more
to reorder at the cost of one rerank call.
Tool-loop bound for one gatherer. Much tighter than recursionLimit because a gatherer
works a single atomic claim; sizing it near recursionLimit / N keeps the worst-case turn
bound comparable to the single-agent loop.
Toolset selection. Flag-gated tools: fetch_document, get_document_signatures,
is_within_hours / get_difference_in_hours, build_timeline. list_documents and
search_chart are not built at all — see tools.ts. The metadata-filter / rerank levers
below are inert while search_chart is off.
Include fetch_document. Default on. The runner may turn this off for a metadata-manifest
run when settings.enableFetchDocumentOnMetadata is false.
Experimental: when on, search_chart exposes a fileNames param and pushes it down as a
real Pinecone file_name metadata filter instead of relying only on the best-effort JS
post-filter. Default off.
Experimental: when on, search_chart over-fetches a candidate pool (searchCandidatePoolSize
instead of limit) and reranks it with a Pinecone reranking model before returning the top
limit. Default off: the over-fetch plus the cross-encoder call is paid on every search, and
the ranking win over plain semantic top-k has not been measured. Turn it on per-arm to A/B it.
Include the structured get_document_signatures tool.
Include the build_timeline tool (a chronological event index of the whole chart).
Include the is_within_hours / get_difference_in_hours time tools.
OptionalmodelOverride: PromptModelConfigProtected Optional ReadonlymodelProtected ReadonlyoutputStructured shape the loop must return. Typed as LangChain's interop schema so
createAgent's overload infers T = TOutput directly (no cast). Subclasses still
declare it with z.object(...), which is assignable to InteropZodType<TOutput>.
ProtectedrecursionBounds the tool loop. Override to widen/narrow.
Protected ReadonlysnapshotCommitted cold-start snapshot for the system prompt (hub name, template, model).
Hub identifier — derived from the committed snapshot.
ProtectedbuildThe seed messages for the loop. Defaults to a single user turn.
ProtectedbuildBuild the ChatOpenAI instance. Default uses override → resolved hub/snapshot model. Tests override this to inject a fake.
ProtectedbuildThe tools the agent may call. May be empty. Optional runner ctx threads into .toTool(ctx).
Optionalctx: RunnerContextProtectedbuildThe seed user turn for the loop. Override buildMessages for full control.
Optionalctx: RunnerContextProtectedsystemOptional verbatim system prompt. When it returns a non-empty string, the agent uses it as-is, bypassing the hub and variable formatting. Defaults to none.
ProtectedsystemPure: map typed input to the system-prompt template's variables.
ProtectedtraceOptional non-PII trace inputs for the child span.
The deep chart-review agent for pass/fail (grading) questions: a
createAgenttool loop that gathers and verifies evidence, then returns a structured verdict (agentPassFailAnswerSchema). The runner self-critiques and gates that verdict downstream.Monomorphic in its output, so pass/fail and summary are two classes (a unioned
responseFormatbreakscreateAgent's overload inference). Everything except the answer schema/name is shared behavior via../buildSystemPromptand../tools.