# Auto Build routing

> Plan/build/verify/refine tiers, heuristic vs Flue controller routing, orchestration plans, mission control policies, failure cooldowns, and CLAUDE_AUTO_ROUTE_DECISION events.

- Repository: Parcha-ai/build
- GitHub: https://github.com/Parcha-ai/build
- Human docs: https://grok-wiki.com/public/docs/parcha-ai-build-bea5702b371b
- Complete Markdown: https://grok-wiki.com/public/docs/parcha-ai-build-bea5702b371b/llms-full.txt

## Source Files

- `src/main/services/auto-router.service.ts`
- `src/main/services/flue-meta-router.service.ts`
- `src/shared/types/index.ts`
- `src/renderer/components/chat/AutoRouteBadge.tsx`
- `src/shared/constants/channels.ts`
- `scripts/verify-auto-router-plan-mode.ts`

---

---
title: "Auto Build routing"
description: "Plan/build/verify/refine tiers, heuristic vs Flue controller routing, orchestration plans, mission control policies, failure cooldowns, and CLAUDE_AUTO_ROUTE_DECISION events."
---

When the session model is `auto`, `claude.service` calls `autoRouterService.classifyAndRoute()` in the main process before streaming. That returns a `RoutingDecision` (tier, harness, model, orchestration plan, mission-control policy) and pushes it to the renderer on `claude:auto-route-decision` (`IPC_CHANNELS.CLAUDE_AUTO_ROUTE_DECISION`). Routing combines a deterministic heuristic classifier, an optional Cerebras-backed Flue meta-controller, per-session failure cooldowns, and multi-stage orchestration executed by `claude.service`.

## Routing pipeline

```mermaid
sequenceDiagram
  participant UI as Renderer (InputArea)
  participant CS as claude.service
  participant AR as autoRouterService
  participant FM as flueMetaRouterService
  participant Exec as Harness executors

  UI->>CS: sendMessage (model = auto)
  CS->>AR: classifyAndRoute(sessionId, message, options)
  AR->>AR: classifyHeuristic + workflow + permission
  opt Cerebras key present
    AR->>FM: route (structured JSON)
    FM-->>AR: FlueMetaRouteDecision or null
  end
  AR->>AR: chooseModel + buildOrchestrationPlan
  AR-->>CS: RoutingDecision
  CS->>UI: CLAUDE_AUTO_ROUTE_DECISION
  CS->>Exec: stream lead harness + optional delegate stages
```

<Steps>
<Step title="Classify intent">
Heuristic scoring assigns `requestedTier` from keywords, GStack mode, permission mode, attachments, and session phase.
</Step>
<Step title="Apply workflow rules">
`applyWorkflowAwareness` may shift tier (for example plan-before-build for complex work, build-after-plan for “go ahead”).
</Step>
<Step title="Run meta-controller (optional)">
If a Cerebras API key exists and confidence ≥ 0.55, Flue may override tier, model, and delegate stages (`method: 'controller'`).
</Step>
<Step title="Resolve execution">
Pick lead model/harness, merge `MetaHarnessPolicy`, build `OrchestrationPlan`, emit IPC event, stream lead then delegate stages.
</Step>
</Steps>

<ParamField body="RouteOptions" type="object">
Optional inputs to `classifyAndRoute`: `gstackMode`, `permissionMode`, `attachmentCount`, `attachmentTypes`, `recentMessages`, `isSSH`, `remoteCliCapabilities`, `goalObjective`, `goalSource`, `skipMetaController`.
</ParamField>

## Plan, build, verify, and refine tiers

| Tier | Typical intent | Default model (`DEFAULT_CONFIG`) |
|------|----------------|----------------------------------|
| `plan` | Design, risk, architecture, reviews before edits | `claude-sonnet-4-6` |
| `build` | Implementation, wiring, feature work | `codex:gpt-5.5` |
| `verify` | Tests, QA, debugging, root-cause investigation | `codex:gpt-5.5` |
| `refine` | Small UI/copy/docs tweaks | `cursor:composer-2.5` |

`TaskDomain` further scopes routing: `copy`, `frontend`, `backend`, `fullstack`, `debug`, `ops`, `docs`, `data`, `general`. Domain and attachment signals influence model candidates (for example frontend → Cursor Composer, backend → Codex).

Heuristic tiers use scored keyword lists (`PLAN_SIGNALS`, `BUILD_SIGNALS`, `VERIFY_SIGNALS`, `REFINE_SIGNALS`) plus special cases: capability-escalation phrases force `plan`, GStack modes (`plan-ceo-review`, `qa`, `investigate`, …) override, and `permissionMode === 'plan'` forces planning. `enforcePermissionMode` downgrades `build`/`refine` to `plan` when the session cannot mutate (`plan` or `dontAsk` permission modes).

## Heuristic classifier (fallback path)

The heuristic path always runs first. Its output is stored as `deterministicResult` and used when:

- No `cerebrasApiKey` / `EMBEDDED_KEYS.cerebras` / `CEREBRAS_API_KEY` is available
- Flue returns `null` (runtime failure, timeout, unsupported Node, auth cooldown)
- Controller confidence is below `META_MIN_CONFIDENCE` (0.55)
- `getMetaRouteRejectionReason` rejects a contradictory controller route (for example prompt-injection patterns forcing a different tier)

<Note>
`shouldUseDeterministicFastPath` is intentionally disabled: every request attempts the meta-controller when a key exists; heuristics are not skipped on “easy” messages.
</Note>

`RoutingDecision.method` is `'heuristic'` unless a valid controller decision is accepted, then `'controller'`. There is no separate `'llm'` method; legacy direct LLM classifiers were removed.

## Flue meta-controller

`flueMetaRouterService` loads `@flue/runtime` (optionally via `FLUE_RUNTIME_NODE_MODULES`), configures the Cerebras provider, and prompts `cerebras/gpt-oss-120b` for a single structured routing JSON object. The sandbox denies file I/O and shell execution so the controller only decides routing.

| Constant | Value | Role |
|----------|-------|------|
| `FLUE_TIMEOUT_MS` | `9000` (override with `FLUE_META_ROUTER_TIMEOUT_MS`) | Abort slow controller calls |
| `FLUE_FAILURE_COOLDOWN_MS` | `60000` | Back off after generic errors |
| `FLUE_AUTH_FAILURE_COOLDOWN_MS` | `600000` | Back off after 401/invalid API key |
| `FLUE_ROUTE_CACHE_TTL_MS` | `15000` | Dedupe identical prompts per session |

<Warning>
Flue requires Node **≥ 22.18**. Older Node versions skip the controller entirely.
</Warning>

Controller output fields map into `RoutingDecision`: `requestedTier`, `leadTier`, `leadModel`, optional `matchedCategoryId`, `confidence`, `reason`, and `stages[]` with triggers. Reasons are redacted for user-visible text (internal terms like “Flue meta-harness” become “workflow routing”). `sanitizeMetaLead` prefers the first configured candidate per tier unless the user asked for capability escalation.

## Orchestration plans

`OrchestrationPlan` describes how one user turn may span multiple harnesses:

<ResponseField name="mode" type="'single' | 'lead-with-delegates' | 'sequential'">
`single` when only the lead stage runs; `lead-with-delegates` when multiple harnesses participate; `sequential` when multiple stages share one harness.
</ResponseField>

<ResponseField name="stages" type="OrchestrationStage[]">
Each stage has `tier`, `harness`, `model`, `purpose`, `required`, `trigger`, optional `fallbackModels`, and per-stage `MetaHarnessPolicy` fields.
</ResponseField>

<ResponseField name="contextPolicy" type="object">
Controls handoff payload size: transcript references, plan file reference, `maxHandoffConversationChars: 24000`, project instructions, skills, agents, memories.
</ResponseField>

<ResponseField name="handoffPrompt" type="string">
Injected coordination text for the lead harness; tells the agent to avoid mentioning internal sequencing unless asked.
</ResponseField>

### Stage triggers

| Trigger | When used |
|---------|-----------|
| `now` | Lead stage (always first) |
| `after-plan` | Build or verify after planning completes |
| `after-build` | Verification after implementation |
| `on-failure` | Optional refine delegate when lead output mentions errors |
| `manual-follow-up` | Reserved; not auto-run |

Deterministic `buildOrchestrationPlan()` adds delegates when, for example, the user requested `build` but lead is `plan` and a Codex/Cursor/Gemini/OpenCode delegate is available. Controller plans merge Flue `stages` with required deterministic follow-ups so verification is not dropped.

After the lead stream finishes, `streamAutoBuildStages()` runs delegate stages (Codex, Cursor, Gemini, OpenCode only—not Claude/custom as helpers). Failures call `recordHarnessFailure`; successes call `recordHarnessSuccess` and `recordTierCompletion`.

## Mission control policies

`RoutingDecision.missionControl` is a `MetaMissionControlPolicy`:

- `controllerHarness: 'meta'` — routing brain is Flue, not the executing harness
- `requestedTier` — raw user intent tier from classifier/controller
- `leadTier` / `leadHarness` / `leadModel` — what runs first this turn
- Optional `categoryId` / `categoryLabel` when a custom settings category matched

Per-tier and per-category **MetaHarnessPolicy** fields ride on the decision and lead stage:

| Field | Values | Effect |
|-------|--------|--------|
| `effort` | string (e.g. thinking level) | Passed to Claude lead as `thinkingMode` when set |
| `speed` | `auto`, `standard`, `fast` | Harness speed hint |
| `workflow` | `auto`, `single`, `lead-with-delegates`, `sequential`, `dynamic` | Exposed on decision; orchestration `mode` may differ |
| `budgetUsd` | number | Budget cap hint |
| `verification` | `auto`, `none`, `optional`, `required` | Whether verify delegates are added/required |

Plan-tier routes also force `autoBuildLeadPermissionMode = 'plan'` in `claude.service` so the lead harness cannot mutate files until the user approves execution.

## Failure cooldowns

Per-session maps track helper failures:

- **Harness cooldown** (`sessionHarnessFailures`): codex, cursor, gemini, opencode — base 10 minutes, scales with repeat failures up to 60 minutes
- **Model cooldown** (`sessionModelFailures`): custom harness models and explicit model strings
- **Claude** harness failures are not cooled down (always available as fallback)

Cooldowns are restored from recent assistant messages (`Lead error:`, `Auto Build helper could not complete`) and from `message.metadata.workflowFailures`. `formatActiveHarnessCooldowns` appends avoidance text to the routing `reason`. Successful runs clear cooldowns; Cursor auth failures clear when `cursor-agent status` shows logged-in again.

Flue service failures use separate global cooldowns (60s / 10m auth) independent of per-harness session cooldowns.

## `CLAUDE_AUTO_ROUTE_DECISION` event

| Property | Value |
|----------|-------|
| Channel | `IPC_CHANNELS.CLAUDE_AUTO_ROUTE_DECISION` → `'claude:auto-route-decision'` |
| Direction | Main → renderer (push event, not invoke) |
| Payload | `{ sessionId: string; decision: RoutingDecision }` |

Emitted immediately after routing resolves, before the lead stream yields `system` info with `resolvedModel`.

**Preload:** `window.electronAPI.claude.onAutoRouteDecision(callback)` registers the listener; returns an unsubscribe function.

**Renderer store:** `session.store` writes `autoRouteDecision[sessionId]`, updates `activeStreamModel`, and seeds `activeMetaGoals` when `decision.goal` is present.

**UI:** When the model picker is `auto`, `InputArea` shows `AutoRouteBadge` with tier/domain colors and harness label (compact while sending).

```typescript
// Payload shape (simplified)
{
  sessionId: string;
  decision: {
    tier: 'plan' | 'build' | 'verify' | 'refine';
    domain?: TaskDomain;
    resolvedModel: string;
    resolvedHarness?: Harness;
    confidence: number;
    reason: string;
    method: 'heuristic' | 'controller';
    missionControl?: MetaMissionControlPolicy;
    orchestration?: OrchestrationPlan;
    goal?: { objective: string; source: 'slash-command' | 'ralph-loop' };
    // ...effort, speed, workflow, budgetUsd, verification
  };
}
```

<Info>
`enableGoals` is set for verify-tier routes or when a `/goal` objective is active; Codex goals may be auto-enabled in `~/.codex/config.toml` for delegated verification.
</Info>

## Cost-aware and learned routing

When `autoRouterConfig.costAware` is true (default), plan-tier Opus is downgraded to Sonnet unless the user explicitly configured plan Opus. `analyticsService.getHarnessInsightsForTier()` may reorder candidates when override/success stats justify it; analytics failures never block routing.

## Configuration and verification

Defaults and UI-editable fields live in `claudette-settings` → `settings.autoRouterConfig` (see **Auto Build configuration**). API keys gate harness availability: OpenAI/Codex, Google/Gemini, Cursor CLI, DeepSeek/OpenCode, custom proxy models, plus Cerebras for the controller.

Regression scripts (run individually or via `npm run verify:auto-router:meta-harness`):

<CodeGroup>
```bash title="Controller confidence gate"
npm run verify:auto-router:controller-confidence
```

```bash title="Plan permission mode wiring"
npm run verify:auto-router:plan-mode
```

```bash title="Flue fallback when controller fails"
npm run verify:auto-router:flue-fallback
```
</CodeGroup>

<Check>
After changing routing logic, run the meta-harness quality gate before release; live Flue eval needs `CEREBRAS_API_KEY` and `FLUE_RUNTIME_NODE_MODULES`.
</Check>

## Related pages

<CardGroup>
<Card title="Auto Build configuration" href="/auto-build-configuration">
`AutoRouterConfig` fields, category editor, and `verify:auto-router:*` scripts.
</Card>
<Card title="Shared types reference" href="/shared-types-reference">
`RoutingDecision`, `OrchestrationPlan`, `OrchestrationStage`, `SessionPhase`, `MetaHarnessPolicy`.
</Card>
<Card title="Harnesses and models" href="/harnesses-and-models">
Harness prefixes (`codex:`, `cursor:`, …) and permission modes that constrain routing.
</Card>
<Card title="IPC channels reference" href="/ipc-channels-reference">
Full `IPC_CHANNELS` catalog including `claude:auto-route-decision`.
</Card>
<Card title="Settings reference" href="/settings-reference">
`autoRouterConfig` defaults in `claudette-settings`.
</Card>
</CardGroup>
