# How Agent Sessions Are Managed for Review Loops vs. Fixer Sessions in No-Mistakes

> Understand how no-mistakes manages agent sessions for review loops versus fixer sessions. Learn about isolation between reviewer and fixer contexts for durable sessions.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: internals
- Published: 2026-07-13

---

**The `no-mistakes` pipeline uses a per-run, per-role session manager to maintain durable agent sessions across resumable review-loop turns, ensuring complete isolation between reviewer and fixer contexts.**

The `kunchenguid/no-mistakes` repository implements a sophisticated pipeline for automated code review that persists agent state across multiple turns. Understanding how agent sessions are managed for review loops compared to fixer sessions reveals a strict architectural separation that prevents context contamination between distinct operational roles.

## The Dual-Role Session Architecture

### SessionRole Constants and Role Separation

In [`internal/pipeline/sessions.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/sessions.go) lines 18-21, the pipeline defines two distinct `SessionRole` constants: `SessionRoleReviewer` for initial full reviews and subsequent rereviews, and `SessionRoleFixer` for every review-fix turn. These constants ensure that the fixer role never mixes with the reviewer role, creating a hard boundary between the two operational contexts.

### State Isolation Guarantees

The reviewer and fixer sessions remain completely isolated according to the source code. The reviewer’s session is exclusively used for the reviewer role, while the fixer’s session handles only fix operations. This isolation prevents the fixer from inheriting the reviewer’s working context or vice versa, enforced by the `SessionRole` type and distinct persistence paths in the database schema.

## The RunSessions Manager Implementation

### Session Lifecycle and Persistence

When a pipeline step executes, it invokes `RunSessions.Run` with the desired role. The manager executes a three-phase lifecycle defined in [`internal/pipeline/sessions.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/sessions.go):

1. **Load**: Retrieve any persisted session ID for the given `(run, role)` pair via `GetRunAgentSessions` (lines 44-63).
2. **Attach**: If the adapter supports session resumption, attach the stored ID to `agent.RunOpts.Session`.
3. **Persist**: After the agent completes execution, save the new session ID via `UpsertRunAgentSession` (lines 84-86).

The review loop implementation in [`internal/pipeline/steps/review.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/review.go) utilizes this manager to orchestrate both roles, while [`internal/pipeline/steps/review_session_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/review_session_test.go) verifies that sessions remain distinct and correctly resumed across turns.

### Database Schema for Per-Role Storage

Session persistence relies on the `run_agent_sessions` table defined in [`internal/db/agent_session.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/db/agent_session.go) lines 5-15. The schema includes a distinct `role` column that stores each role's session ID separately, ensuring that reviewer and fixer sessions occupy separate database records even within the same pipeline run.

## Session Fallback and Recovery

When resume attempts fail due to expired or dead sessions, `RunSessions.Run` implements a `SessionFallback` mechanism (lines 90-100 in [`internal/pipeline/sessions.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/sessions.go)). The manager drops the stale identity, logs the failure, and re-executes the turn with a fresh session, ensuring pipeline correctness even when session persistence proves unreliable.

## Practical Implementation Example

The following Go code demonstrates how `RunSessions` manages distinct sessions for each role:

```go
// Creating a RunSessions manager for a specific run
rs := pipeline.NewRunSessions(db, runID, myAgent, true)

// Running the reviewer role (initial review or rereview)
reviewResult, err := rs.Run(ctx, myAgent, pipeline.SessionRoleReviewer,
    agent.RunOpts{Prompt: reviewerPrompt}, nil)

// Running the fixer role (each review-fix turn)
fixResult, err := rs.Run(ctx, myAgent, pipeline.SessionRoleFixer,
    agent.RunOpts{Prompt: fixerPrompt}, nil)

```

The manager automatically loads any saved session ID, attaches it to `RunOpts`, and persists the new ID after each call, handling the complexity of session resumption transparently.

## Summary

- **Per-role isolation**: The pipeline uses `SessionRoleReviewer` and `SessionRoleFixer` constants to maintain distinct session contexts that never mix.
- **Automatic persistence**: The `RunSessions` manager handles loading and saving session IDs via `GetRunAgentSessions` and `UpsertRunAgentSession` without manual intervention.
- **Database separation**: The `run_agent_sessions` table stores each role's session under a distinct `role` column, preventing cross-contamination at the persistence layer.
- **Graceful degradation**: The `SessionFallback` mechanism ensures pipelines continue executing with fresh sessions when stored sessions expire or become invalid.

## Frequently Asked Questions

### What happens when a stored session expires during a review loop?

When a resume attempt fails because the stored session is dead or expired, `RunSessions.Run` detects the failure and triggers `SessionFallback`. It drops the stale session identity, logs the failure for observability, and re-executes the current turn with a fresh session, ensuring the pipeline completes successfully even when session persistence is unreliable.

### Can reviewer and fixer agents share the same session ID?

No. The architecture explicitly forbids session sharing between roles. The `SessionRole` type and the database schema in [`internal/db/agent_session.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/db/agent_session.go) enforce complete isolation, with each role persisting to a separate record in the `run_agent_sessions` table. This prevents the fixer from inheriting the reviewer's context or state.

### How does the database schema enforce session isolation?

The `run_agent_sessions` table includes a `role` column that stores the specific `SessionRole` value (either `SessionRoleReviewer` or `SessionRoleFixer`) alongside the `run_id` and `session_id`. This composite key structure ensures that each `(run, role)` combination maintains its own session record, preventing any overlap between reviewer and fixer session storage.

### Is session resumption supported for all agent adapters?

Session resumption depends on the specific agent adapter's capabilities. The `RunSessions` manager checks whether the adapter supports session resumption before attaching the stored session ID to `agent.RunOpts`. If the adapter does not support resumption, the manager operates correctly but creates a fresh session for each turn, falling back to standard execution without the persistent context.