# Architecture of the Recovery Reviewer and Decision System in DeepSeek Reasonix

> Explore the DeepSeek Reasonix recovery system architecture. Discover how the Auto-Guard framework with a recovery reviewer and decision gate manages episodes, budgets, and persistence.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: architecture
- Published: 2026-08-07

---

**The DeepSeek Reasonix recovery system employs a two-layer Auto-Guard architecture where an independent LLM-based recovery reviewer evaluates failure evidence and emits structured verdicts, while a decision gate orchestrates episode flow, enforces token budgets, and manages persistence via side-car state files.**

DeepSeek Reasonix (also referred to as DeepSeek-Reasonix) implements a sophisticated failure recovery mechanism to keep long-running autonomous agents productive and safe. The system centers on a **recovery reviewer** that acts as an independent, read-only evaluator of failures, paired with a **decision system** that orchestrates retries, pauses, and abortions based on structured verdicts returned by the reviewer.

## Recovery Reviewer Implementation

The **Recovery Reviewer** provides an isolated LLM session dedicated to evaluating agent failures without side effects. Implemented in [[`internal/recovery/reviewer.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/reviewer.go)](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/recovery/reviewer.go), this component operates under strict resource constraints to prevent runaway token consumption during error analysis.

### Bounded Session Configuration

Each reviewer session is instantiated with deterministic, conservative limits to ensure predictable behavior. The `Session` struct enforces **temperature = 0** for deterministic outputs, **MaxTokens = 256**, and strict byte budgets for all inputs. When calling `NewSessionWithSink`, the system initializes a provider connection to the `deepseek/recovery-reviewer` model and attaches a `UsageSink` for telemetry tracking.

```go
rev := recovery.NewSessionWithSink(provider, usageSink) // creates a bounded reviewer
verdict, err := rev.Review(ctx, failureEvent, evidence, proposal, taskSummary)

```

The session imposes a hard timeout of **30 seconds** (`reviewerTimeout = 30s`) on all calls to `provider.Stream`. If the LLM fails to respond within this window or exceeds the token limit, the session returns an error immediately, triggering fallback logic in the decision gate.

### Evidence Packaging and Policy

The reviewer operates against a static **PolicyPrompt** (approximately 2 KB) that defines its role: *"You are an independent Auto plan-decision reviewer for a coding agent."* All failure evidence is packaged into a `FailureEvent` struct containing `ArgsSummary` and `OutputExcerpt`, then clipped to configurable budgets defined by `reviewerMaxEvidenceBytes` and `reviewerMaxTaskSummary` before transmission.

```go
fail := recovery.FailureEvent{
    ArgsSummary:   "read_file(\"config.yaml\")",
    OutputExcerpt: "permission denied",
}

```

### Review Verdict Parsing

The reviewer returns a strictly typed `ReviewVerdict` containing an `Outcome` field (`continue`, `pause`, or `abort`) and a `ChangeKind` field (`noop`, `retry`, `rewind`, or `ambiguous`). The `Review` method validates JSON structure and required fields; malformed responses surface as errors that the decision system must handle through deterministic fallback rules.

## Decision System and Gate Logic

While the reviewer provides recommendations, the **Decision System** located in [[`internal/recovery/decision.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/decision.go)](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/recovery/decision.go) executes them. This layer manages episode state, enforces global budgets, and coordinates the transition between agent execution and recovery procedures.

### Gate Architecture and Budgeting

The `Gate` struct in [[`internal/recovery/gate.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/gate.go)](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/recovery/gate.go) serves as the primary interface between the agent and recovery logic. It wraps the reviewer session and maintains per-episode budgets including `reviewerMaxTokens` and `reviewerMaxTotalBytes`. The gate tracks the number of reviewer invocations to prevent infinite retry loops and exposes `HandleFailure` as the unified entry point for processing errors.

```go
gate := recovery.NewGate(sessionID, provider, usageSink)
verdict, err := gate.HandleFailure(ctx, stepErr)

```

When a failure occurs, the gate captures a `FailureEvent`, budgets the evidence, queries the reviewer via `gate.Reviewer.Review()`, and produces a `Decision` struct via `ApplyVerdict`. The decision specifies one of three actions: **ActionContinue** (retry the step), **ActionPause** (halt auto-retry pending user input), or **ActionAbort** (terminate the episode).

### Rules Engine Fallback

For scenarios where the reviewer is unavailable, times out, or returns `ChangeKind: ambiguous`, the system falls back to deterministic classifiers implemented in [[`internal/recovery/rules.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/rules.go)](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/recovery/rules.go). These rule-based functions analyze the failure signature—for example, detecting "method signature altered" scenarios—without LLM latency, ensuring the agent remains responsive even when the recovery reviewer service is degraded.

### State Persistence

The decision system maintains crash resilience through [[`internal/recovery/persist.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/persist.go)](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/recovery/persist.go). After each verdict, the gate serializes its state to a side-car JSON file (`*.recovery.json`) using the types defined in [[`internal/recovery/types.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/types.go)](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/recovery/types.go). This allows sessions to resume mid-episode using `LoadGateFromDisk`, restoring the exact decision point and budget consumption history.

```go
gate := recovery.LoadGateFromDisk(sessID, sink)
return gate.Resume(ctx)

```

## Interaction Flow Between Components

The recovery architecture follows a strict pipeline when handling agent failures:

1. **Failure Detection**: When a tool or plan step errors, the gate generates a `FailureEvent` capturing `ArgsSummary`, `OutputExcerpt`, and context.
2. **Evidence Budgeting**: The system trims failure evidence to fit `reviewerMaxEvidenceBytes` and combines it with the static `PolicyPrompt`.
3. **Reviewer Evaluation**: The `Gate` transmits the packaged evidence to the reviewer LLM via `provider.Stream`, enforcing the 30-second timeout.
4. **Verdict Application**: The `Decision` consumes the `ReviewVerdict`, updates episode budgets, and determines whether to modify the current proposal (e.g., rolling back to a previous plan state).
5. **Persistence**: The gate writes the updated state to disk, enabling resumption after crashes or user-initiated pauses.

## Code Implementation Examples

### Creating a Stand-Alone Reviewer Session

The following pattern initializes a reviewer for isolated failure analysis without full gate orchestration:

```go
import (
    "context"
    "reasonix/internal/recovery"
    "reasonix/internal/provider"
)

func exampleReviewer(ctx context.Context) error {
    // Provider targets the dedicated recovery-reviewer model
    prov := provider.NewOpenAI("deepseek/recovery-reviewer")
    sink := recovery.NewUsageSink()

    // Create bounded session with telemetry
    rev := recovery.NewSessionWithSink(prov, sink)

    fail := recovery.FailureEvent{
        ArgsSummary:   "git_push(\"main\")",
        OutputExcerpt: "rejected: non-fast-forward",
    }

    verdict, err := rev.Review(ctx, &fail, nil, recovery.Proposal{}, "")
    if err != nil {
        return err
    }

    switch verdict.Outcome {
    case "continue":
        // Proceed with retry
    case "pause":
        // Halt for manual intervention
    case "abort":
        // Terminate operation
    }
    return nil
}

```

### Integrating Reviewer into the Decision Gate

For production agent loops, embed the reviewer within the gate to manage episode lifecycle:

```go
func runEpisode(ctx context.Context, sessID string) error {
    prov := provider.NewOpenAI("deepseek/recovery-reviewer")
    sink := recovery.NewUsageSink()
    gate := recovery.NewGate(sessID, prov, sink)

    for {
        // Execute agent step...
        if stepErr != nil {
            verdict, err := gate.HandleFailure(ctx, stepErr)
            if err != nil {
                return err // Reviewer unavailable or budget exceeded
            }

            dec := gate.ApplyVerdict(verdict)
            switch dec.Action {
            case recovery.ActionContinue:
                continue // Retry current step
            case recovery.ActionPause:
                return fmt.Errorf("auto-retry paused; awaiting user input")
            case recovery.ActionAbort:
                return fmt.Errorf("episode aborted by reviewer decision")
            }
        }
        // Success path...
    }
}

```

### Persisting and Resuming Recovery Sessions

To survive process restarts, persist gate state and resume execution:

```go
func resumeEpisode(ctx context.Context, sessID string) error {
    sink := recovery.NewUsageSink()
    // Automatically loads *.recovery.json side-car file
    gate := recovery.LoadGateFromDisk(sessID, sink)
    
    // Continues from last decision point with budgets intact
    return gate.Resume(ctx)
}

```

## Summary

- The **Recovery Reviewer** in [`internal/recovery/reviewer.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/reviewer.go) provides an isolated, bounded LLM session (temperature 0, 256 token limit, 30s timeout) that evaluates failures through a static `PolicyPrompt` and returns structured `ReviewVerdict` objects.
- The **Decision System** centers on the `Gate` struct in [`internal/recovery/gate.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/gate.go), which orchestrates episode flow, enforces per-session budgets (`reviewerMaxEvidenceBytes`, `reviewerMaxTokens`), and coordinates between the agent and reviewer.
- **Fallback logic** in [`internal/recovery/rules.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/rules.go) handles reviewer unavailability or ambiguous verdicts using deterministic classifiers.
- **State persistence** via [`internal/recovery/persist.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/persist.go) serializes decision state to `*.recovery.json` files, enabling crash recovery and session resumption through `LoadGateFromDisk`.
- All reviewer usage is tracked via `UsageSink` under the `recovery-reviewer` model reference for cost monitoring and telemetry.

## Frequently Asked Questions

### How does the recovery reviewer handle token budget overflows?

The reviewer enforces strict byte and token budgets through configuration constants (`reviewerMaxEvidenceBytes`, `reviewerMaxTaskSummary`, `MaxTokens = 256`). Input evidence is pre-clipped before transmission, and if the LLM response exceeds limits or the 30-second timeout fires, the `Review` method returns an error. The decision gate then falls back to deterministic rules in [`internal/recovery/rules.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/rules.go) rather than proceeding without reviewer guidance.

### What is the difference between the Gate and the Reviewer in Reasonix?

The **Reviewer** ([`internal/recovery/reviewer.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/reviewer.go)) is a stateless, read-only LLM client that analyzes failure evidence and returns verdicts. The **Gate** ([`internal/recovery/gate.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/gate.go)) is a stateful orchestrator that owns the reviewer instance, manages episode budgets, persists state to disk, and translates verdicts into concrete actions (continue, pause, abort). The gate handles the lifecycle; the reviewer provides the analysis.

### Can the recovery system resume after a process crash?

Yes. The decision system serializes its complete state—including current budget consumption, last verdict, and episode position—to a `*.recovery.json` side-car file after every significant transition. Upon restart, calling `recovery.LoadGateFromDisk(sessionID, sink)` restores the exact state, allowing the agent to resume from the precise decision point without re-running previous steps or re-consuming reviewer tokens.

### What happens when the reviewer returns an ambiguous verdict?

When the `ReviewVerdict` contains `ChangeKind: ambiguous`, the decision system delegates to the **Rules Engine** in [`internal/recovery/rules.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/recovery/rules.go). This module applies deterministic heuristics—such as detecting specific error patterns like "method signature altered"—to decide whether to retry, rewind, or abort without requiring additional LLM calls. This ensures the agent remains responsive even when the reviewer cannot provide a definitive classification.