reactive

package
v0.9.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 20, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package reactive turns events on the domain-event spine into agent cognition: it subscribes to the bus, filters events through a salience gate and loop guard, and wakes the matching agent via the interpreter. See docs/reactive-agents-design.md.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Classifier

type Classifier interface {
	Salient(ctx context.Context, agentName, wakePrompt string, e events.Event) (salient bool, reason string)
}

Classifier is the optional tier-2 salience gate (§5.2): a cheap model check that runs after the rules tier passes, for triggers that opt in with `gate: model`. reason is recorded in the audit log.

type Config

type Config struct {
	Bus      *events.Bus
	Dispatch Dispatcher
	Triggers TriggerRegistry
	Guard    *LoopGuard
	// Classifier, if set, is the tier-2 salience gate for triggers that opt in
	// with `gate: model`. Nil means rules-only (the gate is a no-op).
	Classifier Classifier
	// Prepare decorates the dispatch context per agent — e.g. attaching memory
	// via serve.ContextWithMemory. Nil means identity.
	Prepare func(ctx context.Context, agentName string) context.Context
	// Audit, if set, receives one Record per (agent, event) considered.
	Audit func(Record)
	// AfterWake, if set, runs when a reactive wake completes, with the agent's
	// result. serve uses it for end-of-wake consolidation — the self-learning
	// write-back that makes a short reactive burst leave a trace in memory
	// regardless of length (§3.4). Runs even if the wake returned an error
	// (result may be empty), so a failed reaction is still remembered.
	AfterWake func(ctx context.Context, agentName string, e events.Event, result string)
}

Config wires a Router. Only Triggers is required for evaluate(); Bus and Dispatch are required for a live Start().

type Dispatcher

type Dispatcher interface {
	SendToAgent(ctx context.Context, agentName, message string) (string, error)
}

Dispatcher wakes an agent with a message. The dsl.Interpreter satisfies this via SendToAgent; the router depends only on the method, not the interpreter.

type LoopGuard

type LoopGuard struct {
	// contains filtered or unexported fields
}

LoopGuard enforces, independently of the salience gate, the limits that keep a reactive fleet from running away: chain depth, per-agent rate, and dedup of identical events. It is safe for concurrent use.

func NewLoopGuard

func NewLoopGuard(cfg LoopGuardConfig) *LoopGuard

NewLoopGuard builds a guard from cfg. Now defaults to time.Now.

func (*LoopGuard) Allow

func (g *LoopGuard) Allow(agentName string, e events.Event) (bool, string)

Allow reports whether a wake for the given agent and event should proceed. On rejection it returns a short reason ("depth", "dedup", or "rate") suitable for the audit log. Checks run cheapest-first; depth needs no lock.

type LoopGuardConfig

type LoopGuardConfig struct {
	MaxDepth      int           // reactive-chain depth cap (0 = unlimited)
	RatePerWindow int           // max wakes per agent per RateWindow (0 = unlimited)
	RateWindow    time.Duration // sliding window for the rate limit
	DedupWindow   time.Duration // drop identical payloads seen within this span (0 = off)
	Now           func() time.Time
}

LoopGuardConfig configures the reactive safety backstop (§5.3). A zero or negative value disables that dimension.

type Record

type Record struct {
	Agent   string
	EventID string
	Type    string
	Fired   bool
	Reason  string // "" when fired; otherwise gate/guard/error reason
}

Record is one audit entry: what the spine made an agent consider, and whether it acted or was gated out (and why). Silent suppression is a bug — §7.

type Router

type Router struct {
	// contains filtered or unexported fields
}

Router subscribes to the event spine and turns matching events into agent wakes, filtered by the salience gate and loop guard.

func NewRouter

func NewRouter(cfg Config) *Router

NewRouter builds a Router from cfg. It does not subscribe until Start.

func (*Router) Start

func (r *Router) Start(ctx context.Context)

Start subscribes to the bus (durable — a reactive trigger must not miss a creak) and dispatches wakes until ctx is cancelled.

type Trigger

type Trigger struct {
	On     string
	Where  string
	Gate   string
	Prompt string
}

Trigger is one reactive subscription declared on an agent: when an event of type On (a glob) arrives and its optional Where predicate holds, the agent wakes with Prompt (a template) rendered against the event. Gate selects the salience tier ("" = rules only, "model" = add the cheap classifier, §5.2).

This is the canonical type; the Agent blueprint carries a []Trigger (D1).

type TriggerRegistry

type TriggerRegistry interface {
	ReactiveTriggers() map[string][]Trigger
}

TriggerRegistry provides the current agent→triggers map. Backed by the agent registry in production so there is no separate subscription store (D1).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL