Skip to main content
The harness turns model responses into a bounded, inspectable loop.

Definition

The harness is the control layer around the model. It decides what context and tool schemas to send, executes requested tools through the registry, returns results to the model, and records the work shown with the answer. It is a linear loop, not a planner graph, critic swarm, or sub-agent hierarchy.

Architecture

For each question, the harness builds a system prompt from the workspace catalog and schema, optional root fella.md, recent conversation context, and learned folder notes. The user question follows as a separate message. If no workspace is available, the model receives no tool schemas. With a workspace, it receives only the fixed built-in registry for that run; the registry has no runtime connector or plugin expansion path.

Flow

1

Ask the model

Fella streams the response. The model can return text, tool calls, or both.
2

Execute calls

Exact duplicate built-in calls reuse their result within the run. Other calls from the same response execute concurrently and are returned in call order.
3

Record evidence

Each call produces an evidence item with its arguments, summary, timing, result data, and error where applicable.
4

Repeat or finish

Tool results enter the next model turn. A response with no tool calls moves to verification and completion.
The control flow is intentionally linear. This abbreviated excerpt shows the important ordering without the error-handling branches:
This is a documentation excerpt, not a drop-in function: the production loop also races model calls against cancellation, handles partial model failures, memoizes exact duplicate built-in calls, emits UI events, and performs the final no-tool turn after the step cap. The implementation is in agent::run. EngineState::ask_once and ask_once_usage are separate evaluation helpers. They make one tool-free model call for judge/baseline measurements and are not used by the interactive product path; they do not create evidence or run verification.

Behavior

The prompt tells the model to prefer SQL for tables, search or read documents directly, reserve Python for analysis SQL cannot express, avoid unsupported figures, and stop once it has enough evidence. These are behavior instructions, not enforcement boundaries. Deterministic verification always runs when the harness finishes an answer. A changed or failed SQL rerun can trigger one tool-free corrective turn. If checks still contain a warning, a separate default-on self-consistency path can request one stricter tool-free second opinion; FELLA_SELF_CHECK=0 disables it.

Guidance versus enforcement

Limits

  • The default hard cap is 20 tool-calling iterations (FELLA_MAX_STEPS). At the cap, the harness requests one final answer with tools disabled.
  • Soft stop pressure begins after the normal three-round-trip budget (FELLA_SOFT_STOP).
  • Older tool results are elided as history grows and can be queried again.
  • Stop cancels the active model request, keeps collected evidence, and returns Stopped.
  • Prompt rules still do not define the Python capability boundary. The embedded WASM guest has no OS imports; Wasmi limits the guest and the host exposes only output, entropy for interpreter startup, and bounded read-only SQL.
  • Verification can identify evidence and query-shape problems, not resolve every ambiguous interpretation.
The major loop changes were introduced incrementally: PR #39 added the scored evaluation harness, PR #95 added escalating stop pressure, PR #97 added the cost-gated second opinion, and PR #134 added the current depth/aside prompt behavior. The current code, not any one historical PR description, is authoritative.

Next steps

Built-in tools

See what the harness can execute and which boundaries each tool enforces.

Verification

Separate deterministic checks from model-based second opinions.