Skip to content

Lanes

A Lane ties everything together: one ticketing source, one or more repos, and the modules to use. Think of it as a pipeline definition — "watch these tickets, work in these repos, behave this way." You'll typically have one Lane per project or repo-group, and every run (record) belongs to exactly one Lane.

Each Lane polls its ticketing source on its own interval. How a ticket is picked up depends on the tracker: on a label tracker (GitHub Issues) a ticket is eligible when it carries all of the Lane's discovery labels; on a status tracker (Jira / Shortcut) when it sits in the Lane's Ready status. Either way it's your per-ticket on/off switch, and it can route tickets to different Lanes (e.g. ai-eligible → a small-fixes Lane on a cheap model, ai-complex → a heavy Lane on a strong one).

Creating a Lane

Prerequisites: a Ticketing module and a Version Control module (Modules), each backed by a working credential. Then Lanes → New Lane.

The form is organized into five tabs:

  1. Basics — name, polling, on/off, notes.
  2. Connections — the ticketing source, the repo host, and the repos. Every required field lives in these first two tabs.
  3. Agent Context — what the agents know beyond the ticket: coding standards, optimization, history, tests.
  4. Execution — how the run behaves: agent tuning, model choice.
  5. Output & Behavior — what the run emits: silent mode, commit identity, messaging.

The minimum viable Lane:

  1. Name it (Basics).
  2. Pick your Ticketing module and set the pickup trigger — discovery labels or a Ready status (Connections).
  3. Confirm the Existing tickets (cold-start) check so a pre-existing backlog doesn't run by surprise (Connections, create only — see below).
  4. Pick your Version Control module and add at least one repo, pressing Verify on each row (Connections).
  5. Press Create Lane.

Everything past Connections is optional tuning with sensible defaults. If a save fails validation, the tab holding the problem is flagged and the form jumps to it. Once created, the Lane starts polling immediately if enabled.

(Missing a module? Each module dropdown in the form links straight to creating one, so you don't have to abandon a half-filled Lane.)

The rest of this chapter walks the form tab by tab.

Basics

  • Name (required) — plus an optional Description.
  • Poll interval (seconds) — how often this Lane checks its ticketing source. Default 30 s; min 5 s, max 24 h.
  • Enabled — a disabled Lane keeps its config but stops polling.
  • Notes — freeform markdown for you and your team: links, quirks, deploy notes, gotchas. Human-only — notes are never included in run context (agent-facing guidance belongs in Coding Standards or the Optimize guide). On a saved Lane, notes save immediately with their own Save button, so a quick note edit doesn't mean re-saving the whole form.

Connections

Everything Tenbi talks to: the ticket source, the repo host, and the repos themselves.

Ticketing

Pick your Ticketing module. The form then adapts to the tracker's vocabulary:

Label trackers (GitHub) ask for:

  • Discovery (labels — AND together) — a ticket must have all of these labels to be picked up. Most Lanes need exactly one; press Add condition only when you want a narrower AND-match.
  • Re-run label — default ai-redo; covered under Lifecycle below.
  • Label transitions — an expandable panel of per-stage label updates, defaults pre-filled; also under Lifecycle.

Status trackers (Jira / Shortcut) show the Lifecycle mapping instead:

  • A required Ready status — the pickup trigger.
  • Optional per-stage status moves: the pipeline (ReadyIn ProgressDone) plus the exit states (Failed / Cancelled). In Progress carries a recommended tag in the form — the Lifecycle section below explains why it earns it.
  • The form fetches the real status names from your tracker and renders dropdowns. If that fetch fails (bad credential, network hiccup), you can type the status names manually instead of being blocked.

Statuses, not columns. The status dropdowns list your tracker's workflow statuses — not its board columns. A Kanban column can map to a different underlying status name, so pick from the actual statuses your project defines.

Existing tickets (cold-start)

Shown at create only. Your source may already hold tickets matching the discovery you just configured, and a brand-new Lane must not silently sweep that backlog on its first poll. So before creating, press Check for existing tickets (it needs the ticketing module and the discovery labels — or the Ready status — filled in first; the check works the same on both tracker kinds):

  • No matches — nothing to confirm. (If you expected matches, the discovery config may be mis-scoped — worth a second look before saving.)
  • N matches — the panel shows the count and asks what to do with them:
    • Process none — dismiss them (recommended) (the default) — the backlog is skipped; the Lane only works tickets from here on.
    • Process all — every existing match is worked once the Lane goes live.
    • Pick which to process — a checkbox list of the matching tickets (each linked, so you can open it and decide); ticked tickets are worked, the rest are dismissed.

The check itself is read-only — nothing is touched until you press Create Lane. At that point, dismissed tickets are written as cancelled skip-records, so polling never picks them up — but they're not gone for good: open the dismissed ticket's record and press Rerun to revive it later. Tickets labelled (or moved into Ready) after the Lane exists are unaffected either way — cold-start only concerns the pre-existing backlog.

Version Control

Pick your Version Control module — the repo host (GitHub, Bitbucket, or Azure) where Tenbi pushes branches and opens pull requests.

Optionally set a Lane-level default base branch; leave it blank to use the Version Control module's default. (Full precedence under Workspace Repos below.)

Workspace Repos

At least one repo. Each row has:

  • A nameowner/repo on GitHub, workspace/repo on Bitbucket, project/repo on Azure Repos.
  • A role — a short label like primary, api, or frontend that becomes the repo's folder name in the agent's workspace. Roles must be unique within a Lane — they become folder names, so two repos with the same role collide.
  • A Verify button — press it on each row to confirm the credential can reach the repo before you rely on it. On success it also reports the repo's default branch, and fills the per-repo base branch for you if you left it empty. If you set a base branch that doesn't exist on the repo, Verify flags that too.

The tuning knobs:

  • Multi-repo Lanes: add several repos and a single ticket gets a workspace containing all of them — the agents make coordinated changes across repos, and every repo that ends up modified gets its own PR in one run. Use roles the agents can understand (frontend / backend beats repo1 / repo2).
  • Advanced (per repo): an explicit clone URL (auto-derived from the name if blank) and a per-repo base branch override.
  • Base branch precedence: per-repo → Lane default → Version Control module default → main.

Lifecycle

Configured in the Ticketing section above, but it earns its own walkthrough. As a run progresses, the Lane updates the ticket so anyone looking at the board sees the state without opening Tenbi. The Ticketing section is adapter-aware — it speaks whichever vocabulary your tracker uses:

  • Label trackers (GitHub) — the Label transitions panel: per stage, labels to add and remove (comma-separated). Sensible defaults are pre-filled; clear both fields on a row to disable that transition.
  • Status trackers (Jira / Shortcut) — per stage, a single status to move the ticket to, chosen from the tracker's own workflow statuses.

The stages are the same either way. Only Ready is required; the rest are optional — leave a stage blank to skip it.

StageFires when
Ready (required — the trigger)A ticket here is picked up
In Progress (recommended)The ticket is picked up
DoneThe run finishes (the PR is opened)
FailedThe run fails
CancelledThe run is cancelled

For reference, the pre-filled label-tracker defaults:

StageAddsRemoves
In Progress (on pickup)ai-in-progressai-eligible
Doneai-completedai-in-progress
Failedai-failedai-in-progress
Cancelledai-cancelledai-in-progress

Updates are best-effort — a tracker API hiccup is logged but never fails the run.

Records are the truth. Board labels and statuses are reflection for humans; whether a ticket runs is decided by its run records, not by what's on the board. That's why a stale or failed label write can't cause a double run — a finished ticket is never re-picked-up by accident even if a lifecycle update didn't land.

Re-running a finished ticket

A finished ticket already has a run record, so it won't be picked up again on its own — re-running takes a deliberate, distinct signal:

  • Label trackers — add the Lane's Re-run label (default ai-redo) to the finished ticket. It's removed once the re-run starts. (Re-applying the discovery label does nothing — the ticket already has a record.) Leave the field empty to disable label re-runs; the Rerun button still works.
  • Status trackersmove the ticket back to the Ready status. Tenbi sees it's back in Ready after a finished run and re-runs it.
  • Any tracker — the Rerun button on the record itself.

Status trackers: map In Progress. The move-back-to-Ready re-run only works if In Progress is mapped to a status — that's what moves the ticket out of Ready on pickup, so its later return to Ready is an unambiguous "do it again." Leave In Progress blank and a finished ticket just sits in Ready; re-runs then need the Rerun button on the record instead. (Mapping it also keeps the board honest — otherwise a ticket being actively worked still shows as Ready.) One caveat: the mapping has to actually work — if the In Progress move can't be applied (e.g. the transition isn't reachable in your Jira workflow), the ticket never leaves Ready and the re-run edge can fire again. Tenbi logs the failed move; keep the mapping valid.

The signals differ in reach:

  • The two board signals (re-run label, move-back-to-Ready) fire only on tickets whose last run reached Done or Failed — never on a cancelled one. A run you deliberately stopped (or a ticket you dismissed at cold-start) stays stopped no matter what the board says.
  • The Rerun button works on any finished record — Done, Failed, or Cancelled. It's the one way to revive a cancelled run or a cold-start dismissal.
  • On silent Lanes both board signals are disabled (see Silent mode below); the button is the only re-run path.

Two more re-run behaviors worth knowing:

  • One run at a time per ticket. While a run for a ticket is in flight, no re-run signal fires and the Rerun button refuses — two concurrent runs would race toward two PRs for the same ticket. Wait for the current run to finish (or cancel it) first.
  • The ticket is re-fetched. Every re-run re-reads the ticket first, so clarifying comments you added after the last attempt are part of the new run's context.

Agent Context

What the agents know beyond the ticket itself. All of it optional; the defaults are sensible.

Coding Standards

Attach a Coding Standards module and its markdown is written to each repo's worktree as CODING-STANDARD.md at the start of every run. See Modules.

Optimize

One checkbox — Optimize this Lane's repos — turns on hosted context optimization: Tenbi pre-digests your repos so runs skip re-parsing them. It costs a bit up front, then saves on every run after, like prompt caching. It gets a chapter of its own: Optimize.

Cross-ticket history

Two toggles, both on by default.

Let the PM phase consult prior tickets in this Lane — the planning agent can see what this Lane has already done:

  • Recent finished and failed runs — their tickets, PRs, and what they produced, as bounded summaries.
  • One prior artifact in full (e.g. the PRD of a clearly related ticket) when the summary isn't enough.

The point is continuity: the agent doesn't re-derive decisions or retry approaches that already failed. It's pull-based — history is only fetched when the agent judges a past run relevant, so the added cost is small — but it uses your model credits when it does. Turn it off to keep every run strictly scoped to its own ticket.

Read reviewer feedback when re-running a ticket — a re-run reads the reviewer's comments on the prior attempt's PR and folds them into the new plan, so a redo addresses what was flagged instead of repeating it. It only fires on re-runs (a first attempt is a no-op) and uses your model credits when it fetches. Turn it off to keep re-runs clean-room.

Testing

Commit tests to the PR — on by default. When off, Tenbi still writes and runs the tests (the change is verified either way) but leaves them out of the PR — for teams that want the verification without an agent's tests landing in the repo. Only applies when the repo has a test framework; repos with no test setup never get tests either way.

Execution

How the run itself behaves.

Agent Tuning (beta)

Attach an Agent Tuning module to layer your custom per-agent instructions onto the run. Standard agent behavior is preserved — only your additions layer on top. See Modules.

Model

Per-Lane override of the global default from Settings: pick the Claude model for this Lane, or leave it blank to inherit. This is the main cost/quality routing lever — cheaper models for low-risk Lanes (small bugs), stronger models for complex ones.

Output & Behavior

What the run emits — and who it looks like.

Silent mode (beta)

For working a ticket without the orchestrator visibly touching it. With silent mode on, the run still happens end to end — but every observable surface is muted.

Still happens:

  • The ticket is picked up, worked, and committed.
  • The branch is pushed to the repo host.
  • The record captures everything on Tenbi's side, as always.

Suppressed:

  • Ticket comments — none are posted.
  • Lifecycle updates — no labels change, no statuses move.
  • The PR — not opened.
  • Notifications — none fire, Messaging channels and email alike.

Everything that would have been posted (comments, labels, the PR title and body) is saved on the record so you can read or copy it later and open the PR yourself.

Silent mode also disables both board re-run signals — the redo label would never be cleared and the status move-out never happens, so either signal would re-fire forever. Silent Lanes re-run via the Rerun button only.

Commit identity controls who the commits appear authored by. Leave both fields blank and silent mode auto-detects the identity from your Version Control token (GitHub today); set name + email to force a specific author. If neither is available, commits fall back to Ticket Orchestrator <ai@orchestrator.local>.

Messaging

Attach one or more channels (Discord / Slack modules) and pick each one's hooks — PR opened, Run failed, or both (a newly added channel starts with both checked). The same channel module can serve many Lanes with different hooks on each.

Workflow

The phase list at the bottom — which agents run, in what order — is read-only and shows the engine default:

PhaseAgent
PlanningPM
CodingArchitect
CodingTest Author
CodingDeveloper
ReviewingQA
FinalizingDevOps

Per-Lane workflow editing lands in a later release.

Protected paths

A run's changes should trace to the ticket. Some paths are privileged enough that Tenbi enforces this mechanically: by default, .github/workflows/ (GitHub Actions CI/CD definitions) is protected — if the agents modify a protected path the ticket didn't authorize, those changes are stripped from the branch before anything is pushed. The rest of the work ships normally, and the removed changes are attached to the PR description under "Suggested follow-ups (not applied)", diff included, so you can review the idea and apply it deliberately if you want it.

Two ways to authorize protected-path changes:

  • Per ticket — add the allow-protected-paths label to the ticket before it's picked up. That run may then change protected paths freely (they still go through review like everything else — Tenbi never merges).
  • Per Lane — the Lane's protected-path list is configurable: add prefixes (e.g. infra/, Dockerfile) to protect more, or set the list empty to disable the gate entirely.

Heads up on GitHub token scope: pushing workflow-file changes also requires the workflow scope on your PAT — see Credentials. If you grant allow-protected-paths on a ticket that touches CI, make sure the token has that scope, or the push will be rejected by GitHub itself.

Day-to-day

  • Watch it work — once the Lane is live, picked-up tickets appear as records on the Dashboard.
  • Pause a Lane — uncheck Enabled; config and history stay put.
  • Edit safely — each run snapshots the Lane's config when the ticket is picked up, so edits never affect runs already in flight, only future pickups.
  • Delete — removes the Lane, but existing records under it are kept (each carries its own config snapshot).
  • Refresh one repo's optimization — each repo row on a saved Lane has a Run indexer button; details in Optimize.
  • Modules — the reusable building blocks a Lane attaches.
  • Optimize — the per-Lane context optimization behind the Optimize checkbox.
  • Dashboard — watching the records a Lane produces.
  • Troubleshooting — when a Lane doesn't behave as described here.