Getting Started
Installation
bash
npm install @criterionx/core zodbash
yarn add @criterionx/core zodbash
pnpm add @criterionx/core zodCriterion requires Zod as a peer dependency for schema validation.
Your First Decision
Let's create a simple risk assessment decision that classifies transactions based on their amount.
1. Define the Schemas
First, define what data your decision needs:
typescript
import { z } from "zod";
// Input: the data we receive
const inputSchema = z.object({
amount: z.number(),
currency: z.string(),
});
// Output: what we return
const outputSchema = z.object({
risk: z.enum(["HIGH", "MEDIUM", "LOW"]),
reason: z.string(),
});
// Profile: parameters that can vary by context
const profileSchema = z.object({
highThreshold: z.number(),
mediumThreshold: z.number(),
});2. Define the Decision
Now create the decision with its rules:
typescript
import { defineDecision } from "@criterionx/core";
const riskDecision = defineDecision({
id: "transaction-risk",
version: "1.0.0",
inputSchema,
outputSchema,
profileSchema,
rules: [
{
id: "high-risk",
when: (input, profile) => input.amount > profile.highThreshold,
emit: () => ({ risk: "HIGH", reason: "Amount exceeds high threshold" }),
explain: (input, profile) =>
`Amount ${input.amount} > ${profile.highThreshold}`,
},
{
id: "medium-risk",
when: (input, profile) => input.amount > profile.mediumThreshold,
emit: () => ({ risk: "MEDIUM", reason: "Amount exceeds medium threshold" }),
explain: (input, profile) =>
`Amount ${input.amount} > ${profile.mediumThreshold}`,
},
{
id: "low-risk",
when: () => true, // Catch-all rule
emit: () => ({ risk: "LOW", reason: "Amount within acceptable range" }),
explain: () => "Default: amount within limits",
},
],
});3. Run the Decision
Create an engine and run the decision:
typescript
import { Engine } from "@criterionx/core";
const engine = new Engine();
const result = engine.run(
riskDecision,
{ amount: 7500, currency: "USD" },
{ profile: { highThreshold: 10000, mediumThreshold: 5000 } }
);4. Inspect the Result
The result contains the decision outcome and full audit trail:
typescript
console.log(result);
// {
// status: "OK",
// data: { risk: "MEDIUM", reason: "Amount exceeds medium threshold" },
// meta: {
// decisionId: "transaction-risk",
// decisionVersion: "1.0.0",
// matchedRule: "medium-risk",
// evaluatedRules: [
// { ruleId: "high-risk", matched: false },
// { ruleId: "medium-risk", matched: true, explanation: "Amount 7500 > 5000" }
// ],
// explanation: "Amount 7500 > 5000",
// evaluatedAt: "2024-01-15T10:30:00.000Z"
// }
// }5. Get Human-Readable Explanation
Use the explain method for a formatted summary:
typescript
console.log(engine.explain(result));
// Decision: transaction-risk v1.0.0
// Status: OK
// Matched: medium-risk
// Reason: Amount 7500 > 5000
//
// Evaluation trace:
// ✗ high-risk
// ✓ medium-riskComplete Example
Here's the full code:
typescript
import { Engine, defineDecision } from "@criterionx/core";
import { z } from "zod";
// Schemas
const inputSchema = z.object({
amount: z.number(),
currency: z.string(),
});
const outputSchema = z.object({
risk: z.enum(["HIGH", "MEDIUM", "LOW"]),
reason: z.string(),
});
const profileSchema = z.object({
highThreshold: z.number(),
mediumThreshold: z.number(),
});
// Decision
const riskDecision = defineDecision({
id: "transaction-risk",
version: "1.0.0",
inputSchema,
outputSchema,
profileSchema,
rules: [
{
id: "high-risk",
when: (input, profile) => input.amount > profile.highThreshold,
emit: () => ({ risk: "HIGH", reason: "Amount exceeds high threshold" }),
explain: (input, profile) =>
`Amount ${input.amount} > ${profile.highThreshold}`,
},
{
id: "medium-risk",
when: (input, profile) => input.amount > profile.mediumThreshold,
emit: () => ({ risk: "MEDIUM", reason: "Amount exceeds medium threshold" }),
explain: (input, profile) =>
`Amount ${input.amount} > ${profile.mediumThreshold}`,
},
{
id: "low-risk",
when: () => true,
emit: () => ({ risk: "LOW", reason: "Amount within acceptable range" }),
explain: () => "Default: amount within limits",
},
],
});
// Run
const engine = new Engine();
const result = engine.run(
riskDecision,
{ amount: 7500, currency: "USD" },
{ profile: { highThreshold: 10000, mediumThreshold: 5000 } }
);
console.log(result.data); // { risk: "MEDIUM", ... }
console.log(engine.explain(result)); // Formatted explanationNext Steps
- Core Concepts - Understand decisions, rules, and profiles
- Profiles - Learn about profile-driven parameterization
- Examples - See real-world use cases