concept

Reactive Agents

created 2026-05-28 ai · agents · reactive · event-driven · architecture · mozaik

Reactive Agents

An agent architecture where an agent declares which events it cares about and reacts to them as they arrive — rather than being stepped through a sequence by a controller. Events can be a human message, a function call from the agent’s own model, a reasoning trace from a peer agent, or a tool output from somewhere else. Introduced as the organizing concept of mozaik.

The Shift: Compose, Don’t Orchestrate

Most agent frameworks are orchestration-shaped: a controller (supervisor, graph, state machine) decides whose turn it is and routes between steps. Reactive agents flip this — there is no central controller. Each agent is an independent participant in a shared environment; system behavior emerges from participants reacting to each other’s events concurrently.

“a framework where intelligent behavior is something you compose, not something you orchestrate.”

Orchestrated (langgraph-multi-agent-patterns)Reactive (this)
Who decides next stepController / graph edgesEach agent, independently
CouplingCentral routing logicJust the event contract
Adding a roleEdit the controller/graphWrite one agent, join() it
ExecutionMostly sequential turnsConcurrent reactions

Typed Event Handlers

The key ergonomic move: replace a single generic dispatch (onContextItem(source, item) + branching) with dedicated, default-no-op handlers, so an agent overrides only what’s relevant and reads as a flat “when X → do Y” list:

  • onMessage — plain conversational strings
  • onFunctionCall / onFunctionCallOutput
  • onReasoning
  • onModelMessage

Self vs. external split

Every handler has an external twin fired when a peer (not the agent itself) emits the event: onFunctionCall vs onExternalFunctionCall(source, item), etc. This removes manual if (source === me) checks and separates two distinct intents:

  • self handlers → “act on my own outputs” (record context, run the next inference, execute my tool call)
  • external handlers → “observe / react to others” (a reviewer, a logger, a handoff trigger)

A pure observer is just a participant that overrides only the onExternal* handlers and never runs inference.

Why It’s Interesting

  • Less boilerplate, clearer intent — no branching dispatch; the handler list is the spec of what the agent does.
  • Observers and safety reviewers are first-class — they just listen to peers’ streams (ties into streaming-as-runtime).
  • Open composition — new behavior arrives by adding participants, not by growing a central switch. This is what makes agent-swarms cheap to extend.

Caveats

Emergent, controller-free systems trade explicit control flow for flexibility: reasoning about what will happen is harder than reading a graph, ordering/termination is less obvious, and debugging means tracing event cascades. For strictly sequential pipelines a graph (langgraph-multi-agent-patterns) is often clearer. Reactive shines when concurrency, live observation, and easy role-addition matter.