Patterns
Patterns are the agent’s loop shape. Built-ins self-register via register_pattern in packages/harness/src/felix/patterns/ (felix-run/felix).
Built-ins
| Pattern | Kind | Behavior |
|---|---|---|
| react (default) | single | Sequential tool-calling loop bounded by recursion_limit |
| deep | single | react + plan tools (plan_create / plan_update_step / plan_get) + planning prompt suffix |
| router | multi | Classifier picks one sub_agents child; forwards thread_id |
| parallel | multi | Fan-out all children, then aggregator synthesis; parent owns the session |
| groupchat | multi | Round-robin speakers sharing a parent transcript (max_turns) |
| reflect | single | react + verifier model; below-threshold critique replays up to max_iterations |
| plan_execute | single | Planner decomposes → per-subtask react executor → synthesis; optional replan |
react (default)
- Open session;
SessionStrategyrenders the working set (full_replay/windowed:N/summarizing:N/semantic:N/compacting). - Persist new caller turns.
- Loop: optional JIT tool retrieval → token-budget checks →
model.chat/stream_chat→ sequential tool dispatch through governance-wrapped executors → persist events. - Stop on non-
tool_use, fatal tool, or recursion exhaustion.
Streaming uses an async generator: text deltas yield; the final structured result (tool calls + usage) is the generator return value — no second non-stream call.
Multi-agent thread discipline
| Pattern | Session ownership |
|---|---|
| react / deep / reflect | Opens {tenant_id}:{suffix}; appends as events are produced |
| router | Forwards thread_id to the chosen child |
| parallel / groupchat / plan_execute | Parent owns the transcript; children run without writing the parent session (avoids concurrent append races) |
Shared contracts
- Deny strings, not throws — governance returns model-visible deny content so the loop can adapt.
- Sequential tool dispatch — deterministic audit order; limit counters don’t race.
- Orthogonal bounds —
recursion_limitcaps loop steps;spec.limitscaps aggregate work (tool calls, wall clock, peer hops, tokens). - Durable —
spec.execution.mode: durablewraps any pattern so invoke enqueues a fiber / Temporal run (see architecture).
Pick reflect when one shot might be right and you want quality via replay. Pick plan_execute when the task is multi-phase and a single react loop loses the plot — pair with procedural_memory for planner few-shots.