Skip to content

Function: aggregate()

@kortexya/reasoninglayer


@kortexya/reasoninglayer / aggregate

aggregate(spec): RuleAggregatorDto

Defined in: src/builders/psi.ts:291

Declare engine-side aggregation on a rule head.

The group key, the operator and the feature to aggregate.

string[]

Feature names that define the aggregation group. Proofs agreeing on all of them are merged into one conclusion.

RuleAggregatorOp

One of the five operators in RuleAggregatorOp.

string

The feature whose value is aggregated inside each group.

RuleAggregatorDto

The descriptor to pass as addRule’s aggregator.

ValidationError when groupBy is empty, when a groupBy entry or target is blank, or when target also appears in groupBy — a feature cannot be both the group key and the aggregated value.

Serialization format: snake_case wire keys. The descriptor rides on the REQUEST, not on the head: POST /api/v1/inference/rules takes it as a top-level aggregator and the listing lifts it back onto the rule entry as {"group_by":["customer_id"],"op":"sum","target":"amount"}, never as a feature of the head. Measured on 2026-09-18 — the returned head’s features map holds only customer_id, amount and when.

An aggregating rule has NO OSFQL spelling: the same listing omits osfql entirely for it, while the negation rule beside it carried one. A UI must disable “edit as text” for such a rule rather than guess.

Without the descriptor the rule derives one conclusion PER PROOF; with it, one per group. Measured: three order facts (cust-a 10.0, cust-a 32.5, cust-b 7.25) under DERIVE total_spend(customer_id: ?C, amount: ?A) WHEN order(customer_id: ?C, amount: ?A) with aggregate({ groupBy: ['customer_id'], op: 'sum', target: 'amount' }) produced exactly two rows — cust-a 42.5 and cust-b 7.25.

import { aggregate, psi } from '@kortexya/reasoninglayer';
await client.inference.addRule({
term: psi('total_spend', { customer_id: '?C', amount: '?A' }),
antecedents: [psi('order', { customer_id: '?C', amount: '?A' })],
aggregator: aggregate({ groupBy: ['customer_id'], op: 'sum', target: 'amount' }),
});