# How `subagent_concurrency` Controls Parallel Task Execution in DeepSeek-Reasonix

> Learn how subagent_concurrency in DeepSeek-Reasonix controls parallel task execution by limiting simultaneous sub-agent spawns up to 32. Discover its deadlock prevention.

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

---

**The `subagent_concurrency` setting caps simultaneous sub-agent execution at 32 (default 6), preventing deadlocks by rejecting new spawns once the session-wide slot limit is reached.**

The `subagent_concurrency` parameter in the **DeepSeek-Reasonix** repository governs how many isolated child agents can operate simultaneously within a single session. When skills such as *explore*, *research*, *review*, or *security_review* are marked with `runAs=subagent`, the system spawns isolated child loops that consume concurrency slots. Configured via `agent.max_subagent_concurrency` in TOML, this mechanism prevents resource exhaustion and parent-child deadlocks by enforcing strict limits on parallel sub-agent processes.

## What Is subagent_concurrency?

`subagent_concurrency` exposes a session-wide semaphore that controls the maximum number of sub-agents permitted to run at once. In the codebase, this value is represented by `agent.max_subagent_concurrency` and is enforced by the session's **write-scheduler**. Each time a skill triggers a sub-agent spawn, the scheduler attempts to allocate a slot from the available pool.

## How Parallel Execution Is Controlled

The concurrency mechanism operates through slot tracking and fast-fail validation.

### Slot Allocation and Write Scheduling

When Reasonix spawns a sub-agent, the write-scheduler hands out a *sub-agent concurrency slot* to the child process. The scheduler maintains two critical counters: the total number of active sub-agents and the subset allowed to perform write-capable actions (parallel writers). According to [`internal/agent/scheduler.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/agent/scheduler.go), the system checks these counters before permitting any new sub-agent to initialize.

### Deadlock Prevention

The primary architectural goal is avoiding scenarios where a parent sub-agent waits indefinitely for a child that cannot be created. If the number of active sub-agents reaches the configured `max_subagent_concurrency`, the scheduler aborts the spawn immediately with the error: "subagent concurrency limit reached (%d); nested subagents fail fast to avoid parent/child slot deadlock". This fail-fast approach prevents circular dependencies where nested sub-agents would otherwise block on unavailable slots.

## Configuration Limits and Defaults

The limits are defined in [`internal/agent/write_claims.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/agent/write_claims.go):

- **Default**: `DefaultMaxSubagentConcurrency = 6` (line 13) — the out-of-the-box concurrency cap used when no custom value is specified.
- **Hard ceiling**: `MaxSubagentConcurrencyLimit = 32` (line 20) — any user-provided value exceeding 32 is clamped to this maximum.

The helper function `NormalizeConcurrencyLimits(total, writers int)` (lines 39–44) enforces these bounds, ensuring both total sub-agent slots and parallel-writer slots remain within the valid range of `[1, 32]`.

## Configuring subagent_concurrency

You can adjust the limit via TOML configuration or programmatically at runtime.

**TOML Configuration (default 6, maximum 32):**

```toml

# reasonix.example.toml

[agent]
max_subagent_concurrency = 6   # session-wide sub-agent concurrency for tasks/fleet/skills

```

**Runtime Configuration via Desktop UI:**

```go
// desktop/settings_app.go
func (a *App) SetMaxSubagentConcurrency(n int) error {
    total, _ := agent.NormalizeConcurrencyLimits(n, 0)
    a.cfg.Agent.MaxSubagentConcurrency = total
    // propagate to scheduler …
    return nil
}

```

## Handling Concurrency Limit Errors

When the scheduler detects that `currentSubagents >= maxTotal`, it returns an error immediately rather than queuing the request. As implemented in [`internal/agent/scheduler.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/agent/scheduler.go) (lines 49–98), this prevents the session from entering an unstable state:

```go
// internal/agent/scheduler.go
if currentSubagents >= maxTotal {
    return noop, fmt.Errorf(
        "subagent concurrency limit reached (%d); nested subagents fail fast to avoid parent/child slot deadlock",
        maxTotal)
}

```

This error surface allows calling code to handle saturation gracefully, whether by retrying with backoff or escalating to the user.

## Summary

- **`subagent_concurrency`** controls how many sub-agents can run simultaneously in a single DeepSeek-Reasonix session.
- **Default limit** is **6** (`DefaultMaxSubagentConcurrency`), with a **hard ceiling of 32** (`MaxSubagentConcurrencyLimit`).
- The **write-scheduler** allocates slots and rejects new sub-agents once the limit is reached to prevent deadlocks.
- Configuration occurs via `agent.max_subagent_concurrency` in TOML or through the `NormalizeConcurrencyLimits` helper for runtime changes.

## Frequently Asked Questions

### What happens if I set `max_subagent_concurrency` higher than 32?

The value is automatically clamped to 32. The `NormalizeConcurrencyLimits` function in [`internal/agent/write_claims.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/agent/write_claims.go) enforces this hard ceiling regardless of the input value, ensuring the system never allocates more than 32 concurrent sub-agent slots.

### Why does DeepSeek-Reasonix use a fail-fast error instead of queuing excess sub-agents?

Fail-fast behavior prevents parent-child deadlocks. If a parent sub-agent waited for a child to spawn while all slots were occupied, the parent would hang indefinitely. By returning an error immediately when the limit is reached, the scheduler forces the caller to handle saturation explicitly rather than risking circular wait conditions.

### Which skills trigger sub-agent creation and consume concurrency slots?

Skills marked with `runAs=subagent` spawn isolated child loops that consume slots. Common examples include *explore*, *research*, *review*, and *security_review*. Each invocation of these skills requests a slot from the session's write-scheduler before execution begins.

### Can I change the concurrency limit without restarting the Reasonix session?

Yes. The [`desktop/settings_app.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/settings_app.go) implementation demonstrates runtime adjustment via `SetMaxSubagentConcurrency`, which calls `NormalizeConcurrencyLimits` to validate the new value before applying it to the active scheduler configuration.