Skip to content
docs
Arxo ↗

Query types

For LLMs10 sections

One request shape, seven question kinds. The kind says what the engine does with the facts: check a claim, compute a value, count days, explain a gap, or list what the case requires. This chapter says when to use each, what the answer carries, and which exist in Python.

TypeScript
export type AskRequest = {
kind: 'truth' | 'focused_truth' | 'why_not' | 'collect' | 'calendar_op' | 'term' | 'positions';
predicate?: string;
args?: FactArg[];
caseInput: CaseInput;
queryId?: string;
caseName?: string;
extra?: Record<string, unknown>;
};
TypeScript
truth(predicate: Rel, args: FactArg[], caseInput: CaseInput): Promise<Answer>;
Python
def truth(self, predicate: str, args: list[Any], case_input: dict[str, Any]) -> Answer: ...

Use truth to check a complete claim: does the period end on 20 March. The answer carries truthStatus — one of TRUE_ONLY, FALSE_ONLY, BOTH, NEITHER — with the proof of what fired. The candidate date is yours; the engine only judges it.

JavaScript
await fristen.truth('frist_ende', ['frist', '2026-03-20'], caseInput);
// COMPUTED, TRUE_ONLY
await fristen.truth('frist_ende', ['frist', '2026-03-21'], caseInput);
// COMPUTED, NEITHER — the wrong date is supported by nothing

focused_truth — the same answer, sliced by the question

Section titled “focused_truth — the same answer, sliced by the question”
TypeScript
focusedTruth(predicate: Rel, args: FactArg[], caseInput: CaseInput): Promise<Answer>;

The same answer as truth, with the proof and the issues reduced to the question’s cone only. The answer is marked focused_truth and carries a focus manifest instead of the full proof graph. It is not an audit document: a sliced answer has no full result hash. Python does not ship this kind; ask truth instead.

TypeScript
whyNot(predicate: Rel, args: FactArg[], caseInput: CaseInput): Promise<Answer>;
Python
def why_not(self, predicate: str, args: list[Any], case_input: dict[str, Any]) -> Answer: ...
def whyNot(self, predicate: str, args: list[Any], case_input: dict[str, Any]) -> Answer: ...

Use why_not when truth answered NEITHER and the application must ask the user for more. The answer carries whyNot: one blocker per candidate rule, each with its applicability, a summary trigger, and the state of every conjunct. Compare the premises with the facts you supplied and the gap is named.

JavaScript
const w = await fristen.whyNot('frist_ende', ['frist', '2026-03-20'], partial);
w.value.value.blockers;
// two blockers: TagesfristEnde waits on frist_ereignis and frist_dauer_tage,
// Verlegung193 waits on frist_ende_kalender

On the partial frist case — the duration fact removed — the report holds exactly two blockers. Term errors of candidate rules, if any, are reported next to them in whyNotTermErrors.

TypeScript
collect(predicate: Rel, args: FactArg[] | { args: FactArg[]; free?: unknown }, caseInput: CaseInput): Promise<Answer>;
Python
def collect(self, predicate: str, args: Any, case_input: dict[str, Any]) -> Answer: ...

Use collect to compute rather than check: on which day does the period end. The free position is named with ?name in the argument list, or passed explicitly as free with args as a dict. The answer carries the bindings in value.

JavaScript
const end = await fristen.collect('frist_ende', ['frist', '?end'], caseInput);
end.value[0].value; // '2026-03-20'

Choose collect when the application does not have a candidate, and truth when it does — a form that asks “when does it end” collects, a form that asks “does it end on this day” checks.

TypeScript
deadline(
opArgs: { date: string; days?: number; unit?: 'business_day' | 'calendar_day'; afterTime?: string; policy?: unknown; suspensions?: Array<{ start: string; end: string }> },
caseInput: CaseInput,
): Promise<Answer>;
Python
def deadline(self, op_args: dict[str, Any], case_input: dict[str, Any]) -> Answer: ...

Use deadline for the calendar operation itself: a start date plus a number of days under a counting policy. The policy defaults to the case’s deadlinePolicy. Python sends the operation as {"op": "deadline", **op_args}. The answer carries the computed date in value.

TypeScript
calc(term: unknown, caseInput: CaseInput): Promise<Answer>;
Python
def calc(self, term: Any, case_input: dict[str, Any]) -> Answer: ...

Use calc to evaluate a term — an amount, a comparison, an aggregate over the case — without asking a predicate. The term travels in the request and the answer carries its value. A term that needs the case’s counting policy reads deadlinePolicy from the context.

TypeScript
positions(caseInput: CaseInput): Promise<Answer>;
Python
def positions(self, case_input: dict[str, Any]) -> Answer: ...

Use positions to list the duties the facts give rise to and their statuses, without naming a predicate. The answer carries them in positions on the Python shape and in the value on the TypeScript shape.

TypeScript
unfold(predicate: Rel | string, options?: { lang?: string; depth?: number; quote?: number; fold?: boolean }): { tree: unknown; text: string };
questions(lang?: string): FormManifest;

Neither executes a rule. unfold returns the tree of producers of a predicate over the package’s world — every rule, its strength, the provision it is anchored to, and the facts it needs — plus the text the engine prints for it. questions returns the canon’s inventory: the questions that can be asked, the facts that can be supplied, their parameters with types and widgets, and the author’s labels. Both are TypeScript-only; Python reads the inventory at author time instead, as the Python chapter describes.

KindTypeScriptPython
truthtruthtruth
focused_truthfocusedTruth—
why_notwhyNotwhy_not / whyNot
collectcollectcollect
calendar_opdeadlinedeadline
termcalccalc
positionspositionspositions
unfoldunfold—
manifestquestions— (author-time workaround)
  • collect needs exactly one free position: ?name inline or an explicit free.
  • deadline without a policy — neither in the operation nor in the case — answers that the policy is missing; the engine never assumes how days are counted.
  • focused_truth answers are slices: same verdict, reduced proof, no full result hash.

Documentation for Arxo. Writings — blog.arxo.io.

Anonymous visit counts on stats.arxo.io, no cookies.