Annotations are @name(...) style markers placed before rules, custom functions, and test cases.
The engine uses a small built-in set for common behavior such as naming, hints, disabling, and rule salience. You can also declare your own custom annotations and use them for grouping, ownership, team responsibility, tickets, rollout state, or other organizational concerns.
Built-in annotations are interpreted directly by the engine:
@name(...)@hint(...)@disabled(...)@salience(...) for rules onlyCustom annotations are declared up front in the global annotation registry and then become available for typed parsing.
Use the annotation registry on RulesEngine during startup:
import { RulesEngine } from '@samatawy/rules';
RulesEngine.annotationRegistry().register('group', 'string');
RulesEngine.annotationRegistry().register('team', 'string');
RulesEngine.annotationRegistry().register('owner_email', 'email');
RulesEngine.annotationRegistry().register('tags', 'string[]');
RulesEngine.annotationRegistry().register('reviewed_at', 'date');
Available annotation types currently include:
stringnumberbooleandatearrayobjectstring[]number[]boolean[]date[]emailemail[]anyOnce declared, the annotations can be used before rule syntax, function definitions, and test cases.
workspace.addRule(`
@group(pricing)
@team(commercial)
@name(Premium Discount)
IF Order.customer_tier == "premium"
THEN Order.discount_rate = 0.15
`);
workspace.addRule(`
@group(pricing)
@team(finance)
@name(Tax Rate)
IF Order.country == "CA"
THEN Order.tax_rate = 0.13
`);
workspace.addFunction(`
@team(risk)
@owner_email(risk-team@example.com)
@tags(["manual-review", "fraud"])
requires_manual_review(score: number) = score >= 75
`);
suite.addTestCase(`
@group(pricing)
@team(commercial)
@reviewed_at("2026-06-05T10:00:00Z")
TEST { Order: { customer_tier: "premium" } }
EXPECT { Order: { discount_rate: 0.15 } }
`);
Rules and functions can be filtered through their registries.
const pricingRules = workspace.ruleRegistry().getRulesAnnotated('group', 'pricing');
const financeRules = workspace.ruleRegistry().getRulesAnnotated('team', 'finance');
const riskFunctions = workspace.functionRegistry().getFunctionsAnnotated('team', 'risk');
const taggedFunctions = workspace.functionRegistry().getFunctionsAnnotated('tags');
Pass only the annotation name to find all components carrying that annotation, or include the optional value to filter more narrowly.
Custom annotations are useful for:
@group(pricing) or @group(eligibility)@team(commercial) or @team(finance)@owner_email(...)@status(review)@ticket(PROJ-123)Keep custom annotations descriptive and organizational. They should help humans and tooling understand the declared logic, not hide business behavior that belongs in the rule or function itself.
group, team, status, or ticket.For built-in rule syntax and built-in annotations, see Rules Syntax. For custom functions, see Custom Functions. For test-case annotations, see Testing Automation.