How Routa’s Kanban Lane Specialist System Works: Automating Workflows with AI Agents
Routa’s Kanban lane specialist system treats each board column as an automated workflow orchestrated by small, purpose-built AI agents (specialists) that execute specific stages of work and enforce quality gates before cards can advance.
The open-source project phodal/routa implements a sophisticated automation layer on top of traditional Kanban boards. Unlike simple status columns, Routa’s lanes can host multi-step specialist workflows where each step represents a distinct agent—such as a code reviewer, test runner, or deployment specialist—that must complete before the task moves forward.
Core Architecture of the Lane Specialist System
The system centers on the concept that a Kanban column defines an automation object containing one or more KanbanAutomationStep entries. These steps are defined in src/models/kanban.ts and specify which specialist should handle the work through flexible selectors.
Automation Definition and Step Configuration
Each automation step can target a specialist using multiple identification fields. According to the model definitions in the repository, a step may include:
{
specialistId?: string; // Exact specialist identifier
specialistName?: string; // Human-readable name
role?: string; // Role such as "developer" or "reviewer"
providerId?: string; // Backend provider (e.g., "anthropic")
}
Columns with single steps automatically select that specialist. Multi-step lanes require the system to resolve which step is currently active based on the task’s assignment metadata and any running lane sessions.
State Resolution and Step Matching
The heart of the resolution logic lives in src/core/kanban/lane-automation-state.ts. The exported function resolveCurrentLaneAutomationState constructs a CurrentLaneAutomationState object that captures:
- The
currentColumnIdwhere the task resides - The ordered list of automation
stepsfor that column - The active lane session (retrieved via
getTaskLaneSessionfromsrc/core/kanban/task-lane-history.ts) - The
currentStepIndexand references tocurrentStepandnextStep
When no lane session exists, the system invokes findStepIndexFromTaskAssignment to score every step against the task’s fields (assignedProvider, assignedRole, assignedSpecialistId, assignedSpecialistName) using the getStepMatchScore algorithm. The highest-scoring match becomes the active step. If the system cannot infer a step in a multi-step lane, it logs a warning to aid debugging.
Blocking Mechanisms and Quality Gates
Routa enforces workflow integrity by preventing task movement while specialists are active. UI components call buildRemainingLaneStepsMessage(taskTitle, state) from lane-automation-state.ts (lines 55–71) to generate user-facing blockers.
If state.hasRemainingSteps returns true, the function produces messages such as:
Cannot move "Add login page" out of Review yet: code-review is still active and testing must run next in the same lane.
This mechanism ensures that quality gates are respected—cards cannot bypass automated code review or testing stages simply by manual drag-and-drop operations.
Specialist Execution and Session Tracking
When a step becomes active, the orchestration engine invokes the specialist runner located at tools/hook-runtime/src/specialist-review.ts. This module loads specialist definitions from YAML files in resources/specialists/ (or falls back to built-in defaults) and executes them via the configured LLM provider.
Session persistence is handled through TaskLaneSession records managed by getTaskLaneSession in src/core/kanban/task-lane-history.ts. Each session tracks:
- The
stepIndexcurrently executing - The
statusenum value (running,transitioned, orcompleted) - Hand-off data between specialists
This allows the system to resume interrupted workflows—for example, if a code review specialist fails due to a missing API key (surfaced as "Automatic review specialist unavailable"), the task retains its context when the system retries.
Practical Implementation Example
The following TypeScript example demonstrates how to resolve the current automation state for a task and handle blocking logic in a custom UI:
import { resolveCurrentLaneAutomationState } from "@/core/kanban/lane-automation-state";
import { buildRemainingLaneStepsMessage } from "@/core/kanban/lane-automation-state";
import { getBoardColumns } from "@/core/kanban/boards";
// Task entering the "Review" column
const task = {
id: "T-123",
title: "Add login page",
columnId: "review",
assignedSpecialistId: "code-reviewer",
assignedProvider: "anthropic",
};
const boardColumns = await getBoardColumns();
const laneState = resolveCurrentLaneAutomationState(task, boardColumns);
if (laneState.hasRemainingSteps) {
console.log(
`Task "${task.title}" is waiting on specialist:`,
laneState.currentStep?.specialistName ?? laneState.currentStep?.specialistId
);
}
// Generate UI blocker message
const blockMsg = buildRemainingLaneStepsMessage(task.title, laneState);
if (blockMsg) {
alert(blockMsg); // Prevent lane movement in the UI
}
Summary
- Lane specialization: Each Kanban column defines automation steps in
src/core/kanban/lane-automation-state.tsthat map to specific AI specialists viaKanbanAutomationStepconfigurations. - Dynamic resolution: The
resolveCurrentLaneAutomationStatefunction determines the active step by matching task assignments against step selectors or resuming existing lane sessions fromtask-lane-history.ts. - Movement blocking: The
buildRemainingLaneStepsMessageutility enforces workflow integrity by generating descriptive error messages when tasks attempt to leave lanes with incomplete specialist steps. - Session persistence:
TaskLaneSessionrecords insrc/core/kanban/task-lane-history.tstrack step indices and status, enabling recovery from interruptions and maintaining state across specialist hand-offs. - Execution runtime: Specialists run through
tools/hook-runtime/src/specialist-review.ts, which loads YAML definitions and manages provider-specific LLM interactions.
Frequently Asked Questions
How does Routa determine which specialist to run in a multi-step lane?
Routa uses the findStepIndexFromTaskAssignment helper in lane-automation-state.ts to calculate a match score for each step against the task’s assignedProvider, assignedRole, assignedSpecialistId, and assignedSpecialistName fields. The step with the highest score becomes active. If a lane session already exists from a previous run, the system resumes from the recorded stepIndex instead.
Can users manually move a card while a specialist is running?
No. The buildRemainingLaneStepsMessage function checks state.hasRemainingSteps and returns a blocking message if any automation steps remain incomplete. This prevents manual bypassing of automated quality gates such as code review or security scanning.
Where are specialist definitions stored and how are they loaded?
Specialist definitions are stored as YAML files in resources/specialists/ or as built-in defaults. The specialist-review.ts runtime in the tools/hook-runtime package loads these definitions and executes them against the configured provider (e.g., Anthropic), handling errors such as missing API keys gracefully.
What happens if a specialist execution is interrupted?
The system maintains TaskLaneSession records in src/core/kanban/task-lane-history.ts that persist the stepIndex, status (running, transitioned, or completed), and hand-off data. When resolveCurrentLaneAutomationState is called again, it retrieves the most recent session via getTaskLaneSession and resumes the workflow from the exact point of interruption.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →