Skip to content

Auto Mode Service

Autonomous feature implementation engine that drives agent execution, worktree lifecycle, concurrency, and the auto-loop for multi-project builds.

Overview

AutoModeService is the central coordinator for AI-driven feature development. It:

  • Schedules features — picks the next backlog item and dispatches it to an agent
  • Manages worktrees — creates isolated git worktrees per feature for parallel execution
  • Controls concurrency — enforces max concurrent agents with a ConcurrencyManager
  • Runs auto-loops — continuous execution loops per project/worktree pair
  • Handles failures — circuit breaker pauses the loop after consecutive failures, auto-resumes after cooldown
  • Manages memory — monitors heap usage and blocks/aborts agents when thresholds are breached

Architecture

text
AutoModeService
  ├── FeatureScheduler      — loop ownership, feature loading, dispatch
  ├── ExecutionService      — per-feature execution logic (plan, build, verify, merge)
  ├── ConcurrencyManager    — concurrency slot tracking across all projects
  ├── AutoLoopCoordinator   — per-worktree loop state (running, paused, failures)
  ├── FeatureStateManager   — persist-before-emit status transitions
  └── TypedEventBus         — type-safe event emission

Feature Execution Flow

text
startAutoLoop()
  --> FeatureScheduler.loop()
    --> Load next backlog feature
    --> ConcurrencyManager: acquire slot
    --> ExecutionService.executeFeature()
          --> createWorktreeForBranch()
          --> Build prompt with context files + images
          --> Claude Agent SDK invocation (via LeadEngineerService)
          --> StreamObserver: detect agent loops
          --> On success: gitWorkflowService.merge()
          --> On failure: trackFailure() → circuit breaker check
    --> Release concurrency slot
    --> FeatureStateManager: persist status → FeatureLoader.update() auto-emits feature:status-changed

Key Components

FeatureScheduler

Owns the auto-loop tick. Each iteration:

  1. Checks if auto-mode is still running
  2. Loads backlog features respecting dependency order
  3. Filters blocked features (human-assigned deps, pipeline gates)
  4. Dispatches to ExecutionService

ExecutionService

Handles all per-feature execution logic:

  • Worktree creation/reuse
  • Prompt assembly (buildPromptWithImages, context file loading)
  • Claude Agent SDK invocation with MCP servers
  • StreamObserver integration for loop detection
  • Plan approval gating (when planningMode is enabled)
  • Retry on LoopDetectedError with recovery guidance

ConcurrencyManager

Controls how many agents run simultaneously. Slot-based approach:

  • Slots are claimed synchronously before any async work
  • Released on completion (success or failure)
  • Separate from per-project concurrency — global cap is MAX_SYSTEM_CONCURRENCY

AutoLoopCoordinator

Per-worktree loop state (key: projectPath::branchName):

typescript
interface ProjectAutoLoopState {
  abortController: AbortController;
  isRunning: boolean;
  consecutiveFailures: { timestamp: number; error: string }[];
  pausedDueToFailures: boolean;
  humanBlockedCount: number;
  cooldownTimer: NodeJS.Timeout | null;
}

TypedEventBus

Wraps the shared event bus with a emitAutoModeEvent() method that enforces consistent auto-mode event shapes.

Every call to emitAutoModeEvent(eventType, data) produces two emissions:

  1. Envelopeauto-mode:event with payload { type: eventType, ...data } (consumed by WebSocket streaming to UI clients)
  2. Direct — the event type itself, normalized from auto_mode_* to auto-mode:* (e.g., auto_mode_stoppedauto-mode:stopped)

The direct emission lets internal subscribers (such as Lead Engineer fast-path rules) listen on auto-mode:stopped without subscribing to the envelope and filtering by type.

Circuit Breaker

After CONSECUTIVE_FAILURE_THRESHOLD (2) failures within FAILURE_WINDOW_MS (60s), the loop pauses for COOLDOWN_PERIOD_MS (5 minutes), then auto-resumes.

Memory Management

Heap usage is checked before starting new agents:

ThresholdEnv VarDefaultBehavior
StopHEAP_STOP_THRESHOLD0.80Block new agent starts
AbortHEAP_ABORT_THRESHOLD0.90Abort running agents

LoopDetectedError

StreamObserver monitors agent output for repeated patterns. When a loop is detected, it throws LoopDetectedError with the loopSignature. ExecutionService catches this and retries once with recovery guidance injected into the prompt.

typescript
export class LoopDetectedError extends Error {
  readonly loopSignature: string;
}

Execution State Persistence

Before executing, the service persists ExecutionState to disk (.automaker/execution-state.json). On server restart, interrupted features are detected and resumed.

typescript
interface ExecutionState {
  version: 1;
  autoLoopWasRunning: boolean;
  maxConcurrency: number;
  projectPath: string;
  branchName: string | null;
  runningFeatureIds: string[];
  savedAt: string; // ISO-8601
}

Call resumeInterruptedFeatures(projectPath) on startup to re-queue any in-progress features that survived a crash.

Multi-Project Support

Auto-loops are keyed by projectPath::branchName. Multiple projects can run loops simultaneously. The key function:

typescript
function getWorktreeAutoLoopKey(projectPath: string, branchName: string | null): string {
  const normalizedBranch = branchName === 'main' ? null : branchName;
  return `${projectPath}::${normalizedBranch ?? '__main__'}`;
}

startAutoLoopForProject(projectPath, branchName, config) starts a loop for a specific worktree. stopAutoLoopForProject(key) stops it.

Configuration

typescript
interface AutoModeConfig {
  maxConcurrency: number;
  useWorktrees: boolean;
  projectPath: string;
  branchName: string | null; // null = main worktree
}

Settings read from workflowSettings in .automaker/settings.json:

SettingDescription
agentExecutionModelPrimary model for agent execution
maxConcurrencyMax parallel agents (capped at system limit)
useWorktreesEnable per-feature git worktrees
autoLoadClaudeMdAuto-inject CLAUDE.md into agent context
mcpServersMCP server config passed to Claude SDK
planningModeEnable plan approval gating

Prometheus Metrics

MetricTypeDescription
agent_cost_totalCounterCumulative cost (USD) across all agents
agent_execution_durationHistogramFeature execution time (seconds)
active_agents_countGaugeCurrently running agents
agent_tokens_input_totalCounterTotal input tokens consumed
agent_tokens_output_totalCounterTotal output tokens generated
agent_executions_totalCounterTotal feature executions

Key Files

FileRole
apps/server/src/services/auto-mode-service.tsCore service — loop orchestration and public API
apps/server/src/services/auto-mode/execution-service.tsPer-feature execution logic
apps/server/src/services/auto-mode/concurrency-manager.tsConcurrency slot management
apps/server/src/services/auto-mode/auto-loop-coordinator.tsPer-worktree loop state
apps/server/src/services/auto-mode/feature-state-manager.tsStatus persistence, notifications, app_spec sync
apps/server/src/services/auto-mode/typed-event-bus.tsType-safe event wrappers
apps/server/src/services/feature-scheduler.tsLoop tick and feature dispatch
apps/server/src/services/lead-engineer-service.tsClaude Agent SDK invocation
apps/server/src/services/stream-observer-service.tsAgent output monitoring (loop detection)
apps/server/src/services/recovery-service.tsCrash recovery and resume logic

Built by protoLabs — Open source on GitHub