Skip to content

Repository files navigation

Gess

Gess is a Go rules engine. It provides a Rete-based runtime, a Go API for building rulesets, and a .gess file format for defining modules, globals, pure functions, templates, seed facts, rules, and queries outside app code.

The preferred workflow is to keep rule definitions in .gess files, compile them to Go with gessc, and use the generated ruleset from normal Go code.

Status

This repository is under active development. The public API is organized around the rules, session, dsl, and scenario packages.

Requirements

  • Go 1.26.2 or newer, matching the module go.mod.

Quick start

Use the module path github.com/cpcf/gess from Go code. The main public packages are github.com/cpcf/gess/rules, github.com/cpcf/gess/session, github.com/cpcf/gess/dsl, and github.com/cpcf/gess/scenario.

Run the examples from the module root:

go test ./examples/...

Regenerate and test the compiled .gess example:

go generate ./examples/gess-files/order_routing
go test ./examples/gess-files/order_routing

Run gessc directly:

go run ./cmd/gessc \
  -package main \
  -func buildGeneratedRuleset \
  -o examples/gess-files/order_routing/rules_generated.go \
  examples/gess-files/order_routing/rules.gess

Format .gess files with gessfmt:

go run ./cmd/gessfmt -w examples/gess-files/order_routing/rules.gess

.gess workflow

A typical project keeps rules and templates in a source file:

(deftemplate order
  (slot id (type STRING) (required TRUE))
)

(deftemplate routed-order
  (slot order (type STRING) (required TRUE))
)

(defrule route-order
  (order (id ?id))
  =>
  (assert (routed-order
    (order ?id)
  )
  )
)

Compile that file during generation:

//go:generate go run ../../../cmd/gessc -package main -func buildGeneratedRuleset -o rules_generated.go rules.gess

That relative path is for the in-repository examples. In another module, point go:generate at the gessc command however you provide it; the flags are the same.

Use the generated build function from app code:

ctx := context.Background()
ruleset, initials, err := buildGeneratedRuleset(ctx, dsl.Registry{})
if err != nil {
	return err
}

session, err := sess.New(ruleset, sess.WithInitialFacts(initials...))
if err != nil {
	return err
}
defer session.Close()

_, err = session.Run(ctx)

See docs/TUTORIAL.md for a fuller walkthrough based on examples/gess-files/order_routing.

For an interactive edit-and-run workshop, use tutorial/README.md or run go run ./tutorial/cmd/gess-tutorial.

Documentation

The published documentation site is available at https://cpcf.github.io/gess/.

The guides under docs/ cover the engine in depth:

  • Core concepts: templates, facts, rules, activations, the agenda, sessions, rulesets, and queries.
  • The .gess language reference.
  • Go API guide for the rules, session, dsl, and scenario packages.
  • Value JSON: the lossless typed-value contract shared by scenarios, reports, Workbench, and MCP.
  • Scenario and report JSON: the strict, versioned portable artifacts for deterministic scenario inputs and run reports.
  • Explain JSON: the versioned, one-way contract for derivations, why-not reports, and counterfactual runs.
  • Session lifecycle: mutations, runs, queries, snapshots, diagnostics, durable checkpoints, mutation logs, forks, what-if runs, events, focus, and ruleset swaps.
  • Runtime diagnostics JSON: versioned machine-readable graph, memory, agenda, and runtime state.
  • Command-line tools: the gess REPL, gessc, gessfmt, and the gess-mcp stdio server.
  • Advanced behavior: the Rete runtime, aggregates, higher-order conditions, logical support, explanations, backward chaining, and module focus.
  • Examples map: where to start in examples/.
  • Developer guide: repository layout, architecture, tests, and benchmarks.

Session control and observability

Beyond assert/run/query, sessions expose:

  • Agenda introspectionsession.Agenda(ctx) returns pending activations in the exact order Run would fire them, including focus-stack drain order. Use ActivationsForModule to inspect unfocused modules.
  • Bounded runssession.Run(ctx, sess.WithMaxFirings(n)) fires at most n activations and returns RunFireLimit when work remains; Run with WithMaxFirings(1) in a loop single-steps a rule cascade.
  • Trace listenersess.NewTraceListener(os.Stderr) prints one line per event; pass sess.ForEventTypes(...) to WithEventListener to subscribe a listener to a subset of event types (unsubscribed event envelopes are never constructed).
  • Conflict strategysess.WithStrategy(sess.StrategyBreadth) switches equal-salience ordering from recency (depth, the default) to FIFO creation order.
  • Globals — declare typed per-session values with defglobal (or Workspace.AddGlobal), read them as *name* in rule and query expressions and RHS asserts, and bind per-session values with sess.WithGlobals.
  • DSL functionsdeffunction defines pure expression-bodied functions directly in .gess, callable from any condition, test, or query expression; no Go registration needed.
  • Session forksession.Fork(ctx) branches an idle session (facts, globals, graph memory, agenda, refraction, focus, logical support, and demand) for what-if runs without rebuilding.
  • Explain and counterfactualsExplain traces why a fact exists, WhyNot diagnoses a missing activation, and WhatIf runs bounded mutations on an isolated fork and returns its fact/agenda diff.
  • Durable stateCheckpoint plus Restore preserves exact semantic session state across processes; checkpoint-anchored mutation logs add a validated, append-only replay stream.
  • Runtime diagnosticsDiagnostics exports graph, memory, agenda, terminal, query, aggregate, truth-maintenance, and backchain state as typed Go data or versioned JSON.
  • Runtime source spans — rulesets compiled from .gess carry file:line spans into runtime errors (ActionFailureError, expression evaluation) and rule events.

Interactive REPL

cmd/gess provides a shell over the public API:

go run ./cmd/gess repl
gess> load examples/gess-files/order_routing/rules.gess
gess> facts
gess> run 1
gess> agenda
gess> query routes-by-lane lane=expedite

In an interactive terminal, the REPL uses shell-style line editing: up/down arrow history, ctrl-r reverse history search, tab completion, ctrl-l clear-screen, and ctrl-d exit on an empty line. Completion is context-aware for commands, .gess files, loaded templates, rules, queries, fact IDs, fields, modules, and watch event names. History is persisted under the user's state directory.

Piped mode (gess repl < script.txt) is deterministic and exits non-zero if any command fails. Files whose (call ...) actions are not registered load with --stub-calls, which prints stub invocations instead of failing; missing pure functions cannot be stubbed because they affect matching.

Packages

  • rules: public types for templates, conditions, actions, queries, values, and compiled rulesets.
  • session: runtime API for asserting, modifying, retracting, running rules, querying, snapshots, diagnostics, explanations, durable state, forks, events, and logical support.
  • dsl: parser, loader, generated-code support, and registry hooks for .gess files.
  • scenario: strict, deterministic scenario and run-report artifacts plus lossless JSON adapters for rules.Value data.
  • cmd/gessc: command-line compiler from .gess files to generated Go. Generated code embeds each construct's source span verbatim from the input file name passed to gessc, so runtime errors point back at the authored .gess line.
  • cmd/gessfmt: canonical formatter for .gess files.
  • cmd/gess: interactive REPL (gess repl).
  • cmd/gess-mcp: bounded, root-confined stdio MCP server over one session.

Most implementation code lives under internal/engine.

Examples

Examples are in examples/:

  • gess-files: .gess files compiled with gessc.
  • forward-chaining: deriving facts from asserted facts.
  • queries: named query APIs over asserted and derived facts.
  • negation: not conditions.
  • aggregates: accumulate, count, and sum.
  • logical-support: logical assertions and support cascades.
  • backward-chaining: query-driven proof examples.
  • modules-focus: module declarations and agenda focus control.
  • higher-order: exists and forall conditions.
  • vulnerability_management: larger end-to-end example.

Development

Format touched Go files, update source, and run tests after implementation changes:

gofmt -w <touched-go-files>
go fix ./...
go test ./...

For docs-only changes, run the relevant example tests when commands or snippets refer to examples.

References

Gess uses rule-engine concepts associated with Rete-family systems, including Jess and CLIPS. It is a Go-native implementation and is not intended to be a Jess compatibility layer.

License

Gess is licensed under the Apache License 2.0.

About

A forward-chaining rules engine written in Go

Resources

Contributing

Stars

Watchers

Forks

Releases

Contributors

Languages