# How the Fix Loop Escalates in the Subagent Workflow: Codex-Security Deep-Scan Architecture

> Learn how the fix loop escalates in the subagent workflow. Understand how unresolved findings propagate and resources are allocated until the scan stabilizes.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: architecture
- Published: 2026-09-10

---

**The fix loop escalates by propagating unresolved findings to additional subagents when SQLite `close_reason` flags indicate remediation failure or false positives, iteratively allocating resources based on the configured `subagents` count until the scan reaches a stable state.**

The Codex-Security deep-scan system in the `openai/plugins` repository implements a multi-agent workflow to automate security vulnerability remediation. Understanding how the fix loop escalates within this subagent architecture is essential for optimizing scan throughput and resource allocation. This article examines the orchestration logic, database schema constraints, and configuration parameters that govern when the system spawns additional subagents to handle unresolved candidates.

## Understanding the Subagent Fix-Loop Architecture

The deep-scan system processes security findings through a pool of **subagents** operating inside an iterative workflow. Each subagent attempts automatic remediation, records the outcome via a constrained SQLite schema, and either completes the task or triggers escalation. According to the source code in [`plugins/codex-security/scripts/deep_scan_workbench.py`](https://github.com/openai/plugins/blob/main/plugins/codex-security/scripts/deep_scan_workbench.py), the orchestration layer maintains runtime state—including `workers` and `subagents` counts—to determine when to expand the processing pool and continue the loop.

## The Three Stages of Fix-Loop Escalation

### Stage 1: Attempting Automatic Remediation

When a subagent receives a candidate finding, it first inspects the issue and attempts to apply an automatic fix. The success of this remediation attempt determines the subsequent path through the workflow. Successful fixes proceed to completion, while failed attempts, false positives, or developer-declared "won't fix" statuses initiate the escalation sequence.

### Stage 2: Recording the Close Reason in SQLite

The outcome of each remediation attempt is persisted to the database schema defined in [`plugins/codex-security/scripts/workbench_schema.py`](https://github.com/openai/plugins/blob/main/plugins/codex-security/scripts/workbench_schema.py). At line 136, the `close_reason` column enforces a constrained set of values that drive the escalation logic:

```python

# workbench_schema.py – definition of the close_reason column

subagents INTEGER NOT NULL CHECK (subagents >= 0),
...
close_reason IS NULL OR close_reason IN ('already_fixed', 'wont_fix', 'false_positive')

```

Accepted values include:
- **`already_fixed`** – The subagent successfully remediated the finding
- **`wont_fix`** – The developer explicitly declined to address the issue
- **`false_positive`** – The finding was determined to be invalid

### Stage 3: Triggering Escalation via New Subagent Spawning

Escalation occurs whenever the `close_reason` is set to any value other than `already_fixed`. The orchestration layer reads the `subagents` count from the deep-scan configuration to determine whether to instantiate additional agents. As implemented in [`plugins/codex-security/scripts/deep_scan_workbench.py`](https://github.com/openai/plugins/blob/main/plugins/codex-security/scripts/deep_scan_workbench.py) (lines 61-64), the runtime state exposes both `workers` and `subagents` fields, allowing the system to re-evaluate the work queue and spawn new subagents when permitted.

The escalation logic follows this pattern:

```python

# Pseudo-code of the fix-loop escalation

for finding in candidates:
    if can_fix(finding):
        apply_fix(finding)
        close_reason = "already_fixed"
    elif user_declares_no_fix(finding):
        close_reason = "wont_fix"
    else:
        close_reason = "false_positive"

    record_close_reason(finding.id, close_reason)

    if close_reason != "already_fixed":
        # Escalate: let the orchestrator spawn another sub-agent

        increment_subagents_counter()

```

## Configuration and Orchestration Details

### Defining Subagent Limits in deep_scan_config.py

The maximum number of subagents permitted during escalation is controlled through the configuration parser in [`plugins/codex-security/scripts/deep_scan_config.py`](https://github.com/openai/plugins/blob/main/plugins/codex-security/scripts/deep_scan_config.py) (lines 81-83). The system retrieves the `subagents` value using a `require_integer` validator with a configurable default:

```python

# deep_scan_config.py – pulling the subagents setting from the config

"subagents": require_integer(
    configured.get("subagents", DEFAULT_SUBAGENTS),
    "deep_scan.subagents",
),

```

This configuration determines the upper bound of how many times the fix loop may escalate by spawning additional agents.

### Runtime State Management in deep_scan_workbench.py

The orchestration routine tracks active resources through a runtime state object that informs escalation decisions. In [`plugins/codex-security/scripts/deep_scan_workbench.py`](https://github.com/openai/plugins/blob/main/plugins/codex-security/scripts/deep_scan_workbench.py), the configuration block exposes the current allocation:

```python

# deep_scan_workbench.py – exposing subagents in the runtime state

"config": {
    "workers": run["workers"],
    "subagents": run["subagents"],          # ← used to decide whether to spawn more sub-agents

    ...
},

```

The orchestrator compares these values against the configured limits to determine whether the fix loop should spawn new subagents or mark the finding as requiring human intervention.

## Summary

- The fix loop escalates when findings receive a `close_reason` of `wont_fix` or `false_positive`, or when automatic remediation fails to apply successfully
- The SQLite schema in [`workbench_schema.py`](https://github.com/openai/plugins/blob/main/workbench_schema.py) constrains `close_reason` to three specific values that function as state machine triggers for escalation logic
- Configuration parameters in [`deep_scan_config.py`](https://github.com/openai/plugins/blob/main/deep_scan_config.py) control the maximum `subagents` count available for iterative escalation
- The orchestration layer in [`deep_scan_workbench.py`](https://github.com/openai/plugins/blob/main/deep_scan_workbench.py) manages runtime state to coordinate subagent spawning across fix-loop iterations until all findings reach a terminal state

## Frequently Asked Questions

### What triggers the fix loop to escalate in the subagent workflow?

Escalation triggers when a subagent cannot successfully fix a finding, resulting in a `close_reason` value of `wont_fix` or `false_positive` in the SQLite database. The system interprets any non-null `close_reason` other than `already_fixed` as a signal that the current subagent has completed its work on that finding, requiring delegation to a new subagent instance if the scan configuration permits additional resources.

### How does the system determine when to spawn additional subagents?

The orchestration layer checks the `subagents` count from the deep-scan configuration against the current runtime state. As defined in [`deep_scan_config.py`](https://github.com/openai/plugins/blob/main/deep_scan_config.py), this integer value limits how many subagents may be active simultaneously. The orchestrator in [`deep_scan_workbench.py`](https://github.com/openai/plugins/blob/main/deep_scan_workbench.py) re-evaluates this allocation during each iteration of the fix loop, spawning new agents only when the configuration allows and unprocessed candidates remain in the queue.

### What database schema supports the fix-loop escalation tracking?

The escalation mechanism relies on the SQLite schema defined in [`plugins/codex-security/scripts/workbench_schema.py`](https://github.com/openai/plugins/blob/main/plugins/codex-security/scripts/workbench_schema.py), specifically the `close_reason` column at line 136. This column accepts only three constrained values (`already_fixed`, `wont_fix`, `false_positive`), creating a finite state machine that determines whether the fix loop should close the finding or escalate it to additional subagents for re-processing.

### Where is the subagent orchestration logic implemented?

The primary orchestration logic resides in [`plugins/codex-security/scripts/deep_scan_workbench.py`](https://github.com/openai/plugins/blob/main/plugins/codex-security/scripts/deep_scan_workbench.py), which exposes the runtime configuration including `workers` and `subagents` fields at lines 61-64. This module coordinates the fix-loop iterations, manages the work queue, and determines when to escalate findings to newly spawned subagents based on the `close_reason` flags and the limits defined in the scan configuration.