Quick Start
In this tutorial, we will run Sortie — an autonomous coding agent orchestrator — end-to-end on your machine. By the end, you will have watched Sortie poll for issues, spin up workspaces, run mock agent sessions, and record the results — all without touching Jira or any external API.
Prerequisites
- Sortie installed and on your
PATH(installation guide) - This tutorial uses a mock agent, so no real coding agent is needed yet. When you move to a real agent like Claude Code, first verify it handles issues well in a manual terminal session — Sortie automates the scheduling, not the quality of the agent’s output.
Confirm Sortie is ready:
sortie --versionYou should see output like:
sortie 1.19.0 (commit: 0651d1f, built: 2026-07-11, go1.26.1, linux/amd64)Set up a project directory
Create a fresh directory for this tutorial:
mkdir sortie-demo && cd sortie-demoWe will create two files here: an issues file and a workflow file.
Create an issues file
Create a file called issues.json with two sample issues:
[
{
"id": "1",
"identifier": "DEMO-1",
"title": "Add input validation to signup form",
"description": "The signup form accepts empty email addresses. Add validation before submission.",
"state": "To Do",
"priority": 1
},
{
"id": "2",
"identifier": "DEMO-2",
"title": "Fix off-by-one error in pagination",
"description": "Page 2 repeats the last item from page 1. The offset calculation is wrong.",
"state": "To Do",
"priority": 2
}
]This is the same shape Sortie gets from a real tracker like Jira. The file adapter reads it directly, so we can skip all API setup for now.
Create a workflow file
Create WORKFLOW.md in the same directory:
---
tracker:
kind: file
project: DEMO
active_states:
- "To Do"
handoff_state: "Done"
file:
path: ./issues.json
agent:
kind: mock
max_turns: 2
polling:
interval_ms: 5000
---
Fix the following issue.
**{{ .issue.identifier }}**: {{ .issue.title }}
{{ .issue.description }}This single file drives everything Sortie does. The YAML front matter between
the --- fences configures the tracker, agent, and polling interval. The
Markdown body below is a prompt template — Sortie renders it once per issue
and sends it to the agent.
Notice a few things:
tracker.kind: filetells Sortie to read issues from a local JSON file instead of calling an API.agent.kind: mockuses a built-in mock agent that simulates work without changing any files.max_turns: 2limits each agent session to two turns.{{ .issue.identifier }}and friends are Go template variables that Sortie fills in with data from each issue.
Run Sortie
Start Sortie and point it at the workflow file:
sortie ./WORKFLOW.mdYou should see output similar to:
level=INFO msg="sortie starting" version=1.19.0 workflow_path=/home/you/sortie-demo/WORKFLOW.md
level=INFO msg="database path resolved" db_path=/home/you/sortie-demo/.sortie.db
level=INFO msg="sortie started"
level=INFO msg="tick completed" candidates=2 dispatched=2 running=2 retrying=0
level=INFO msg="workspace prepared" issue_id=1 issue_identifier=DEMO-1 workspace=…/DEMO-1
level=INFO msg="agent session started" issue_id=1 issue_identifier=DEMO-1 session_id=mock-session-001
level=INFO msg="turn started" issue_id=1 issue_identifier=DEMO-1 turn_number=1 max_turns=2
level=INFO msg="turn completed" issue_id=1 issue_identifier=DEMO-1 turn_number=1 max_turns=2
level=INFO msg="turn started" issue_id=1 issue_identifier=DEMO-1 turn_number=2 max_turns=2
level=INFO msg="turn completed" issue_id=1 issue_identifier=DEMO-1 turn_number=2 max_turns=2
level=INFO msg="worker exiting" issue_id=1 issue_identifier=DEMO-1 exit_kind=normal turns_completed=2
level=INFO msg="worker exiting" issue_id=2 issue_identifier=DEMO-2 exit_kind=normal turns_completed=2
level=INFO msg="handoff transition succeeded, releasing claim" issue_id=1 issue_identifier=DEMO-1 handoff_state=Done
level=INFO msg="handoff transition succeeded, releasing claim" issue_id=2 issue_identifier=DEMO-2 handoff_state=Done
level=INFO msg="tick completed" candidates=0 dispatched=0 running=0 retrying=0Let’s walk through what happened:
- Sortie loaded
WORKFLOW.mdand readissues.json. It found two issues in the “To Do” state —DEMO-1andDEMO-2. - For each issue, it created a workspace directory and started a mock agent session.
- The mock agent ran two turns per issue (the
max_turnswe set). - After both turns completed, Sortie transitioned each issue to “Done” (the
handoff_statefrom our config). - On the next poll cycle, Sortie found zero candidates and went idle.
Notice the second tick completed line shows candidates=0 — there is
nothing left to process. Press Ctrl+C to stop Sortie.
Check the results
Sortie persists all run history in a local SQLite database. Look at your project directory:
ls -aYou should see:
.sortie.db issues.json WORKFLOW.mdThe .sortie.db file contains session metadata, turn history, and metrics for
every run.
Open issues.json again and notice that it is unchanged. The file tracker
holds each transition in memory for the life of the process rather than
rewriting the fixture, so both issues still read "state": "To Do" on disk and
the next sortie ./WORKFLOW.md runs the same demo again.
What we built
We ran the full Sortie lifecycle without any external services:
- Poll — Sortie watched
issues.jsonfor issues in the “To Do” state. - Dispatch — Each matching issue got its own workspace and agent session.
- Execute — The mock agent ran two turns per issue.
- Handoff — Sortie transitioned completed issues to “Done.”
- Persist — Run results were recorded in
.sortie.db.
The mock agent doesn’t modify code, but the lifecycle is identical to a real
agent session. In production, you would swap mock for claude-code and
file for jira or github — the orchestration works the same way. The quality of the
agent’s output depends on your prompt and agent configuration, not on Sortie.
Next steps
- Connect a Jira tracker to pull real issues
- Run with Claude Code as the agent for automated code changes
- Run with Codex as the agent for automated code changes with the OpenAI stack
- Workflow file reference for all configuration options, template variables, and hook lifecycle
- Troubleshoot common failures if something goes wrong
Was this page helpful?