Skip to content

Rule Engine

The rule engine evaluates if-this-then-that rules at BeforeAgentTurn (priority 100, after routing at priority 50). It can block, dispatch, or pass messages based on keywords, channels, or user identity.

Overview

inbound message

    ▼  (priority 50)   RoutingHook    — tag detection, tool restriction, context injection

    ▼  (priority 100)  RuleEngineHook — rule file evaluation

         ├── no rule matched      → Continue (LLM handles it)
         ├── PassToDefaultAgent   → Continue (explicit pass-through)
         ├── Ignore               → Block
         ├── StartWorkflow(..)    → Continue + workflow dispatched
         └── RunNativeAction(..)  → Continue + native action dispatched

Rules and routing are distinct features that both run pre-LLM. Use routing to shape the prompt (detect tags, inject context, restrict tools). Use rules to make decisions about message handling (block spam, dispatch to workflows, route by channel).

Config File

Rules live in a dedicated TOML file, separate from ugent.toml:

toml
# ugent.toml
[rule_engine]
enabled = true
rules_path = "~/.ugent/rules.toml"

At BeforeAgentTurn, the engine builds a match context from the inbound message and evaluates rules in descending priority order. The first rule whose condition matches fires its decision; the rest are skipped.

Rule file edits are hot-reloaded — no restart needed.

Quick Start

toml
# ~/.ugent/rules.toml

# Keyword-based workflow dispatch: messages mentioning "report" trigger the report workflow.
[[rules]]
priority = 100
name = "report-trigger"
[rules.condition]
type = "any_of"
conditions = [
  { type = "keyword", value = "report" },
  { type = "keyword", value = "summary" },
]
[services.decision]
type = "StartWorkflow"
workflow = "daily-report"

Conditions

TypeDescriptionKey Fields
keywordMatches if the message contains the keyword (case-insensitive)value
channelMatches the message source channelvalue (e.g., slack, discord, web)
source_typeMatches the sender typevalue (e.g., user, bot)
user_idMatches a specific uservalue
all_ofBoolean AND — all sub-conditions must matchconditions (list)
any_ofBoolean OR — any sub-condition must matchconditions (list)
notBoolean NOT — inverts the sub-conditioncondition

Decisions

TypeDescription
PassToDefaultAgentExplicitly pass the message to the LLM (default behavior)
IgnoreSilently drop the message
StartWorkflowDispatch the message to a named workflow
RunNativeActionRun a built-in native action (e.g., memory_compaction, memory_extraction)

Example: Channel Filtering

Only allow messages from Slack and Discord; ignore everything else:

toml
[[rules]]
priority = 200
name = "channel-whitelist"
[services.condition]
type = "not"
condition = { type = "any_of", conditions = [
  { type = "channel", value = "slack" },
  { type = "channel", value = "discord" },
] }
[services.decision]
type = "Ignore"

Example: Per-User VIP Routing

Route messages from a specific user to a premium workflow:

toml
[[rules]]
priority = 300
name = "vip-routing"
[services.condition]
type = "all_of"
conditions = [
  { type = "user_id", value = "U12345678" },
  { type = "channel", value = "slack" },
]
[services.decision]
type = "StartWorkflow"
workflow = "premium-support"

Example: Boolean Logic

Combine conditions with nested boolean logic:

toml
[[rules]]
priority = 150
name = "complex-rule"
[services.condition]
type = "all_of"
conditions = [
  { type = "channel", value = "web" },
  { type = "any_of", conditions = [
    { type = "keyword", value = "pricing" },
    { type = "keyword", value = "demo" },
  ] },
  { type = "not", condition = { type = "keyword", value = "internal" } },
]
[services.decision]
type = "StartWorkflow"
workflow = "sales-handoff"

This rule matches web messages that mention "pricing" or "demo" but do NOT contain "internal".

Hot Reload

Editing rules.toml takes effect immediately — the engine watches the file and reloads on save. No restart needed.

Routing vs Rule Engine

RoutingRule Engine
Priority50 (runs first)100 (runs after routing)
PurposeShape the promptMake message-handling decisions
Can rewrite textYes (rewriters)No
Can restrict toolsYes (per-turn)No
Can block messagesYes (intent-reject)Yes (Ignore)
Can dispatch workflowsYes (delegate-research)Yes (StartWorkflow)
Config filerouting.tomlrules.toml
Config sectionTop-level [routing][rule_engine] in ugent.toml

Use both together: routing enriches and shapes the prompt, then the rule engine decides whether to pass it to the LLM or dispatch to a workflow.

Released under the Private Beta License.