Background Agents and Parallel Tasks in Claude Code
AI generated
Claude
>_
Claude Code · Background Agents · Parallelization · Automation
Background Agents and Parallel Tasks in Claude Code
Long-running work in the background, without blocking the session

Background agents start long-running commands such as builds, test suites, or deployments in the background and hand control back immediately instead of letting the session wait blockingly for the result. Combined with several parallel tasks, this creates a working mode that puts waiting time to productive use, but also raises new questions about resources, conflicts, and monitoring.

17 min read run_in_background · Monitoring · Parallelization · Race Conditions Claude Code · Claude Sonnet 5 · Anthropic

1. What background agents and parallel tasks mean

A background agent in Claude Code describes a long-running process that gets started asynchronously, with its result flowing back into the actual conversation only later, through a notification or a targeted status check. This differs fundamentally from the default case, where every command runs synchronously and the entire session waits until it finishes. A complete production build, an extensive test suite, or a database migration script can take several minutes, and work on other subtasks does not need to stand still during that time.

Parallel tasks go one step further: instead of running only a single background process while continuing to work on something else, several independent tasks can be handled at the same time, for instance researching a library while a build runs, or preparing a second change while the first is still being tested. The benefit arises from converting waiting time into productive time, a principle well known from classic software development with asynchronous programming, and it transfers directly to the Claude Code workflow.

2. Starting long-running commands in the background

The practical entry point for background agents is the ability to run a bash command explicitly in the background instead of waiting for it to finish. Instead of starting npm run build synchronously and pausing the conversation for several minutes, the command starts in the background, control returns immediately, and work on another task can begin right away. The process keeps running regardless of whether another file is being edited or another question is being answered at the same time.

Important for meaningful use of background agents: not every command is suited for this. Short commands whose result is needed immediately for the next step, such as reading a configuration file, should stay synchronous. Long-running processes decoupled from the next step, such as builds, full test suites, database dumps, or downloading large dependencies, are the ideal candidates for background mode.


# Start a long-running build in the background instead of blocking the session
npm run build > /tmp/build.log 2>&1 &
BUILD_PID=$!
echo "Build started in background with PID $BUILD_PID"

# Continue working on other tasks immediately while the build runs
# ... edit other files, answer other questions ...

# Check later whether the background build has finished
if kill -0 "$BUILD_PID" 2>/dev/null; then
  echo "Build still running"
else
  echo "Build finished, exit code: $(wait $BUILD_PID; echo $?)"
  tail -n 20 /tmp/build.log
fi

3. Monitoring progress and getting notified

A background agent is only useful if its progress and result stay traceable. Two complementary approaches suit this: active polling, where the status of the background process is checked at regular intervals, and passive waiting for a notification once the process has completed. Active polling suits short to medium wait times where a brief glance at progress suffices, while passive waiting makes more sense for very long-running processes such as a full regression test.

In practice both get combined: a background process writes its log continuously to a file, a simple monitor loop checks at intervals whether the process is still running, and reports completion along with the last relevant lines from the log. This way it always stays traceable whether a background agent is still working, finished successfully, or aborted with an error, without needing to follow the output live.


#!/usr/bin/env bash
# monitor-background-task.sh -- polls a background PID until it finishes
set -euo pipefail

PID="$1"
LOG_FILE="$2"
INTERVAL=5

while kill -0 "$PID" 2>/dev/null; do
  echo "[$(date +%H:%M:%S)] Task $PID still running..."
  sleep "$INTERVAL"
done

wait "$PID"
exit_code=$?

echo "[$(date +%H:%M:%S)] Task $PID finished with exit code $exit_code"
echo "--- last 20 log lines ---"
tail -n 20 "$LOG_FILE"

exit "$exit_code"

4. Working on several independent tasks in parallel

The real productivity gain from parallel tasks shows up when several genuine streams of work exist at the same time. A typical scenario: while a background agent runs the full test suite for an already completed change, work already begins on the next, independent task, such as writing a new component or researching an API integration. Both streams of work are independent of each other, their results do not influence one another, which is the basic precondition for safe parallelization.

A second common pattern is several independent research tasks, for instance investigating multiple candidate libraries for the same requirement at the same time. Since pure read operations do not interfere with each other, such research can be kicked off in parallel as several background agents, with the results compared together later. What always matters is the independence of the tasks, as soon as one task depends on the result of another, parallelization loses its advantage and instead creates coordination overhead.

5. Resource and context management with parallelism

Parallel execution is not free. Every additional background agent consumes CPU, memory, and, in the case of database connections or network I/O, limited external resources as well. On a development machine with limited cores, starting three full build processes at the same time often results in all three running slower than a single sequential run, because they compete for the same CPU cycles. The rule of thumb is: the number of simultaneously running, resource-intensive background processes should be guided by the number of available CPU cores, not by the number of desired tasks.

A second, often overlooked aspect concerns the context of the actual conversation. Every parallel task whose result must later be merged in adds additional information to the overall context. With many simultaneous background agents, this can cause the context to grow faster than with purely sequential work, because intermediate results from all parallel streams eventually need to be brought together. Anyone working in parallel should therefore consciously parallelize only genuinely independent, clearly scoped tasks instead of offloading every small thing into its own background process.

6. Avoiding race conditions and conflicts

As soon as several parallel tasks access the same resources, such as the same working directory, the same database, or the same file, classic race conditions arise. Two simultaneously running processes that both write to the same file can overwrite each other, a build process and a simultaneously running test run in the same working directory can overwrite each other's compiled artifacts and create inconsistent intermediate states. These problems are not specific to Claude Code, they are the same concurrency problems known from classic systems programming.

The most reliable safeguard is strict resource separation: every background agent that writes files should run in its own, isolated working directory, for instance via separate git worktrees or temporary directories. Where shared resources are unavoidable, such as a common database, a simple lock mechanism like flock helps, preventing two processes from entering a critical section at the same time. Without this safeguard, parallelization quickly leads to hard-to-reproduce bugs that never occur when tested individually but regularly strike in the parallel interplay.


#!/usr/bin/env bash
# run-parallel-tasks.sh -- runs independent tasks in isolated directories
set -euo pipefail

MAX_JOBS=4
declare -a pids=()

run_isolated_task() {
  local task_id="$1"
  local work_dir
  work_dir=$(mktemp -d)
  (
    cd "$work_dir"
    # Each task operates in its own directory -- no shared state, no races
    git worktree add "$work_dir/repo" "task-$task_id" > /dev/null 2>&1
    cd "$work_dir/repo"
    npm test > "/tmp/task-$task_id.log" 2>&1
  ) &
  pids+=($!)
}

for task_id in 1 2 3; do
  run_isolated_task "$task_id"
  (( ${#pids[@]} >= MAX_JOBS )) && wait "${pids[0]}" && pids=("${pids[@]:1}")
done

for pid in "${pids[@]}"; do
  wait "$pid" || echo "Task with PID $pid failed"
done

7. Background tasks in CI/CD and automation

The principle behind background agents transfers directly to CI/CD pipelines, where parallel jobs are the norm anyway. A Claude Code backed workflow can, for instance, kick off a deploy process that internally contains several parallel steps, database migration, cache invalidation, and asset build, while the session itself waits for the overall result and logs currency-relevant intermediate steps. Clear error handling matters here: if one of the parallel steps fails, the overall result must reflect that instead of silently ignoring a partial failure.

Another sensible use case is running linting, type checking, and unit tests in parallel as three independent background agents, whose results get bundled at the end into a single status report. Since these three checks do not influence each other, parallelization here is risk free and in practice often saves more than half the total runtime compared to sequential execution of the same three steps.


#!/usr/bin/env bash
# ci-parallel-checks.sh -- runs three independent checks as background agents
set -euo pipefail

npm run lint      > /tmp/lint.log 2>&1 &   LINT_PID=$!
npm run typecheck > /tmp/types.log 2>&1 &  TYPES_PID=$!
npm test          > /tmp/tests.log 2>&1 &  TEST_PID=$!

status=0
for pair in "lint:$LINT_PID" "typecheck:$TYPES_PID" "test:$TEST_PID"; do
  name="${pair%%:*}"; pid="${pair##*:}"
  if wait "$pid"; then
    echo "[PASS] $name"
  else
    echo "[FAIL] $name (see /tmp/$name.log)"
    status=1
  fi
done

exit "$status"

8. When sequential work is the better choice

Not every situation benefits from parallel tasks. When one step necessarily needs the result of a previous step, such as a deployment that may only begin after a successful test run, sequential execution is not only simpler but also more correct. Trying to parallelize such a dependency anyway leads either to unnecessary coordination overhead or to genuinely wrong results if the dependent step begins before the previous one has finished.

Parallelization also rarely pays off for small, fast tasks: the overhead of starting a background agent, monitoring it, and later collecting its result quickly exceeds the actual time saved for a task that only takes a few seconds anyway. The rule of thumb remains: parallelization pays off when a task runs long enough to make waiting time relevant, and is independent enough to run alongside other work without coordination overhead. If either of these two conditions is missing, sequential work remains the more robust and often faster choice.


# A dependent sequence must stay synchronous -- parallelizing it would be wrong
run_tests() {
  npm test
}

deploy() {
  # This step must never start before tests have actually finished successfully
  npm run deploy
}

if run_tests; then
  deploy
else
  echo "Tests failed, deployment skipped" >&2
  exit 1
fi

9. Synchronous versus asynchronous compared directly

The decision between synchronous and asynchronous execution depends on a few clear criteria that can be compared directly.

Criterion Synchronous Asynchronous (background agent)
Task runtime Seconds to a few minutes Several minutes or longer
Dependency on the result Next step needs it immediately Result is only needed later
Resource conflict No conflict possible Isolation required (worktree, lock)
Coordination overhead None Monitoring and merging needed
Total time for several tasks Sum of all individual times Overlapping, often significantly shorter

The table makes clear why there is no blanket answer: short, dependent steps belong running synchronously, long-running, independent tasks benefit from asynchronous execution as a background agent. The skill lies in making this judgment consciously for each concrete task instead of reflexively parallelizing everything or reflexively working through everything sequentially.

Mironsoft

Claude Code setup, automation workflows and Magento/Hyva development with AI

Reducing waiting time in your development process?

We build Claude Code workflows for your team with sensibly parallelized background agents, from isolated build processes to parallel research and CI integration.

Workflow design

Identifying a sensible split into parallel and sequential steps

Isolation and locking

Setting up worktrees and locks to reliably avoid race conditions

CI parallelization

Running linting, type checking and tests in parallel in the pipeline

10. Summary

Background agents and parallel tasks bring a proven principle from asynchronous programming to the Claude Code workflow: long-running, independent tasks no longer block the entire session but keep running in the background while productive work continues elsewhere. Monitoring through polling or notification keeps progress traceable, isolation through separate working directories or locks prevents race conditions on shared resources.

The benefit only arises when tasks are genuinely independent of each other and run long enough to justify the coordination overhead. Short tasks and those with a direct dependency on the result of another step continue to belong running synchronously. Anyone who makes this distinction consciously gains noticeable time without creating new, hard-to-reproduce failure sources through uncontrolled parallelization.

Background Agents and Parallel Tasks — The Essentials at a Glance

Core idea

Start long-running commands in the background, regain control immediately, keep working elsewhere.

Monitoring

Polling for short to medium waits, notification for very long-running processes.

Isolation

Separate working directories or locks prevent race conditions on shared resources.

Limits

Only sensible with genuine independence and sufficient runtime, otherwise work sequentially.

11. FAQ: Background Agents and Parallel Tasks in Claude Code

1What is a background agent?
A long-running process in the background, while control returns immediately.
2Which tasks are suited?
Long-running, decoupled processes like builds or test suites. Short, dependent commands stay synchronous.
3How do I monitor progress?
Active polling or passive waiting for a notification, often combined with a log.
4What are race conditions?
Conflicts when several processes change the same resource at once without safeguards.
5How do I avoid race conditions?
Separate working directories per task and lock mechanisms like flock for shared resources.
6How many should run at once?
Guided by the number of available CPU cores, not by the number of desired tasks.
7When does it not pay off?
For short or directly dependent tasks whose overhead exceeds the time saved.
8Use in CI/CD?
Independent checks like linting and tests run in parallel, results get bundled into a report.
9Does it affect the context?
Yes, only genuinely independent tasks should be parallelized to avoid inflating the context.
10Difference from subagents?
A subagent delegates to an isolated model context, a background agent primarily describes asynchronous process execution.