# LoopX Architecture Explained: Local-First Control-Plane Design for AI Agents

> Discover the LoopX architecture: a local-first control plane design separating state management from execution runtimes across six layers. Learn its four runtime responsibilities.

- Repository: [huangruiteng/loopx](https://github.com/huangruiteng/loopx)
- Tags: architecture
- Published: 2026-08-13

---

**LoopX is built around a local-first, provider-neutral control-plane that separates durable state management from execution runtimes through six distinct layers and four strict runtime responsibilities.**

The `huangruiteng/loopx` repository implements a novel **loopx architecture** that treats the control-plane as an effect interpreter, ensuring long-running AI agents maintain durable state independently of their execution hosts. This design enables recovery from crashes, provider neutrality, and fine-grained compute quota management through typed contracts.

## Six Durable Control-Plane Layers

The foundation of the LoopX architecture rests on six durable layers that form the source of truth for all agent work. These layers are more than storage; together they function as an **effect interpreter** that mediates between model requests and host execution (see [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md), lines 48‑61).

The *read model* (`A`) consists of the **Registry**, **Goal State**, and **Run History**. The *projection* (`F[B]`) comprises the **Status/Attention Queue** and compact run summaries. The *decision* logic (`A => F[QuotaDecision]`) lives in the **Kernel**, which determines whether a turn runs, what gates apply, and what scheduler hints to emit.

| Layer | Purpose | Key Docs |
|-------|---------|----------|
| **Registry** | Lists known goals, repositories, adapters, authority sources, status, and guards. | [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md) |
| **Goal State** | Holds the active state file for a single goal, including objectives, scopes, gates, todos, evidence, and quota. | [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md) |
| **Run Log** | JSON and Markdown reports saved per goal, creating an audit trail of execution. | [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md) |
| **Run History** | Compact indexes consumed by agents, heartbeats, and UI for fast lookups. | [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md) |
| **Status / Attention Queue** | First-screen summary indicating who needs to act next (gates, todos, alarms). | [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md) |
| **Compute Quota** | Local policy capping automatic agent compute consumption per goal. | [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md) |

> **Optional probe surface** – A free-form `next_probe` command that must be read-only; it is not a seventh layer but a thin observation entry point (see [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md), lines 15‑19).

### The Effect Interpreter Loop

The control-plane operates on a strict loop:

```

model → effect request → harness interprets effect → observation → model

```

This pattern ensures that state transitions are validated and durable before the model observes results, preventing partial or inconsistent updates.

## Four Runtime Responsibilities

The LoopX architecture enforces strict boundaries through four runtime roles. Each responsibility owns specific concerns and explicitly must not own others, preventing accidental "run-away" writes or unscoped effect authority (see [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md), lines 95‑106).

| Responsibility | Owns | Must **not** own |
|----------------|------|------------------|
| **Agent** | Planning, analysis, tool use, one bounded execution through a host/runtime. | Durable goal lifecycle, unscoped effect authority. |
| **Provider** | External calls, bounded observations, effect results, read-back. | Domain transition policy, LoopX todo state. |
| **Capability** | Caller-facing outcome contract, domain policy, observation normalization, validation, typed transition proposals. | Durable scheduling, claims, gates, direct lifecycle writes. |
| **LoopX Kernel** | Goal, todo, claim, gate, monitor, quota, accepted write-back, recovery, scheduling. | Domain-specific reasoning or provider implementation details. |

### Data Flow and Authority Boundaries

Data flows in opposite directions depending on the operation:

```

Agent → Capability → Provider → external system
← Provider readback ← Capability transition ← Kernel

```

**Observation ≠ transition** – a provider’s read-back is merely data; the Kernel only commits a transition after the Capability validates it, ensuring durable state changes are authorized and scoped.

## Turn Decision Vocabulary

Before and after host execution, LoopX uses precise enums defined in `loopx/control_plane/turn_driver/` to replace informal "deliver / wait / ask" language. This typing ensures the control-plane can make deterministic routing decisions (see [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md), lines 76‑82).

**LoopXTurnRoute** (used before host execution for planning):
- `ready_for_host`, `repair_required`, `replan_required`, `user_action_required`, `wait`, `blocked`, `contract_error`

**LoopXTurnResultKind** (used after host execution for outcome validation):
- `validated_progress`, `validated_completion`, `repair_required`, `replan_required`, `user_action_required`, `wait`, `host_failure`, `validation_failed`, `writeback_failed`, `quota_spend_failed`

## Extensions vs. Capabilities

Extensions package optional providers (such as a new Lark Kanban adapter) but **do not** become a fifth runtime responsibility. They register in `CapabilityRegistry` and remain separate from the Kernel’s authority, maintaining the architectural boundary between optional adapters and core control-plane logic (see [`docs/architecture.md`](https://github.com/huangruiteng/loopx/blob/main/docs/architecture.md), lines 84‑89).

## Core Implementation

The LoopX architecture is implemented through specific modules that enforce the layer and responsibility boundaries.

| File | Role |
|------|------|
| [`loopx/control_plane/registry.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/control_plane/registry.py) | Implements the Registry layer, storing goal metadata and adapters. |
| [`loopx/state_migration.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/state_migration.py) | Handles Goal State loading, validation, and migration. |
| [`loopx/control_plane/quota/live_decision.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/control_plane/quota/live_decision.py) | Computes quota decisions determining whether a Turn may run. |
| [`loopx/control_plane/turn_driver/turn_driver.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/control_plane/turn_driver/turn_driver.py) | Central driver for building plans, running host adapters, and write-back. |
| [`loopx/cli_commands/turn.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/cli_commands/turn.py) | CLI entry point wiring status, quota, turn planning, and execution. |

### Planning and Executing Turns

The turn driver exposes two primary functions for interacting with the control-plane:

```python
from loopx.control_plane.turn_driver import build_loopx_turn_plan

turn_envelope = {
    "goal_id": "my-goal",
    "agent_id": "my-agent",
    "todo_id": "todo-123",
}
plan = build_loopx_turn_plan(
    turn_envelope,
    host={"kind": "codex-cli"},
    execution_mode="isolated-headless",
    scheduler_owner="host_automation",
)
print(plan["route"]["kind"])   # → "ready_for_host"

```

(see source: [`loopx/cli_commands/turn.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/cli_commands/turn.py), lines 56‑80)

```python
from loopx.control_plane.turn_driver import run_loopx_turn_once

payload = {...}                         
result = run_loopx_turn_once(
    payload,
    host_argv=["codex", "run", "--some", "args"],
    host_runner=None,
    project=Path("./my-project"),
    runtime_root=Path("./.loopx"),
    goal_id="my-goal",
    execute=True,
)
print(result["result_kind"])           # e.g. "validated_progress"

```

(see source: [`loopx/cli_commands/turn.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/cli_commands/turn.py), lines 1510‑1560)

### CLI Interaction with Layers

The CLI exposes the architecture layers directly (see README "Core tick is deliberately small", lines 44‑51):

```bash
$ loopx status               # reads Registry, Goal State, Run History → Status/Attention Queue

$ loopx quota should-run    # reads quota layer and decides whether a Turn may run

$ loopx todo claim <todo>   # claims a Todo (Kernel authority)

$ loopx refresh-state        # writes back evidence after a successful Turn

```

## Why This Architecture Works for Long-Running Agents

The LoopX architecture solves specific challenges in autonomous AI agent systems:

- **Durable state** – Goals and todos survive process restarts, enabling recovery after crashes or session changes.
- **Local-first** – No external service is required; the control-plane lives in `.loopx/` beside the project.
- **Provider-neutral** – The same Kernel orchestrates Codex, Claude, Cursor, or any custom runtime without changing core logic.
- **Clear authority boundaries** – Only the Kernel can change durable state; agents and providers act within scoped, bounded contracts.
- **Fine-grained quota** – Compute spend is explicitly authorized after validation, preventing runaway costs.

## Summary

- LoopX implements a **six-layer durable control-plane** (Registry, Goal State, Run Log, Run History, Status/Attention Queue, Compute Quota) that functions as an effect interpreter.
- **Four strict runtime responsibilities** (Agent, Provider, Capability, Kernel) prevent unauthorized state mutations by separating concerns.
- The **turn driver** in `loopx/control_plane/turn_driver/` uses typed enums (`LoopXTurnRoute`, `LoopXTurnResultKind`) to deterministically route execution.
- Extensions integrate via `CapabilityRegistry` without becoming core responsibilities, maintaining the architecture's integrity.
- All state lives in the Kernel-managed `.loopx/` directory, enabling local-first, provider-neutral operation.

## Frequently Asked Questions

### What makes LoopX architecture "local-first"?

The control-plane stores all durable state (goals, todos, quota, run history) in a local `.loopx/` directory adjacent to the project. No external database or cloud service is required for core operation, allowing agents to run entirely offline while maintaining full state integrity across process restarts.

### How does the Kernel prevent runaway agent actions?

The Kernel exclusively owns durable scheduling, claims, gates, and write-back permissions. Agents and Providers operate within bounded contracts and cannot modify goal state directly. Additionally, the Compute Quota layer caps automatic compute consumption, requiring explicit validation before each turn.

### Can I add custom providers without modifying the Kernel?

Yes. Custom providers are added as **Extensions** that register in `CapabilityRegistry`. Extensions package optional adapters (such as for Lark Kanban or internal APIs) but remain separate from the Kernel's authority, adhering to the four-responsibility model without becoming a fifth runtime role.

### What happens when a Turn fails validation?

The turn driver returns a `LoopXTurnResultKind` such as `validation_failed`, `repair_required`, or `replan_required`. The Kernel does not commit invalid transitions to the Goal State. Instead, the architecture routes the failure back to the Agent or Capability for remediation, maintaining durable state consistency.