Custom Workflows & Transitions
Kangentic’s board isn’t just a task tracker - each column can trigger actions when tasks arrive. This lets you build automated pipelines like Plan > Execute > Review without manual intervention.
Default Board Layout
Section titled “Default Board Layout”New projects start with seven columns. You can add, remove, rename, and reorder them to match your workflow.
| Column | Purpose |
|---|---|
| To Do | Holding area. No agent runs. Dragging a task here ends its session. |
| Planning | Spawns the agent in plan mode. It creates a plan, then the task auto-moves to Executing. |
| Executing | Spawns the agent with the default permission mode. The agent works on the task. |
| Code Review | Agent keeps running. Add a message telling it how to review the work. |
| Testing | Agent keeps running. Add a message telling it how to test the work. |
| Merge | Agent keeps running. Add a message telling it how to ship the work. |
| Done | Suspends the session (preserving context) and archives the task. |
None of the seeded columns carries a message or a description. The defaults are names, icons, and colors only, because what a column should tell its agent depends on your repo and your agent. Both fields are yours to fill in from the Board Manager.
These rows describe the session lifecycle. What the agent actually receives at each move, and why an unconfigured column tells it nothing, is covered in What the Agent Is Told.
What Happens When You Drag a Card
Section titled “What Happens When You Drag a Card”When you drag a task from one column to another, Kangentic evaluates these rules in order:
| Rule | Behavior |
|---|---|
| Target is To Do | Full reset: the session is killed and its history wiped, and the worktree is removed (with its branch, when Auto Cleanup is on). The task is treated as never started. |
| Target is Done | Session is suspended (resumable), task is archived. |
| Target has auto-spawn off | Session is suspended. |
| Task already has a running agent | Agent keeps running. If the target column has an auto-command, it’s injected. |
| Task has no running agent | A new agent is spawned (or a suspended session is resumed). |
The key insight: moving between active columns doesn’t restart the agent. The session stays alive, and only an auto-command is injected if one is configured. This means you can move a task from “Executing” to “Code Review” and the agent seamlessly receives a review prompt.
What the Agent Is Told
Section titled “What the Agent Is Told”The board speaks to an agent at exactly two moments: when its session first spawns, and when its task arrives in a column that has an auto-command. This section is the complete inventory of what crosses that boundary - there is no hidden context.
The first prompt
Section titled “The first prompt”A task’s first move out of To Do spawns a fresh agent, and Kangentic passes it a single prompt as the agent CLI’s own prompt argument. The default spawn template is {{task_xml}}{{attachments}}, which renders as:
<task> <title>Fix login redirect</title> <description>The login page bounces to /home even when ?next= is set.Repro steps and the suspect handler are in src/auth/redirect.ts. </description></task>/Users/you/Desktop/login-bug.pngThe description body sits against the left margin so any markdown inside it, code fences included, survives verbatim. A one-line description is inlined on a single line, and a task with no description omits the <description> tag entirely. Attachments follow as bare absolute file paths, one per line, with no header; a task with no attachments ends at </task>.
That is the entire prompt. Kangentic adds no system preamble of its own, and the column is invisible to the agent: no template variable carries a column’s name or description, so the agent cannot tell whether it spawned into Executing, Merge, or a column you invented. Moving a task back to To Do kills its session, so its next move out spawns a fresh agent and sends the envelope again.
Moves between active columns
Section titled “Moves between active columns”Once a session exists, moving its task between active columns continues the same conversation. The title and description are not re-sent - the agent already has them, and repeating them would duplicate context. The only new input is the destination column’s message, delivered as an ordinary user message typed into the running session (when a move resumes or restarts a session, it rides along as the CLI’s prompt argument instead).
If the destination column has no message, nothing is delivered at all. Every column on the default board ships with an empty message, so out of the box a column’s name carries no behavior of its own. Moving a card to Code Review, Testing, or Merge changes what Kangentic does with the session, not what the agent is told - “agent keeps running” means exactly that. To make arrival in a column mean something to the agent, give that column a message.
The two moments can coincide: a task spawning straight into a column that has a message gets the envelope as its prompt and the message as a follow-up once the session shows its first activity (see timing).
Two already-documented cases adjust what a move delivers: an agent change with handoff context enabled prepends a handoff preamble, and the first move out of Done skips the message (see the note under Auto-Commands).
Auto-Commands
Section titled “Auto-Commands”A column’s Message to agent is a prompt delivered to a running agent when a task arrives in that column. This enables hands-free transitions.
Example: Set a Code Review column’s message to:
Review the code changes you just made. Check for bugs, security issues, and adherence to the project’s coding standards.
When you drag a task from Executing to Code Review, that prompt is automatically sent to the running agent - no manual typing needed.
A column message is free prose. A slash command works too, but nothing requires that shape: whatever you type is delivered verbatim as an ordinary user message in the running conversation.
Column messages support template variables (see below) so they can reference the task’s title, description, or worktree path.
Timing: immediate or deferred
Section titled “Timing: immediate or deferred”Each column also chooses when its message fires, with a timing control beside the message field in Board Configuration:
| Setting | Key | Behavior |
|---|---|---|
| Run immediately | immediate (the default) | Delivers as soon as the task arrives. If the agent is mid-turn the command is not cut off: it is typed and submitted, and the CLI queues it to run once the turn finishes. If a delivery is already in flight for that task, the new one queues behind it rather than being dropped |
| Wait for current turn | deferred | Holds the command Kangentic-side until the agent’s current turn genuinely completes, then delivers |
Delivery is non-destructive in both modes. Nothing Kangentic sends interrupts a running turn: the prompt is cleared with Ctrl+U, a line-editing key, and the escape that dismisses a slash-command picker is never sent while a turn is live.
The difference is where the waiting happens. Run immediately hands the command straight to the agent and lets the CLI hold it in its own queue. Wait for current turn keeps it on Kangentic’s side until the turn has genuinely settled, so the command lands on a quiet prompt, which is what you want when it needs to act on the finished result rather than sit behind it. A deferred wait is capped, so a turn that never settles still delivers rather than hanging forever.
A freshly spawned session is a third case and follows neither setting: delivery waits for the agent’s first activity, so the command does not land before the CLI is ready to read it.
How delivery is verified
Section titled “How delivery is verified”Injection is verified rather than fire-and-forget where the agent’s own history makes that possible. Kangentic reads the CLI’s session history back and looks for the text it just submitted, which is the difference between “we typed it” and “the agent took it as a turn”. A command that has not landed yet is retried on Enter, and that retry rung is what closes the delivery gap in practice.
Nine of the fourteen agents can be verified this way: Claude Code, Codex, GitHub Copilot CLI, Grok Build, Antigravity CLI, OpenCode, Aider, Qwen Code, and Kimi Code. Each reads its own agent’s format, so OpenCode is queried out of its SQLite store rather than a file, Aider is matched in the project’s chat-history markdown, and Claude matches its structured slash-invocation record.
Verifying and escalating are two different permissions, and most agents only have the first:
| Tier | Agents | What a failed delivery does |
|---|---|---|
| Verify and escalate | Claude Code, Codex | Retries on Enter, then escalates once to restarting the session with the command passed as the CLI’s own prompt argument, which the spawn guarantees rather than TUI timing |
| Confirm only | GitHub Copilot CLI, Grok Build, Antigravity CLI, OpenCode, Aider, Qwen Code, Kimi Code | Retries on Enter and reports the outcome. Never restarts the session |
| Unverified | Gemini CLI, Cursor CLI, Factory Droid, Warp (Oz CLI), Ollama | Delivered and recorded as unconfirmed. No retry rung, no escalation |
The confirm-only tier is a deliberate floor, not an oversight. Escalation restarts a session and so destroys live work, which means it takes two separate proofs: that the CLI writes its history fast enough to be read inside the delivery window, and that this particular adapter’s resolver finds that record in a running app. A measurement alone does not establish the second, and a wrong path or an uncaptured session ID would turn every single delivery into a false failure and therefore a restart. Declining to escalate is the non-destructive answer, and the worst case for those seven is a reported failure and a notice.
The three unverified coding agents are a measured verdict rather than an unexplored gap: Gemini, Cursor, and Droid write their history at turn end, or too variably to bound, so nothing readable exists inside the window. Warp and Ollama expose no usable history at all.
One more case stays unconfirmed on purpose. If your auto-command begins with /, Codex, Grok Build, Antigravity, and OpenCode decline to verify it, because absence from the history file is ambiguous there: the CLI may have rejected the command, or it may have run it entirely client-side (/status, /compact) so it never became a conversation turn. Those two need opposite responses and a verifier cannot tell them apart, so Kangentic neither retries nor escalates on a slash command for those agents.
Escalation is also narrower than the tier table alone suggests. It is wired for one delivery path: moving a task between columns while its session is already running. A freshly spawned session’s auto-command is verified and retried the same way, but it stops at a reported failure on every agent rather than escalating. And escalation only happens after the turn-completion check passes, so it can never kill live work.
Either way the outcome is recorded on the task, and a delivery that could not be confirmed raises a notice instead of failing silently.
Plan Mode Workflow
Section titled “Plan Mode Workflow”The default board includes a Planning column configured with:
- Permission mode set to
plan - A plan exit target pointing to the Executing column
Here’s what happens:
- You drag a task to Planning
- Kangentic spawns the agent in plan mode (read-only tools only)
- The agent analyzes the codebase and creates a plan
- When the agent calls
ExitPlanMode, Kangentic detects it - The task automatically moves to the column specified by
plan_exit_target_id(default: Executing) - The agent resumes with full autonomy to implement the plan
This gives you a two-phase workflow: plan first, then execute - with the transition happening automatically.
Configuring Plan Exit Targets
Section titled “Configuring Plan Exit Targets”The plan_exit_target_id column setting controls where a task moves when a plan-mode agent calls ExitPlanMode. You can set this in the column settings dialog under Plan Exit Target.
- If
plan_exit_target_idis set, the task auto-moves to that column when planning completes - If not set (null), the task stays in the plan-mode column after planning finishes
- The target column typically has a less restrictive permission mode so the agent can execute the plan
You can chain multiple plan stages - for example, a “High-Level Plan” column that exits to a “Detailed Plan” column, which exits to “Executing.”
Action Types
Section titled “Action Types”When a task arrives in a column with no running session, Kangentic executes a chain of actions sequentially. For example, the default “move to Planning” transition runs: Kill Session > Spawn Agent.
Available action types:
| Action | Description |
|---|---|
| Spawn Agent | Starts an agent session with a prompt template |
| Send Command | Injects text into a running session’s terminal |
| Run Script | Executes a one-off shell command |
| Kill Session | Suspends the current session (preserving it for later resume) |
| Create Worktree | Creates a git worktree for the task |
| Cleanup Worktree | Removes the task’s worktree and optionally its branch |
| Create PR | Reserved - not yet implemented. |
| Webhook | Sends an HTTP request to an external URL |
Action Chaining
Section titled “Action Chaining”When a task arrives in a column with no running session, Kangentic runs the column’s actions sequentially in execution_order. For example, the default “move to Planning” transition runs two actions in order:
- Kill Session - ends any existing session
- Spawn Agent - starts a new agent session in plan mode
You can build multi-step workflows by chaining actions. Each action in the chain completes before the next begins.
Run Script Example
Section titled “Run Script Example”Use Run Script to execute setup or validation commands:
- Action type: Run Script
- Config:
npm run lint -- --fix- runs a linter before the agent starts, ornpm testto validate before shipping.
Run Script executes a one-off shell command in the task’s worktree directory (or project root if worktrees are disabled). The command runs to completion before the next action in the chain.
Webhook Example
Section titled “Webhook Example”Use Webhook to notify external services when tasks change columns:
- Action type: Webhook
- Config: Send an HTTP POST to a Slack incoming webhook URL, a logging endpoint, or any external API. The request body includes the task title, description, column name, and other metadata.
Combine with wildcard transitions to log every column move to an external service.
Template Variables
Section titled “Template Variables”Prompt templates and auto-commands can use these placeholders:
| Variable | Replaced with |
|---|---|
{{task_xml}} | Task title and description wrapped in an XML block. This is the default spawn-prompt template ({{task_xml}}{{attachments}}); see What the Agent Is Told for the rendered form |
{{title}} | Task title |
{{description}} | Task description |
{{taskId}} | Task UUID |
{{worktreePath}} | Git worktree directory path |
{{branchName}} | Git branch name |
{{baseBranch}} | Base branch the worktree was created from |
{{prUrl}} | URL of the linked pull request (empty until a PR is linked) |
{{prNumber}} | Number of the linked pull request (empty until a PR is linked) |
{{attachments}} | Attached file paths, one per line, appended after the task text; empty when the task has no attachments |
{{port}} | The lowest dev-server port this task has reserved (a task can hold up to 10; see kangentic_reserve_dev_ports). Usually empty: a task holds a port only once its agent has asked for one |
Example custom prompt template, replacing the default {{task_xml}}{{attachments}} on a Spawn Agent action:
{{task_xml}}{{attachments}}
Work in {{worktreePath}} on branch {{branchName}}.Concurrency & Queue Management
Section titled “Concurrency & Queue Management”Kangentic runs multiple agents in parallel, each as a separate CLI process (any of the fourteen supported agents). The agent.maxConcurrentSessions setting (default: 8) caps how many sessions can run at once across all agents. When the limit is reached, new sessions enter a FIFO queue.
How Queuing Works
Section titled “How Queuing Works”- You drag a task to an active column.
- If a session slot is available, the agent starts immediately.
- If all slots are full, the task enters the queue and its card shows a “Queued” label.
- When a running session exits or is suspended, the next queued task promotes automatically.
- Queue promotion is reentrancy-safe - if a promotion triggers another session exit, the queue processes correctly without race conditions.
Overflow Behavior
Section titled “Overflow Behavior”The agent.queueOverflow setting controls what happens when the limit is reached:
| Mode | Behavior |
|---|---|
queue (default) | Tasks wait in a FIFO queue until a slot opens |
reject | The move is rejected - the task stays in its current column |
Tuning Concurrency
Section titled “Tuning Concurrency”- Lower the limit if your machine runs out of memory or CPU with many agents. Each agent process uses significant resources.
- Raise the limit if you have a powerful machine and want more agents running simultaneously.
- The limit is global, not per-project. If you have 3 projects each running agents, they share the same pool.
Configure both settings in Settings under the Behavior tab, or in the config file - see Configuration Reference.
Adding Custom Columns
Section titled “Adding Custom Columns”Click the + button at the end of your column row to add a new column. Then configure it:
- Set a name and optional icon and color
- Choose a permission mode if you want to override the default
- Set a Message to agent if tasks arriving here should receive a prompt
- Toggle auto-spawn off if this column shouldn’t run agents
Flipping auto-spawn applies live, with no card move: tasks already sitting in the column spawn agents when you switch it on and suspend when you switch it off.
Columns can be reordered by dragging their headers and deleted when empty. A whole board’s per-column agent, model, and effort settings can also be saved as a named ladder - see Board Profiles.
Wildcard Transitions
Section titled “Wildcard Transitions”You can use a wildcard (*) as the source in a transition rule to match any column. This is useful for creating catch-all behaviors - for example, a wildcard transition pointing to a “Logging” webhook ensures every column move triggers a log entry.
Next steps
Section titled “Next steps”Next: Board Configuration - persist your columns and transitions to kangentic.json.
See also:
- Settings - per-column overrides and permission modes
- Configuration Reference - the full JSON schema
Kangentic is free and open source. A star helps other people find it.
Star on GitHub