polyphony starts from a repository-owned WORKFLOW.md file, but the CLI first loads
~/.config/polyphony/config.toml, then merges the repo workflow, then applies optional
repo-local overrides from .polyphony/config.toml. WORKFLOW.md contains YAML front matter
followed by the worker prompt template.
If WORKFLOW.md is missing, the CLI offers to create a starter file in TUI mode and writes it
automatically in --no-tui mode.
Copyable full-file references live under templates/ and
templates/examples/.
Merge order is:
- built-in defaults
~/.config/polyphony/config.tomlWORKFLOW.mdfront matter.polyphony/config.tomlPOLYPHONY__...environment variables
Treat ~/.config/polyphony/config.toml as user-local shared state, for example credentials,
reusable agent profiles, shared tracker credential profiles, and personal defaults. Treat WORKFLOW.md as the shared repo-owned
workflow policy and prompt. Use .polyphony/config.toml for local repository wiring such as
tracker.profile, tracker.repository, tracker.project_slug, workspace.source_repo_path, and workspace.clone_url
when you do not want to edit the checked-in workflow.
The current workspace configuration covers:
tracker: tracker kind, repository or project identifiers, API settings, and state mappingpolling: tracker polling interval, default60000ms (60 seconds)workspace: root path, checkout strategy, reuse behavior, and transient cleanup pathshooks: optional shell hooks around workspace lifecycle events, with captured stdout/stderr logged in truncated formtools: optional built-in LLM tool allow/deny policy, with per-agent overridesagent: global concurrency, turn, and retry limitscodex: optional single-agent shorthand for one Codex app-server profileagents: named agent profiles and routing rulesautomation: optional post-run git and PR handoff settingsfeedback: outbound notification sink configurationpipeline: multi-stage pipeline orchestration settingsserver: optional server settings
- Start from
templates/WORKFLOW.mdfor the default generatedWORKFLOW.md. - Use
templates/examples/WORKFLOW.multi-agent.mdfor a full multi-agent workflow example.
For a simple single-agent workflow, codex can stand in for a one-profile agents section:
- Use
templates/examples/WORKFLOW.codex-shorthand.mdas a full-file example.
That shorthand is normalized into a default codex agent internally. The legacy top-level
provider block is still accepted as a deprecated alias for the same single-agent mode.
The agents section supports:
default: fallback profile nameby_state: profile overrides keyed by issue stateby_label: profile overrides keyed by issue labelprofiles: named transport definitions
When profiles is empty, Polyphony stays in tracker-only mode: it polls and displays issues, but
does not dispatch work to an agent yet. That is useful when the repo-local workflow is configured
to read GitHub or Linear issues before any agent profile is wired in.
Full copyable files for the config layers are:
templates/config.tomltemplates/repo-config.tomltemplates/examples/config.multi-provider.tomltemplates/examples/repo-config.github.tomltemplates/examples/repo-config.linear.toml
Shared tracker credentials can be defined in ~/.config/polyphony/config.toml under
trackers.profiles.<name>, then selected per repo with tracker.profile = "<name>".
Current transport styles in the codebase are:
app_serverlocal_cliopenai_chat
Each agent profile can also control:
model,models, andmodels_commandfor single-model or discovered-model setupsfetch_modelsto enable automatic model discoveryapi_keyforopenai_chatprofiles when they are actually used, while missing keys only disable/modelsdiscovery during startupapproval_policy,thread_sandbox, andturn_sandbox_policyfor app-server-backed agentsturn_timeout_ms,read_timeout_ms, andstall_timeout_msfor agent timing controlsstall_timeout_ms <= 0to disable orchestrator stall detectionagent.continuation_promptas an optional Liquid template for later live turns on the same threadinteraction_modewithone_shotorinteractiveprompt_modewithenv,stdin, ortmux_pasteidle_timeout_msfor interactive local CLI pollingcompletion_sentinelfor explicit interactive completion detectionuse_tmuxandtmux_session_prefixfor local CLI automation under tmuxenvfor provider-specific environment injection
The optional tools section enables a small built-in tool registry that provider runtimes can
advertise to tool-capable models.
Current built-in tools:
workspace_list_filesworkspace_read_fileworkspace_searchissue_updateissue_commentpr_commentlinear_graphqlfor raw Linear GraphQL access using the configured tracker auth
The policy shape is:
tools.enabledtools.allowtools.denytools.by_agent.<name>.allowtools.by_agent.<name>.deny
Example:
tools:
enabled: true
allow:
- workspace_list_files
- workspace_read_file
- workspace_search
- issue_update
- issue_comment
- linear_graphql
by_agent:
reviewer:
allow:
- workspace_read_file
- workspace_search
- pr_comment
- linear_graphqlSee Built-In Tools for the runtime model and design constraints.
workspace.checkout_kind currently supports:
directorylinked_worktreediscrete_clone
That separation matters because workspace lifecycle is independent from tracker and agent logic.
automation currently supports:
enabledto turn on git commit, push, and PR creation after successful runsdraft_pull_requeststo create draft PRs by defaultreview_agentto choose a second-pass reviewer agentcommit_message,pr_title,pr_body, andreview_promptas Liquid templatesgit.remote_nameplus optional author name/email overrides
feedback currently supports:
offeredto limit which sink kinds are enabledtelegram.<name>withbot_tokenandchat_idwebhook.<name>withurland optionalbearer_token
Template fields include the normal issue.* fields plus handoff values such as
base_branch, head_branch, commit_sha, and pull_request_url where
relevant.
Use
templates/examples/WORKFLOW.automation-feedback.md
as a full-file example that wires automation and feedback together.
When pipeline.enabled = true, Polyphony breaks each issue into a sequence of tasks instead
of dispatching a single agent. This creates a run (Run) that tracks overall progress and
individual Task records that execute sequentially.
Set pipeline.planner_agent to the name of an agent profile that will analyze each issue
and write a structured plan:
pipeline:
enabled: true
planner_agent: planner
replan_on_failure: trueThe planner agent receives the issue and writes .polyphony/plan.json to the workspace:
{
"tasks": [
{
"title": "Research existing auth patterns",
"category": "research",
"description": "Investigate current auth middleware and session management",
"agent": "researcher"
},
{
"title": "Implement OAuth2 flow",
"category": "coding",
"description": "Add OAuth2 login, callback, and token refresh endpoints"
},
{
"title": "Write integration tests",
"category": "testing",
"description": "Cover login, token refresh, and error scenarios"
}
]
}Valid categories are research, coding, testing, documentation, and review.
The agent field is optional — when omitted, the orchestrator falls back to the
stage config or the default agent.
When replan_on_failure is true and a task fails, the planner agent is re-invoked
with error context to produce a revised plan.
Define fixed stages that apply to every issue:
pipeline:
enabled: true
stages:
- category: research
agent: researcher
max_turns: 4
- category: coding
agent: coder
max_turns: 10
- category: review
agent: reviewer
max_turns: 4Each stage becomes a task. Tasks execute in the order listed.
Pipeline tasks share the same workspace directory and communicate through files:
| Artifact | Purpose |
|---|---|
.polyphony/plan.json |
Structured plan from the planner agent |
.polyphony/workpad.md |
Free-form notes any agent can read and extend |
.polyphony/review.md |
Review output from the review pass |
Each task's prompt automatically includes:
- The original issue data
- The full plan (when a planner was used)
- Summaries of completed tasks
- The current task title and description
| Field | Type | Default | Description |
|---|---|---|---|
pipeline.enabled |
bool | false |
Enable pipeline dispatch |
pipeline.planner_agent |
string | — | Agent profile that generates plan.json |
pipeline.planner_prompt |
string | — | Custom Liquid template for the planner (uses built-in default) |
pipeline.stages |
array | [] |
Static stage definitions (used when no planner) |
pipeline.replan_on_failure |
bool | false |
Re-run planner if a task fails |
pipeline.validation_agent |
string | — | Agent that validates after all tasks |
Stage fields:
| Field | Type | Description |
|---|---|---|
stages[].category |
string | Task category: research, coding, testing, documentation, review |
stages[].agent |
string | Agent profile name (falls back to agents.default) |
stages[].prompt |
string | Custom Liquid prompt template for this stage |
stages[].max_turns |
int | Override agent.max_turns for this stage |
templates/examples/WORKFLOW.pipeline-planner.md— planner-driven pipeline with research, coding, and review agentstemplates/examples/WORKFLOW.pipeline-static.md— static three-stage pipeline without a planner
The Markdown body of WORKFLOW.md is treated as a template. At runtime, the workflow crate renders
prompt text with issue and execution context before handing control to the selected agent.
The template has access to issue data and the current attempt value. attempt is nil on the
first run, and an integer on retry or continuation runs. Turn rendering also exposes
turn_number, max_turns, and is_continuation, which are especially useful for
agent.continuation_prompt. Unknown variables and unknown filters fail rendering instead of
silently producing empty output. The parsed workflow is then normalized into AgentDefinition
values that the rest of the runtime consumes.