@wichayutdew/pi-workflows 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -983
- package/dist/index.js +995 -756
- package/examples/starter-kit/mr-review.workflow.yaml +3 -1
- package/examples/starter-kit/steps/mr-review/publish.md +9 -2
- package/examples/starter-kit/steps/mr-review/verify.md +16 -5
- package/package.json +1 -1
- package/schemas/workflow.schema.json +1 -0
- package/src/command-names.ts +1 -0
- package/src/commands.ts +14 -0
- package/src/config/validation/prompt.ts +2 -0
- package/src/engine/create-run.ts +3 -0
- package/src/engine/run-advance.ts +16 -0
- package/src/engine/run-lifecycle.ts +69 -0
- package/src/engine/run-validation.ts +16 -0
- package/src/engine/state-types.ts +7 -0
- package/src/engine/transitions.ts +1 -0
- package/src/harness/action-context.ts +6 -0
- package/src/harness/core-actions.ts +2 -0
- package/src/harness/dependencies.ts +4 -0
- package/src/harness/lifecycle-actions.ts +14 -1
- package/src/harness/session-persistence.ts +66 -0
- package/src/harness/start-actions.ts +188 -1
- package/src/harness.ts +20 -0
- package/src/prompt/step-sections.ts +14 -0
- package/src/prompt/step-task.ts +3 -0
- package/src/prompt/template.ts +2 -0
- package/src/workflow-status/render-summary.ts +3 -0
package/README.md
CHANGED
|
@@ -1,994 +1,30 @@
|
|
|
1
|
-
# Pi Workflows
|
|
2
|
-
|
|
3
|
-
**Turn repeatable agent work into declarative, pauseable workflows that cannot
|
|
4
|
-
silently loop forever.** Put the steps, tools, prompts, approvals, and outcomes
|
|
5
|
-
in YAML; Pi Workflows supplies durable checkpoints, finite automatic execution,
|
|
6
|
-
and a live status view without learning your language, framework, or process.
|
|
7
|
-
|
|
8
1
|
[](https://codecov.io/gh/wichayutdew/pi-workflows)
|
|
9
2
|
|
|
10
|
-
|
|
11
|
-
pi install npm:@wichayutdew/pi-workflows
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
- Compose main-agent and isolated subagent steps from one strict YAML contract.
|
|
15
|
-
- Pause for built-in or Plannotator review, then resume the same checkpoint.
|
|
16
|
-
- Reject dead-end graphs up front and pause bounded cycles at `maxStepVisits`.
|
|
17
|
-
- Keep every domain decision in your workflow files—not in the harness.
|
|
18
|
-
|
|
19
|
-
## Overview
|
|
20
|
-
|
|
21
|
-
Pi Workflows keeps orchestration code generic and moves workflow behavior into
|
|
22
|
-
small YAML configuration and prompt files. Each workflow defines its
|
|
23
|
-
own steps, transitions, execution mode, tool access, MCP access, Bash policy,
|
|
24
|
-
extensions, skills, dependency checks, and optional human-review gate.
|
|
25
|
-
|
|
26
|
-
The harness owns state transitions. A step runs in the main Pi agent by default,
|
|
27
|
-
or in a separate [pi-subagents](https://github.com/nicobailon/pi-subagents)
|
|
28
|
-
child when it declares `subagent`. Main-agent steps advance through
|
|
29
|
-
`workflow_complete_step`; delegated steps return the same validated contract
|
|
30
|
-
through pi-subagents' correlated `structured_output`.
|
|
31
|
-
|
|
32
|
-
## Install
|
|
33
|
-
|
|
34
|
-
Install Pi Workflows from npm:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
pi install npm:@wichayutdew/pi-workflows
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
For local development, install it from the repository instead:
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
pi install /absolute/path/to/pi-workflows
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
For the strongest context isolation and browser-based review experience, use it
|
|
47
|
-
with both [pi-subagents](https://github.com/nicobailon/pi-subagents) and
|
|
48
|
-
[Plannotator](https://github.com/backnotprop/plannotator):
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
pi install npm:pi-subagents
|
|
52
|
-
pi install npm:@plannotator/pi-extension
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Neither integration is required, but both are highly recommended together for
|
|
56
|
-
the best isolation and review experience. Delegated steps require
|
|
57
|
-
pi-subagents `0.36.0` or newer. Run `/subagents-doctor` if an explicitly
|
|
58
|
-
delegated step cannot start.
|
|
59
|
-
|
|
60
|
-
Pi loads `src/index.ts` through the package manifest. Restart Pi or run `/reload` after changing extension source.
|
|
61
|
-
|
|
62
|
-
## Quick start: bootstrap four practical workflows
|
|
63
|
-
|
|
64
|
-
The checked-in [`examples/starter-kit`](./examples/starter-kit) is a portable,
|
|
65
|
-
user-owned starting point for:
|
|
66
|
-
|
|
67
|
-
| Command | Included flow |
|
|
68
|
-
| ------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
69
|
-
| `/work` | Prepare or reuse one dedicated Git worktree, plan, approve, implement, and verify local work. |
|
|
70
|
-
| `/ticket` | Prepare or reuse one dedicated Git worktree, read a ticket, plan, approve, implement, and verify. |
|
|
71
|
-
| `/mr-review` | Fetch a hosted review, produce a child review, approve it, publish it, and verify the remote effect. |
|
|
72
|
-
| `/mr-comment` | Fetch review comments, plan and approve fixes, edit only the current branch/worktree, verify, push, reply. |
|
|
73
|
-
|
|
74
|
-
The starter YAML explicitly selects Pi Subagents' standard role profiles:
|
|
75
|
-
`scout` for evidence gathering, `planner` for implementation plans, `worker`
|
|
76
|
-
for mutations and publication, and `reviewer` for independent review and
|
|
77
|
-
verification. Change those `subagent.agent` values when your own Pi Subagents
|
|
78
|
-
configuration uses different profiles. The generic `pi-workflows.step` profile
|
|
79
|
-
remains available for user-authored `subagent: {}` steps, but the starter kit
|
|
80
|
-
does not rely on it.
|
|
81
|
-
|
|
82
|
-
Install the integrations required by these four examples:
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
pi install npm:pi-subagents
|
|
86
|
-
pi install npm:@plannotator/pi-extension
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
Configure a Pi MCP proxy for the `atlassian`, `gitlab`, and/or `github` server
|
|
90
|
-
IDs when you want that access route. The MR examples try a matching MCP server
|
|
91
|
-
first but can fall back to the repository/host CLIs or cURL named in their
|
|
92
|
-
YAML; ensure at least one route is authenticated and available. The ticket
|
|
93
|
-
example requires Atlassian MCP by default. MCP server names, authentication,
|
|
94
|
-
tool availability, Git hosting, and repository commands are environment
|
|
95
|
-
choices, so adapt the selectors, `requires`, and Bash rules instead of
|
|
96
|
-
expecting the extension to infer them.
|
|
97
|
-
|
|
98
|
-
Copy the starter files into the user workflow directory:
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
mkdir -p ~/.pi/agent/workflows
|
|
102
|
-
cp examples/starter-kit/*.workflow.yaml ~/.pi/agent/workflows/
|
|
103
|
-
cp -R examples/starter-kit/steps ~/.pi/agent/workflows/
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
If files with those names already exist, review and merge them instead of
|
|
107
|
-
overwriting your working configuration. Then customize:
|
|
108
|
-
|
|
109
|
-
1. In `work.workflow.yaml` and `ticket.workflow.yaml`, set each
|
|
110
|
-
`workspace.allowedRoots` to relative directories where the preparation
|
|
111
|
-
prompt may create or reuse a worktree.
|
|
112
|
-
2. Replace or narrow the `atlassian`, `gitlab`, and `github` MCP selectors to
|
|
113
|
-
match your configured adapter. Remove an unused host consistently from the
|
|
114
|
-
relevant `permissions.mcp` blocks and prompts.
|
|
115
|
-
3. Review every Bash mode and executable. The starter implementation and
|
|
116
|
-
verification steps are deliberately language-neutral and therefore
|
|
117
|
-
unrestricted; replace them with repository-specific allow lists when
|
|
118
|
-
possible. Command syntax—including package-manager argument order—belongs
|
|
119
|
-
in your prompt and repository context.
|
|
120
|
-
4. Edit the prompt files under `steps/` to define your artifact format,
|
|
121
|
-
acceptance criteria, publication policy, and organization-specific rules.
|
|
122
|
-
Pi Workflows treats all of that content as opaque domain configuration.
|
|
123
|
-
|
|
124
|
-
Reload and diagnose every graph before the first run:
|
|
125
|
-
|
|
126
|
-
```text
|
|
127
|
-
/reload
|
|
128
|
-
/workflow-reload
|
|
129
|
-
/workflow-doctor work
|
|
130
|
-
/workflow-doctor ticket
|
|
131
|
-
/workflow-doctor mr-review
|
|
132
|
-
/workflow-doctor mr-comment
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
Start them from the repository checkout that should supply the initial
|
|
136
|
-
workspace:
|
|
137
|
-
|
|
138
|
-
```text
|
|
139
|
-
/work update the navigation
|
|
140
|
-
/ticket PROJ-123 retry failed requests
|
|
141
|
-
/mr-review https://gitlab.example.com/group/project/-/merge_requests/42
|
|
142
|
-
/mr-comment https://github.com/example/project/pull/42
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
`/work` and `/ticket` bind the exact worktree returned by their user-authored
|
|
146
|
-
preparation prompt. `/mr-comment` intentionally has no workspace-binding step:
|
|
147
|
-
every child stays on the branch and worktree from which the run started.
|
|
148
|
-
Requested changes return only to the gated plan or review step with the user's
|
|
149
|
-
feedback; they never restart workspace preparation or the whole workflow. The
|
|
150
|
-
starter `/work` and `/ticket` planners use a separate `workspace-refresh`
|
|
151
|
-
outcome only for source-ancestry drift. It revisits preparation in the same
|
|
152
|
-
canonical worktree; the prompt may safely rebase its clean run-owned branch but
|
|
153
|
-
can never bind a replacement directory.
|
|
154
|
-
Remote publication prompts first check whether an approved effect already
|
|
155
|
-
exists because the harness cannot guarantee exactly-once external side effects.
|
|
156
|
-
|
|
157
|
-
## Add a workflow
|
|
158
|
-
|
|
159
|
-
User workflows live in one of these formats:
|
|
160
|
-
|
|
161
|
-
```text
|
|
162
|
-
~/.pi/agent/workflows/*.workflow.yaml
|
|
163
|
-
~/.pi/agent/workflows/*.workflow.yml
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
YAML keeps nested steps and permission lists compact. The loader uses the
|
|
167
|
-
strict YAML 1.2 core schema: duplicate keys, merge keys, invalid tags,
|
|
168
|
-
multiple documents, non-1.2 directives, and excessive alias expansion fail
|
|
169
|
-
closed.
|
|
170
|
-
|
|
171
|
-
Set `PI_WORKFLOWS_DIR` to use another directory. For a complete portable
|
|
172
|
-
starting point, copy the four-workflow starter kit above. Every configured
|
|
173
|
-
command is also available as `/workflow-start <workflow-id> [input]`.
|
|
174
|
-
|
|
175
|
-
## Minimal workflow
|
|
176
|
-
|
|
177
|
-
```yaml
|
|
178
|
-
# yaml-language-server: $schema=./schemas/workflow.schema.json
|
|
179
|
-
version: 1
|
|
180
|
-
id: fix
|
|
181
|
-
command: fix
|
|
182
|
-
description: Inspect, implement, and verify a change
|
|
183
|
-
start: inspect
|
|
184
|
-
steps:
|
|
185
|
-
inspect:
|
|
186
|
-
prompt: Inspect {{workflow.input}} without modifying files.
|
|
187
|
-
permissions:
|
|
188
|
-
tools: [read, grep, bash]
|
|
189
|
-
bash:
|
|
190
|
-
mode: allow-list
|
|
191
|
-
allow:
|
|
192
|
-
- executable: git
|
|
193
|
-
argsPrefixes: [[status], [diff]]
|
|
194
|
-
- executable: rg
|
|
195
|
-
requires:
|
|
196
|
-
tools: [read, bash]
|
|
197
|
-
transitions:
|
|
198
|
-
ready: implement
|
|
199
|
-
blocked: $pause
|
|
200
|
-
|
|
201
|
-
implement:
|
|
202
|
-
prompt:
|
|
203
|
-
file: prompts/implement.md
|
|
204
|
-
permissions:
|
|
205
|
-
tools: [read, edit, write, bash]
|
|
206
|
-
bash:
|
|
207
|
-
mode: allow-list
|
|
208
|
-
allow:
|
|
209
|
-
- executable: project-check
|
|
210
|
-
argsPrefix: [test]
|
|
211
|
-
transitions:
|
|
212
|
-
done: $done
|
|
213
|
-
blocked: $pause
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
The loader rejects unknown properties, duplicate identifiers, missing targets,
|
|
217
|
-
unsafe prompt paths, invalid gate contracts, Pi command-name conflicts, and
|
|
218
|
-
project permissions above the user ceiling. Conflicts with commands from other
|
|
219
|
-
loaded extensions or prompt resources are diagnosed before aliases register.
|
|
220
|
-
|
|
221
|
-
## Configuration
|
|
222
|
-
|
|
223
|
-
Top-level fields:
|
|
224
|
-
|
|
225
|
-
| Field | Required | Default | Description |
|
|
226
|
-
| ----------------- | -------- | ------- | ----------------------------------------------------------------------------------------- |
|
|
227
|
-
| `version` | Yes | — | Configuration contract version. Currently `1`. |
|
|
228
|
-
| `id` | Yes | — | Stable workflow identifier. |
|
|
229
|
-
| `command` | Yes | — | Slash command without `/`. |
|
|
230
|
-
| `description` | Yes | — | Command description. |
|
|
231
|
-
| `start` | Yes | — | First step identifier. |
|
|
232
|
-
| `steps` | Yes | — | Step map. Order is controlled by transitions, not file order. |
|
|
233
|
-
| `maxStepVisits` | No | `5` | Loop guard for each step. |
|
|
234
|
-
| `summaryMaxChars` | No | `4000` | Maximum step `summary` length. Gate artifacts use their separate 200,000-character limit. |
|
|
235
|
-
|
|
236
|
-
Each step supports:
|
|
237
|
-
|
|
238
|
-
| Field | Required | Description |
|
|
239
|
-
| ------------- | -------- | ----------------------------------------------------------------------------------------------------- |
|
|
240
|
-
| `title` | No | Human-readable name. Defaults to the step identifier. |
|
|
241
|
-
| `prompt` | Yes | Inline text or `{ "file": "relative/path.md" }`. |
|
|
242
|
-
| `subagent` | No | Opt into isolated delegation and select the Pi Subagents profile and execution budgets. |
|
|
243
|
-
| `permissions` | No | Resources callable during this step. Everything defaults to denied. |
|
|
244
|
-
| `requires` | No | Dependencies that must be detectable before the step starts. |
|
|
245
|
-
| `transitions` | Yes | Exact outcome to next step, `$pause`, or `$done`. |
|
|
246
|
-
| `gate` | No | Built-in prompt or Plannotator human-review gate. |
|
|
247
|
-
| `workspace` | No | Bind one delegated step result as the working directory for all reachable downstream delegated steps. |
|
|
248
|
-
|
|
249
|
-
Supported prompt variables:
|
|
250
|
-
|
|
251
|
-
```text
|
|
252
|
-
{{workflow.input}}
|
|
253
|
-
{{workflow.id}}
|
|
254
|
-
{{run.id}}
|
|
255
|
-
{{step.id}}
|
|
256
|
-
{{step.title}}
|
|
257
|
-
{{last.summary}}
|
|
258
|
-
{{reviewed.artifact}}
|
|
259
|
-
{{reviewed.feedback}}
|
|
260
|
-
{{gate.artifact}}
|
|
261
|
-
{{gate.feedback}}
|
|
262
|
-
{{resume.input}}
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
Unknown variables fail configuration loading.
|
|
266
|
-
|
|
267
|
-
`{{last.summary}}` normally contains the previous completed step's handoff.
|
|
268
|
-
During a step-requested `$pause` or same-step human gate revision, it contains
|
|
269
|
-
both the preserved incoming handoff and latest current-step summary. Gate
|
|
270
|
-
artifacts and summaries stay separate: prompts opt into an opaque approved
|
|
271
|
-
artifact through `{{reviewed.artifact}}` or the latest rejected artifact
|
|
272
|
-
through `{{gate.artifact}}`.
|
|
273
|
-
`{{resume.input}}` contains guidance supplied to the current attempt through
|
|
274
|
-
`/workflow-resume [guidance]`. If a prompt omits that variable, the harness
|
|
275
|
-
adds the guidance in a clearly delimited standard section, so every workflow
|
|
276
|
-
can still use it. Standard-section guidance is an authoritative task-level
|
|
277
|
-
amendment for that retry, but it cannot change the workflow graph or bypass
|
|
278
|
-
YAML-enforced resource and workspace boundaries. The value is replaced on each
|
|
279
|
-
explicit resume and cleared after the step returns an outcome.
|
|
280
|
-
|
|
281
|
-
### Per-step subagents
|
|
282
|
-
|
|
283
|
-
Omit `subagent` to execute the step entirely in the main Pi agent. This is the
|
|
284
|
-
portable default and requires no other extension:
|
|
285
|
-
|
|
286
|
-
```yaml
|
|
287
|
-
steps:
|
|
288
|
-
inspect:
|
|
289
|
-
prompt: Inspect the request.
|
|
290
|
-
permissions:
|
|
291
|
-
tools: [read]
|
|
292
|
-
transitions:
|
|
293
|
-
done: $done
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
Add `subagent: {}` to delegate through the public
|
|
297
|
-
`pi-subagents/delegation` v1 API with safe defaults:
|
|
298
|
-
|
|
299
|
-
```yaml
|
|
300
|
-
steps:
|
|
301
|
-
inspect:
|
|
302
|
-
subagent: {}
|
|
303
|
-
prompt: Inspect the request.
|
|
304
|
-
transitions:
|
|
305
|
-
done: $done
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
The expanded defaults are `agent: pi-workflows.step`, `context: fresh`,
|
|
309
|
-
`timeoutMs: 900000`, `artifacts: false`, and `retryToolFailures: false`. The
|
|
310
|
-
`agent` value is the actual Pi Subagents profile launched for that step.
|
|
311
|
-
`fresh` is the only supported workflow-step context: each child receives the
|
|
312
|
-
original workflow input and the previous step's compact handoff, never the
|
|
313
|
-
parent or a sibling transcript.
|
|
314
|
-
|
|
315
|
-
The run captures Pi's current working directory when it starts. Without a
|
|
316
|
-
`workspace` binding, every delegated visit—including cycles, retries, and
|
|
317
|
-
resumed steps—uses that directory.
|
|
318
|
-
|
|
319
|
-
One delegated, non-gated step may bind a different directory through structured
|
|
320
|
-
result data:
|
|
321
|
-
|
|
322
|
-
```yaml
|
|
323
|
-
workspace:
|
|
324
|
-
bindOn: [ready]
|
|
325
|
-
allowedRoots: ['..']
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
On a binding outcome, the result must include
|
|
329
|
-
`workspace: { cwd: "/absolute/directory" }`. The harness resolves its real path,
|
|
330
|
-
requires an existing directory under one configured root relative to the
|
|
331
|
-
run-start directory, persists that canonical identity, and passes it to every
|
|
332
|
-
reachable downstream child, revisit, recovery attempt, and resume. If the sole
|
|
333
|
-
binding step is revisited, it may re-affirm the same canonical directory; a
|
|
334
|
-
different directory is rejected. Other outcomes must omit `workspace`. All
|
|
335
|
-
reachable nonterminal steps after a binding must be delegated because the main
|
|
336
|
-
Pi process cannot change its working directory.
|
|
337
|
-
|
|
338
|
-
The workflow prompt owns how the directory is prepared and what it represents.
|
|
339
|
-
The harness does not know Git, worktrees, languages, frameworks, or command
|
|
340
|
-
syntax, and it never derives a directory from summaries or gate artifacts. The
|
|
341
|
-
starter kit's guarded rebase policy is therefore prompt-owned domain behavior,
|
|
342
|
-
not extension behavior. A legacy checkpoint without a captured directory fails
|
|
343
|
-
closed before delegation; abort it and start a new run.
|
|
344
|
-
|
|
345
|
-
Use a profile name directly when only the child profile changes:
|
|
346
|
-
|
|
347
|
-
```yaml
|
|
348
|
-
steps:
|
|
349
|
-
inspect:
|
|
350
|
-
subagent: scout
|
|
351
|
-
prompt: Inspect the request.
|
|
352
|
-
transitions:
|
|
353
|
-
done: $done
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
This name-only form inherits the same execution defaults and launches the
|
|
357
|
-
configured Pi Subagents `scout` profile. Its system prompt and profile defaults
|
|
358
|
-
provide the specialty, while the workflow prompt supplies the exact step
|
|
359
|
-
contract. Use the object form when the step also needs a model, timeout, budget,
|
|
360
|
-
or artifact override:
|
|
361
|
-
|
|
362
|
-
```yaml
|
|
363
|
-
subagent:
|
|
364
|
-
agent: reviewer
|
|
365
|
-
context: fresh
|
|
366
|
-
timeoutMs: 600000
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
Pi Workflows passes `subagent.agent` directly to Pi Subagents. Built-in profiles
|
|
370
|
-
such as `scout`, `planner`, `worker`, and `reviewer` therefore retain their own
|
|
371
|
-
system prompts, models, and specialty defaults. The bundled
|
|
372
|
-
`pi-workflows.step` profile remains the default general-purpose profile when
|
|
373
|
-
`agent` is omitted.
|
|
374
|
-
|
|
375
|
-
Every delegated request sets `context: fresh`, `output: false`, an
|
|
376
|
-
`outputSchema` for the workflow result, and `agentContract: { version: 1 }`.
|
|
377
|
-
Pi Subagents supplies `structured_output`, validates the schema, and emits the
|
|
378
|
-
single correlated terminal response. Pi Workflows' child policy independently
|
|
379
|
-
validates the declared outcome and compact handoff before the parent advances.
|
|
380
|
-
Request-level model, timeout, turn-budget, tool-budget, skills, and artifact
|
|
381
|
-
options are still forwarded. Use `/subagents-models <agent>` to inspect the
|
|
382
|
-
selected profile and `/subagents-doctor` to diagnose discovery or loading
|
|
383
|
-
problems. Workflow project trust and permission ceilings remain separately
|
|
384
|
-
configured in `~/.pi/agent/workflows/settings.yaml`.
|
|
385
|
-
|
|
386
|
-
Supported fields:
|
|
387
|
-
|
|
388
|
-
| Field | Default | Description |
|
|
389
|
-
| ------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
390
|
-
| `agent` | `pi-workflows.step` | Actual Pi Subagents profile, such as `scout`, `planner`, `worker`, or `reviewer`. |
|
|
391
|
-
| `context` | `fresh` | Always isolated; parent and sibling transcripts are never inherited. |
|
|
392
|
-
| `model` | Profile/default model | Optional pi-subagents model override for the selected profile. |
|
|
393
|
-
| `timeoutMs` | `900000` | Child deadline, from 1 second through 24 hours. |
|
|
394
|
-
| `turnBudget` | pi-subagents default | `{ "maxTurns": n, "graceTurns": n }`. |
|
|
395
|
-
| `toolBudget` | pi-subagents default | `{ "soft": n, "hard": n, "block": "*" }`; `block` may instead be a tool-name array. |
|
|
396
|
-
| `artifacts` | `false` | Ask pi-subagents to retain its normal run artifacts. |
|
|
397
|
-
| `retryToolFailures` | `false` | Authorize the bounded automatic recovery sequence in allow-list or unrestricted Bash mode; every failed attempt still needs a complete audit proving that its actual calls were mutation-safe. |
|
|
398
|
-
|
|
399
|
-
Pi Workflows installs an inert listener in every Pi Subagents child and
|
|
400
|
-
activates policy only after a valid, single-use workflow capability arrives, so
|
|
401
|
-
ordinary subagent runs remain unchanged. Delegated completion uses the
|
|
402
|
-
`structured_output` tool provided by Pi Subagents; `workflow_complete_step`
|
|
403
|
-
remains the completion tool only for main-agent steps.
|
|
404
|
-
|
|
405
|
-
After capability verification, Pi Workflows resolves the step permissions
|
|
406
|
-
against every tool registered in the child and activates only that exact set,
|
|
407
|
-
plus the upstream structured completion tool. The selected profile's ordinary
|
|
408
|
-
active-tool allow-list is not a second workflow policy. Profile extension
|
|
409
|
-
loading still controls which extension providers exist in the child; a workflow
|
|
410
|
-
cannot activate a tool whose provider was not loaded.
|
|
411
|
-
|
|
412
|
-
Workflow `permissions.skills` is sent as Pi Subagents' request-level skill
|
|
413
|
-
selection, so it replaces the selected profile's normal skill list for that
|
|
414
|
-
step; an empty list disables injected skills. `output: false` prevents a
|
|
415
|
-
profile-default output file, while omitting acceptance under agent contract v1
|
|
416
|
-
avoids a second acceptance gate. The schema, harness, declared outcomes, and
|
|
417
|
-
optional human review gate own correlated completion.
|
|
418
|
-
|
|
419
|
-
At runtime:
|
|
420
|
-
|
|
421
|
-
1. The harness creates a correlated child policy and result channel.
|
|
422
|
-
2. pi-subagents starts one foreground child using the step's configured agent profile.
|
|
423
|
-
3. The child runtime activates the workflow-permitted registered tools and validates `structured_output`.
|
|
424
|
-
4. The parent waits for the correlated terminal response, applies the transition, and launches the next fresh-context step.
|
|
425
|
-
|
|
426
|
-
Main-agent mode uses the same per-step tool, MCP, Bash, extension-tool, and
|
|
427
|
-
completion enforcement, but it cannot unload globally visible skills or
|
|
428
|
-
extension event handlers from the parent process. Use pi-subagents when fresh
|
|
429
|
-
context, skill isolation, process separation, model selection, or turn/tool
|
|
430
|
-
budgets matter.
|
|
431
|
-
|
|
432
|
-
### Per-step permissions
|
|
433
|
-
|
|
434
|
-
`tools` contains exact Pi tool names available to the active step.
|
|
435
|
-
|
|
436
|
-
`mcp` contains `server` or `server/tool` selectors for the generic `mcp` proxy:
|
|
437
|
-
|
|
438
|
-
```yaml
|
|
439
|
-
mcp:
|
|
440
|
-
- gitlab/get_merge_request
|
|
441
|
-
- gitlab/list_merge_request_discussions
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
The harness requires an explicit `server` and `tool` on every proxy call. Proxy search, discovery, connection, and authentication modes are blocked while a workflow step is running.
|
|
445
|
-
|
|
446
|
-
The generic `mcp` proxy is the portable choice for workflow steps. The bundled
|
|
447
|
-
runtime may also expose direct MCP tools through Pi Subagents settings; Pi
|
|
448
|
-
Workflows still requires each direct runtime name in `tools`.
|
|
449
|
-
|
|
450
|
-
`extensions` contains case-insensitive fragments matched against tool source metadata. Tools registered by matching extensions become visible and callable:
|
|
451
|
-
|
|
452
|
-
```yaml
|
|
453
|
-
extensions: [some-extension]
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
The MCP adapter is excluded from this broad extension rule. Grant proxy access through `mcp`, and grant a direct MCP tool only by its exact name in `tools`.
|
|
457
|
-
|
|
458
|
-
For delegated steps, `skills` states which skills pi-subagents injects into the
|
|
459
|
-
child. In main-agent mode it documents and preflights the intended skills, but
|
|
460
|
-
Pi cannot hide other globally loaded skill text. Put mandatory resources under
|
|
461
|
-
`requires`:
|
|
462
|
-
|
|
463
|
-
```yaml
|
|
464
|
-
permissions:
|
|
465
|
-
skills: [superpowers:test-driven-development]
|
|
466
|
-
extensions: [plannotator]
|
|
467
|
-
requires:
|
|
468
|
-
skills: [superpowers:test-driven-development]
|
|
469
|
-
extensions: [plannotator]
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
The harness preflights required resources, passes selected skills to
|
|
473
|
-
pi-subagents when delegation is enabled, restricts active tools, and authorizes
|
|
474
|
-
every model tool call. Loaded extension event handlers still execute in their
|
|
475
|
-
process; the tool policy does not unload extension code.
|
|
476
|
-
|
|
477
|
-
### Bash modes
|
|
478
|
-
|
|
479
|
-
| Mode | Behavior |
|
|
480
|
-
| -------------- | ------------------------------------------------------------------- |
|
|
481
|
-
| `deny` | Blocks Bash. This is the default. |
|
|
482
|
-
| `allow-list` | Allows one executable plus user-configured argument prefixes. |
|
|
483
|
-
| `unrestricted` | Allows any Bash command. Use only in trusted, user-owned workflows. |
|
|
484
|
-
|
|
485
|
-
Allow-list mode rejects shell operators, substitutions, expansions, wrapper
|
|
486
|
-
shells, and environment assignments before matching the declarative rule.
|
|
487
|
-
|
|
488
|
-
Allow-list entries are OR alternatives. `argsPrefix` is one ordered token
|
|
489
|
-
sequence:
|
|
490
|
-
|
|
491
|
-
```yaml
|
|
492
|
-
mode: allow-list
|
|
493
|
-
allow:
|
|
494
|
-
- executable: git
|
|
495
|
-
argsPrefix: [status]
|
|
496
|
-
- executable: project-check
|
|
497
|
-
argsPrefix: [test]
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
This permits `project-check test --focused` but not `project-check build`.
|
|
501
|
-
|
|
502
|
-
Use `argsPrefixes` to merge several alternatives for one executable without
|
|
503
|
-
widening permission:
|
|
504
|
-
|
|
505
|
-
```yaml
|
|
506
|
-
mode: allow-list
|
|
507
|
-
allow:
|
|
508
|
-
- executable: git
|
|
509
|
-
argsPrefixes: [[status], [diff], [show, --stat]]
|
|
510
|
-
- executable: gh
|
|
511
|
-
argsPrefixes: [[pr, view], [pr, diff], [api]]
|
|
512
|
-
```
|
|
513
|
-
|
|
514
|
-
The inner arrays are OR alternatives. Tokens inside one inner array are an
|
|
515
|
-
ordered prefix. Therefore `argsPrefix: [status, diff]` means the literal
|
|
516
|
-
sequence `git status diff`; it does not mean “status or diff.” `argsPrefix` and
|
|
517
|
-
`argsPrefixes` are mutually exclusive in one rule. Omitting both allows that
|
|
518
|
-
executable with any safely tokenized arguments.
|
|
519
|
-
|
|
520
|
-
The engine deliberately has no package-manager, language, framework, Git, or
|
|
521
|
-
hosted-API command knowledge. It does not rewrite command argument order and
|
|
522
|
-
does not derive Bash authority from prompts, summaries, or gate artifacts.
|
|
523
|
-
Command meaning and syntax belong to the step prompt and the agent's own
|
|
524
|
-
context; executable scope belongs entirely to the YAML `allow` rules.
|
|
525
|
-
|
|
526
|
-
Hard turn and tool-call budgets are best for non-mutating inspection and
|
|
527
|
-
verification steps. For a step that edits files, use a generous timeout and no
|
|
528
|
-
hard count budget unless partial edits are acceptable; inspect the working tree
|
|
529
|
-
after any interruption before resuming.
|
|
530
|
-
|
|
531
|
-
## Built-in review gate
|
|
532
|
-
|
|
533
|
-
Human review works without Plannotator. Omit `provider` (or set it to `prompt`)
|
|
534
|
-
to use Pi's built-in prompt panel:
|
|
535
|
-
|
|
536
|
-
```yaml
|
|
537
|
-
gate:
|
|
538
|
-
submitOutcome: submit
|
|
539
|
-
approvedOutcome: approved
|
|
540
|
-
rejectedOutcome: changes-requested
|
|
541
|
-
transitions:
|
|
542
|
-
approved: implement
|
|
543
|
-
changes-requested: plan
|
|
544
|
-
blocked: $pause
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
When the step completes with outcome `submit`, it must include the full content
|
|
548
|
-
in `artifact`. Pi shows Approve, Request changes, and Pause workflow. Requested
|
|
549
|
-
changes are returned through `{{gate.feedback}}`; approval persists the
|
|
550
|
-
artifact as `{{reviewed.artifact}}` while the step's `summary` remains the
|
|
551
|
-
compact handoff. Here, `changes-requested: plan` immediately runs a fresh
|
|
552
|
-
attempt of that exact gated step with the rejected draft in
|
|
553
|
-
`{{gate.artifact}}`, the original incoming step handoff, and the new feedback,
|
|
554
|
-
then opens another review. Use
|
|
555
|
-
`changes-requested: $pause` instead when revision should require an explicit
|
|
556
|
-
`/workflow-resume`. Dismissing the panel keeps the pending artifact, so
|
|
557
|
-
`/workflow-resume` reopens the same review.
|
|
558
|
-
|
|
559
|
-
Dialog-capable UI is available in Pi TUI and RPC modes. In print or JSON mode,
|
|
560
|
-
the gate pauses safely until resumed in TUI or RPC.
|
|
561
|
-
|
|
562
|
-
## Works great with Plannotator
|
|
563
|
-
|
|
564
|
-
[Plannotator](https://github.com/backnotprop/plannotator) gives Pi a local,
|
|
565
|
-
browser-based surface for visually reviewing and annotating plans. It is
|
|
566
|
-
optional, but highly recommended for rich plan feedback. Install its Pi
|
|
567
|
-
extension alongside Pi Workflows:
|
|
568
|
-
|
|
569
|
-
```bash
|
|
570
|
-
pi install npm:@plannotator/pi-extension
|
|
571
|
-
```
|
|
572
|
-
|
|
573
|
-
Pi Workflows uses Plannotator's shared extension API as a human approval gate:
|
|
574
|
-
|
|
575
|
-
- A workflow submits its plan or other Markdown artifact.
|
|
576
|
-
- Plannotator opens the visual review in your browser.
|
|
577
|
-
- Approval advances through the configured transition.
|
|
578
|
-
- Requested changes follow the workflow's configured transition with structured
|
|
579
|
-
feedback.
|
|
580
|
-
- Pausing never discards a decision; resume queries the same review identifier.
|
|
581
|
-
|
|
582
|
-
This keeps workflow order and permissions declarative while Plannotator handles
|
|
583
|
-
the human review experience.
|
|
584
|
-
|
|
585
|
-
### Configure a Plannotator gate
|
|
586
|
-
|
|
587
|
-
A step can submit an artifact to the installed Plannotator extension:
|
|
588
|
-
|
|
589
|
-
```yaml
|
|
590
|
-
gate:
|
|
591
|
-
provider: plannotator
|
|
592
|
-
submitOutcome: submit
|
|
593
|
-
approvedOutcome: approved
|
|
594
|
-
rejectedOutcome: changes-requested
|
|
595
|
-
timeoutMs: 30000
|
|
596
|
-
transitions:
|
|
597
|
-
approved: implement
|
|
598
|
-
changes-requested: plan
|
|
599
|
-
blocked: $pause
|
|
600
|
-
```
|
|
601
|
-
|
|
602
|
-
Setting `provider: plannotator` is the entire opt-in; do not also grant the
|
|
603
|
-
planning child Plannotator extension tools. The harness preflights the installed
|
|
604
|
-
extension automatically. A main-agent planning step calls
|
|
605
|
-
`workflow_complete_step`; a delegated planning child calls
|
|
606
|
-
`structured_output`. In either case it uses the configured submit outcome and
|
|
607
|
-
places the review content in `artifact`. The harness correlates the Plannotator
|
|
608
|
-
review identifier and accepts only the matching decision. On approval, the
|
|
609
|
-
artifact is preserved as an opaque template value; the separate `summary`
|
|
610
|
-
remains the next step's compact handoff.
|
|
611
|
-
|
|
612
|
-
The `approved` boolean from Plannotator is authoritative; feedback text and
|
|
613
|
-
annotation labels stay opaque. A rejection follows only the YAML transition
|
|
614
|
-
shown above. A same-step rejection is an explicitly human-controlled revision
|
|
615
|
-
loop, so that human-mediated transition bypasses the visit-limit check and may
|
|
616
|
-
continue until approval. The visit is still recorded, and later automatic
|
|
617
|
-
entries remain guarded. A same-step agent retry during revision preserves the
|
|
618
|
-
incoming handoff, rejected artifact, and feedback, but it does not bypass the
|
|
619
|
-
visit-limit check. Gate feedback is capped at 50,000 characters; history and
|
|
620
|
-
user notifications use a compact rejection summary while `{{gate.feedback}}`
|
|
621
|
-
receives the bounded full value.
|
|
622
|
-
|
|
623
|
-
The artifact is never substituted for a missing summary. If an older pending
|
|
624
|
-
gate has no separately stored summary, its transition uses an empty compact
|
|
625
|
-
handoff.
|
|
626
|
-
|
|
627
|
-
If review finishes while the workflow is paused, the result is checkpointed and applied only after `/workflow-resume`. Resume also queries Plannotator’s durable review status, so a decision made while Pi was closed is not lost.
|
|
628
|
-
|
|
629
|
-
### Artifact format belongs to the workflow
|
|
630
|
-
|
|
631
|
-
Pi Workflows imposes no plan headings, acceptance-criteria layout,
|
|
632
|
-
machine-readable appendix, command schema, or other Plannotator prompt format.
|
|
633
|
-
The step's YAML prompt defines what the artifact means and how downstream steps
|
|
634
|
-
use `{{reviewed.artifact}}`. Outcome names are equally opaque: names such as
|
|
635
|
-
`approved`, `retry`, or `replan` have only the transitions and meanings the
|
|
636
|
-
workflow author gives them.
|
|
637
|
-
|
|
638
|
-
In print or JSON mode, a pending built-in plan review remains safely paused.
|
|
639
|
-
Reopen the same session in TUI or RPC mode and run `/workflow-resume` to show
|
|
640
|
-
the preserved review instead of restarting the planning child.
|
|
641
|
-
|
|
642
|
-
## Pause, repair, resume
|
|
643
|
-
|
|
644
|
-
Use:
|
|
645
|
-
|
|
646
|
-
```text
|
|
647
|
-
/workflow-pause <optional reason>
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
The harness stops the active main-agent turn, dismisses a built-in review, or
|
|
651
|
-
sends the versioned pi-subagents cancellation event for a delegated step. It
|
|
652
|
-
keeps the exact current step and pending gate, then persists the checkpoint in
|
|
653
|
-
the Pi session. A late completion cannot advance a paused, aborted,
|
|
654
|
-
reconfigured, or replaced run.
|
|
655
|
-
|
|
656
|
-
When a step itself transitions to `$pause`, the checkpoint keeps both the
|
|
657
|
-
incoming previous-step handoff and the latest failed-attempt summary. The
|
|
658
|
-
resumed execution sees both. The run-start directory, any accepted workspace
|
|
659
|
-
binding, and any separately persisted reviewed artifact are preserved without
|
|
660
|
-
being interpreted.
|
|
661
|
-
|
|
662
|
-
Every settled step also posts one visible chat summary without starting another
|
|
663
|
-
agent turn. Successful and `$pause` outcomes show only the step's validated
|
|
664
|
-
`summary`; the final one also states that the workflow completed. Manual,
|
|
665
|
-
restored-session, and review pauses show their concise pause reason. Runtime
|
|
666
|
-
failures show only a short, redacted failure summary—not the task, artifact,
|
|
667
|
-
tool transcript, or full diagnostic. Complete evidence remains available in
|
|
668
|
-
the status explorer.
|
|
669
|
-
|
|
670
|
-
For a delegated step, if child termination is not confirmed within five
|
|
671
|
-
seconds, the pause is recorded but main tools remain isolated and resume is
|
|
672
|
-
blocked. Wait for the terminal event; if the delegation channel has already
|
|
673
|
-
failed, restart Pi before resuming. This prevents an old writer and a resumed
|
|
674
|
-
writer from overlapping.
|
|
675
|
-
|
|
676
|
-
When a delegated child returns `failed`, `structured_output_failed`,
|
|
677
|
-
`timed_out`, `turn_budget_exhausted`, or `tool_budget_exhausted`, the harness
|
|
678
|
-
audits the retained Pi child session before deciding whether to launch a fresh
|
|
679
|
-
automatic recovery child. The audit accepts only regular, non-symlink session
|
|
680
|
-
files contained by the current parent session's child-run root, requires the
|
|
681
|
-
persisted policy-stripped task and its per-request binding to match the active
|
|
682
|
-
delegation, reads a bounded complete tail, and proves that every recorded call
|
|
683
|
-
used a known-safe non-Bash tool or was rejected by policy before execution.
|
|
684
|
-
A zero-tool attempt is also replay-safe when the complete bound transcript
|
|
685
|
-
proves it. Executed Bash is treated as an unknown effect; automatic recovery
|
|
686
|
-
requires explicit authorization and still cannot claim that a domain-specific
|
|
687
|
-
command was non-mutating.
|
|
688
|
-
|
|
689
|
-
When the terminal error identifies a failed tool, the harness also records the
|
|
690
|
-
exact correlated call, tool error, subagent exit code, terminal error, and
|
|
691
|
-
validated diagnostic session path. If exact correlation is unavailable, the
|
|
692
|
-
generic terminal evidence is retained without claiming an unrelated command.
|
|
693
|
-
A failed process status is treated as resolved when the transcript proves a
|
|
694
|
-
successful `structured_output` occurred after every failed tool result and the
|
|
695
|
-
correlated result validates. This accepts the same finalized child result; it
|
|
696
|
-
never replays mutation-capable work.
|
|
697
|
-
|
|
698
|
-
Without a valid finalized result, the next fresh child receives the bounded
|
|
699
|
-
history of distinct terminal evidence in an escaped JSON data boundary and is
|
|
700
|
-
told to inspect current state, change its approach, resolve the cause, and
|
|
701
|
-
finish the original step. The harness launches at most two automatic recovery
|
|
702
|
-
children and stops early when the semantic failure fingerprint repeats.
|
|
703
|
-
Availability of `edit` or `write` is not itself a veto: the complete audit must
|
|
704
|
-
prove that the failed attempt did not actually make or attempt a mutation.
|
|
705
|
-
Mutation-capable or unknown-effect calls, reported file mutation, a truncated or
|
|
706
|
-
malformed transcript, a missing active-request binding, cancellation,
|
|
707
|
-
interruption, detached or stopped execution, and protocol/configuration errors
|
|
708
|
-
remain hard stops. Local channel failures also wait for confirmed child
|
|
709
|
-
termination instead of risking two live children.
|
|
710
|
-
|
|
711
|
-
Temporary delegation-workspace removal is best-effort housekeeping. A cleanup
|
|
712
|
-
error produces a warning but cannot pause an otherwise healthy next step or
|
|
713
|
-
recovery child. Synchronous startup exceptions are contained by the serialized
|
|
714
|
-
failure path. Each recovery uses a new request identity, private result
|
|
715
|
-
capability, and fresh context. The fixed two-attempt bound means a failing step
|
|
716
|
-
can consume at most three times its per-child timeout, turn budget, and tool
|
|
717
|
-
budget.
|
|
718
|
-
|
|
719
|
-
Inside a live child, recovery is not tied to a list of known error strings. The
|
|
720
|
-
agent receives the exact error and current state, then follows the user-authored
|
|
721
|
-
step prompt and configured outcomes. The engine does not assign a recovery,
|
|
722
|
-
pause, or replanning meaning to any outcome name.
|
|
723
|
-
|
|
724
|
-
While paused, fix repository code, workflow YAML, prompts, MCP configuration,
|
|
725
|
-
an extension, or any other environmental problem. Then run:
|
|
726
|
-
|
|
727
|
-
```text
|
|
728
|
-
/workflow-resume inspect the existing partial output before retrying
|
|
729
|
-
```
|
|
730
|
-
|
|
731
|
-
Resume reloads configuration before continuing:
|
|
732
|
-
|
|
733
|
-
- Optional text after `/workflow-resume` is passed as a user-authored
|
|
734
|
-
task-level amendment for this attempt. It may supersede conflicting prompt or
|
|
735
|
-
handoff instructions, but never YAML-enforced resource or workspace policy.
|
|
736
|
-
- The paused step restarts in its configured main-agent or delegated mode.
|
|
737
|
-
- A changed current step restarts that step.
|
|
738
|
-
- A changed ordinary completed step restarts the earliest changed completed step.
|
|
739
|
-
- A completed human-approved gate keeps its opaque reviewed artifact; later prompt or configuration digest changes do not reopen that gate while its configuration and approved outcome still match.
|
|
740
|
-
- Future-only changes preserve the current checkpoint.
|
|
741
|
-
- Removing the current or a completed step fails closed and requires restoring configuration or aborting.
|
|
742
|
-
- Restoring a Pi session automatically pauses an in-progress workflow for inspection.
|
|
743
|
-
- A pending built-in prompt review reopens with the same artifact.
|
|
744
|
-
- An interrupted Plannotator submission without a review identifier restarts the current step for resubmission.
|
|
745
|
-
|
|
746
|
-
## Commands
|
|
747
|
-
|
|
748
|
-
The full status overlay is an on-demand verification and history page. Toggle
|
|
749
|
-
it with `Ctrl+Alt+W` by default (`q` or `Esc` hides the board). Set
|
|
750
|
-
`statusShortcut` in `settings.yaml` to another Pi key identifier, then run Pi's
|
|
751
|
-
`/reload` to re-register it; `/workflow-reload` cannot change extension
|
|
752
|
-
shortcuts. The overlay shows run timing, execution or review, pause reasons,
|
|
753
|
-
configuration drift, and the completed attempt path without a task-viewer pane
|
|
754
|
-
below the editor. The main surface shows only one small animated
|
|
755
|
-
`◐`/`◓`/`◑`/`◒` working
|
|
756
|
-
indicator followed by the workflow id and current step title/id while a
|
|
757
|
-
workflow runs, then clears it when execution stops. This makes live progress
|
|
758
|
-
visible without opening the status page. All attempt logs, history, failure,
|
|
759
|
-
and review detail stays in the overlay. There, `✓` marks a completed step, `✕`
|
|
760
|
-
a failed or aborted run, and `◆` a paused step or pending review.
|
|
761
|
-
|
|
762
|
-
Use `↑`/`↓` or `j`/`k` to select a step, then `Enter`, `→`, or `l` to inspect
|
|
763
|
-
the bounded task supplied to each attempt, its result and gate decision, and a
|
|
764
|
-
chronological execution log when available. In the detail view,
|
|
765
|
-
`↑`/`↓` or `j`/`k` scrolls one line, while `Ctrl+D` and `Ctrl+U` scroll down and
|
|
766
|
-
up by half a page. `gg` jumps to the top and `G` jumps to the bottom. `←`, `h`,
|
|
767
|
-
or `Esc` returns to the board; `q` or the configured shortcut closes it.
|
|
768
|
-
PgUp/PgDn and Home/End retain page navigation.
|
|
769
|
-
Trace references and bounded task/result evidence live in the checkpoint, so
|
|
770
|
-
completed, paused, resumed, and restored runs remain inspectable. Child logs
|
|
771
|
-
are path-confined, size-bounded, control-sanitized, and redact common
|
|
772
|
-
credential forms.
|
|
773
|
-
For new main-agent attempts, the extension arms only on the exact workflow
|
|
774
|
-
task and checkpoints a redacted, size-bounded prefix of finalized assistant
|
|
775
|
-
and tool events in source order. This log remains part of the parent session,
|
|
776
|
-
but the explorer never reads unrelated parent-session traffic. Legacy
|
|
777
|
-
checkpoints without a main-agent log still show their bounded task and result.
|
|
778
|
-
Long reasons are clamped to the display width while the durable checkpoint
|
|
779
|
-
retains the full reason.
|
|
780
|
-
|
|
781
|
-
| Command | Purpose |
|
|
782
|
-
| ------------------------------- | --------------------------------------------------------- |
|
|
783
|
-
| `/workflow-list` | List loaded workflows and their configured commands. |
|
|
784
|
-
| `/workflow-doctor [id]` | Diagnose completion paths, unreachable steps, and cycles. |
|
|
785
|
-
| `/workflow-start <id> [input]` | Start by workflow identifier. |
|
|
786
|
-
| `/<configured-command> [input]` | Start through a workflow alias. |
|
|
787
|
-
| `/workflow-pause [reason]` | Halt without losing the checkpoint. |
|
|
788
|
-
| `/workflow-resume [guidance]` | Reload, reconcile, and continue with an optional hint. |
|
|
789
|
-
| `/workflow-abort [reason]` | End the active run and restore baseline tools. |
|
|
790
|
-
| `/workflow-reload` | Reload definitions while no workflow is running. |
|
|
791
|
-
|
|
792
|
-
Before a workflow starts or resumes, the doctor rejects graphs whose start
|
|
793
|
-
cannot reach `$done` or whose reachable branches contain a step that cannot
|
|
794
|
-
reach `$done`.
|
|
795
|
-
Unreachable steps and cycles are reported as warnings; a cycle with an exit may
|
|
796
|
-
run, but `maxStepVisits` pauses the uninterrupted run before a step can execute
|
|
797
|
-
more than its configured limit. An explicit resume can continue from that
|
|
798
|
-
checkpoint, so the guard bounds automatic graph advancement rather than
|
|
799
|
-
guaranteeing completion or wall-clock duration. An explicit human gate
|
|
800
|
-
rejection back to that same gated step bypasses the check for that transition;
|
|
801
|
-
the visit remains recorded and every iteration must stop for another human
|
|
802
|
-
decision.
|
|
803
|
-
|
|
804
|
-
Configured aliases also accept multiline input. For example, if `work` is a
|
|
805
|
-
loaded workflow command, Pi Workflows normalizes:
|
|
806
|
-
|
|
807
|
-
```text
|
|
808
|
-
/work
|
|
809
|
-
"""inspect and update this repository"""
|
|
810
|
-
```
|
|
811
|
-
|
|
812
|
-
to the same command with an argument instead of letting the raw multiline text
|
|
813
|
-
start an unrelated parent-agent turn.
|
|
814
|
-
|
|
815
|
-
## User and project configuration
|
|
816
|
-
|
|
817
|
-
User workflows are loaded first. A project may add workflows from:
|
|
818
|
-
|
|
819
|
-
```text
|
|
820
|
-
<project>/.pi/workflows/*.workflow.yaml
|
|
821
|
-
<project>/.pi/workflows/*.workflow.yml
|
|
822
|
-
```
|
|
823
|
-
|
|
824
|
-
Project workflows are disabled by default. Enable them in the user-owned
|
|
825
|
-
`~/.pi/agent/workflows/settings.yaml`:
|
|
826
|
-
|
|
827
|
-
```yaml
|
|
828
|
-
# yaml-language-server: $schema=/absolute/path/to/pi-workflows/schemas/settings.schema.json
|
|
829
|
-
version: 1
|
|
830
|
-
allowProjectWorkflows: true
|
|
831
|
-
statusShortcut: ctrl+alt+w
|
|
832
|
-
permissionCeiling:
|
|
833
|
-
tools: [read, grep, bash]
|
|
834
|
-
mcp: []
|
|
835
|
-
extensions: []
|
|
836
|
-
skills: []
|
|
837
|
-
bash:
|
|
838
|
-
mode: allow-list
|
|
839
|
-
allow:
|
|
840
|
-
- executable: git
|
|
841
|
-
argsPrefixes: [[status], [diff]]
|
|
842
|
-
- executable: rg
|
|
843
|
-
subagent:
|
|
844
|
-
agents: [scout, planner, worker, reviewer]
|
|
845
|
-
contexts: [fresh]
|
|
846
|
-
models: []
|
|
847
|
-
maxTimeoutMs: 900000
|
|
848
|
-
maxTurns: 40
|
|
849
|
-
maxGraceTurns: 3
|
|
850
|
-
maxToolCalls: 100
|
|
851
|
-
artifacts: false
|
|
852
|
-
retryToolFailures: false
|
|
853
|
-
```
|
|
854
|
-
|
|
855
|
-
Settings use the same strict YAML 1.2 parser as workflow definitions. The
|
|
856
|
-
`settings.schema.json` file remains JSON Schema so YAML-aware editors can
|
|
857
|
-
validate `settings.yaml`; adjust or remove the schema comment for your install
|
|
858
|
-
path.
|
|
859
|
-
|
|
860
|
-
Project workflows load only when Pi trusts the project and every step stays
|
|
861
|
-
within this ceiling. The `subagent` ceiling is optional for main-only project
|
|
862
|
-
workflows; if omitted, any project step that declares `subagent` is rejected.
|
|
863
|
-
Project workflows cannot declare `workspace` binding at all, even when their
|
|
864
|
-
other permissions fit the ceiling. Keep workflows that create, choose, or bind
|
|
865
|
-
a different execution directory in the user-owned workflow directory.
|
|
866
|
-
Each delegated project step must declare `turnBudget` and `toolBudget` with
|
|
867
|
-
`"block": "*"`, so it cannot silently inherit unbounded child defaults or keep
|
|
868
|
-
mutation tools after reaching the hard limit. The ceiling also controls
|
|
869
|
-
agent profile names, fresh-context use, model overrides, timeouts, artifact
|
|
870
|
-
retention, and the Bash rules that a project workflow may request. Project
|
|
871
|
-
workflows cannot override user workflow identifiers or commands.
|
|
872
|
-
|
|
873
|
-
## Architecture
|
|
874
|
-
|
|
875
|
-
The package keeps the Pi entry point intentionally small:
|
|
876
|
-
|
|
877
|
-
| Module | Responsibility |
|
|
878
|
-
| --------------------------------- | --------------------------------------------------------------- |
|
|
879
|
-
| `src/index.ts` | Pi entry point only. |
|
|
880
|
-
| `src/harness.ts` | Runtime orchestration and session lifecycle. |
|
|
881
|
-
| `src/commands.ts` | User command surface. |
|
|
882
|
-
| `src/config/` | Types, strict validation, prompt loading, precedence, ceilings. |
|
|
883
|
-
| `src/engine/` | Serializable run state and deterministic transitions. |
|
|
884
|
-
| `src/policy/` | Tool, MCP, and Bash enforcement. |
|
|
885
|
-
| `src/workflow-doctor.ts` | Deterministic transition-graph liveness diagnostics. |
|
|
886
|
-
| `src/integrations/subagents/` | Delegation client, child protocol, and child policy runtime. |
|
|
887
|
-
| `src/integrations/plannotator.ts` | Versioned Plannotator gate adapter. |
|
|
888
|
-
| `src/integrations/prompt-gate.ts` | Built-in Pi prompt review adapter. |
|
|
889
|
-
| `src/runtime/` | Shared completion parsing and main-agent step runtime. |
|
|
890
|
-
| `src/preflight.ts` | Required tool, extension, and skill checks. |
|
|
891
|
-
| `src/prompt.ts` | Template rendering and step contract. |
|
|
892
|
-
| `agents/step.md` | Default general-purpose profile plus workflow child guidance. |
|
|
893
|
-
|
|
894
|
-
The engine and policy modules do not depend on Pi runtime types, so they are fast to test.
|
|
895
|
-
|
|
896
|
-
## Security model
|
|
897
|
-
|
|
898
|
-
Pi extensions are not an operating-system sandbox. Installed extensions execute with the user’s process permissions.
|
|
899
|
-
|
|
900
|
-
The harness provides model-level least privilege in both execution modes, plus
|
|
901
|
-
process separation when a step opts into pi-subagents:
|
|
902
|
-
|
|
903
|
-
- active-tool narrowing for every step;
|
|
904
|
-
- authoritative `tool_call` blocking and immutable authorized arguments;
|
|
905
|
-
- completion as the sole call in its tool batch;
|
|
906
|
-
- optional separate pi-subagents child process per delegated step;
|
|
907
|
-
- an idle, tool-isolated main agent while a delegated step runs;
|
|
908
|
-
- a single-use, parent-created child capability tied to the delegated step;
|
|
909
|
-
- explicit MCP server and tool checks;
|
|
910
|
-
- restricted Bash parsing;
|
|
911
|
-
- exact user-declared Bash executable and argument-prefix rules;
|
|
912
|
-
- project trust and a user-owned permission ceiling;
|
|
913
|
-
- fail-closed durable state, correlated child results, and correlated gate results.
|
|
914
|
-
|
|
915
|
-
It does not restrict commands the human explicitly runs with Pi’s `!` Bash
|
|
916
|
-
input. In main-agent mode it cannot hide globally loaded skills or isolate the
|
|
917
|
-
transcript. In either mode it cannot disable side effects performed
|
|
918
|
-
autonomously by a loaded extension. Review workflow, agent, and extension
|
|
919
|
-
source before installing or enabling it.
|
|
920
|
-
|
|
921
|
-
Step completion is structurally validated—policy digest, declared outcome,
|
|
922
|
-
non-empty bounded summary, required gate artifact, and sole completion call—but
|
|
923
|
-
the harness cannot prove that a model's semantic claims or test evidence are
|
|
924
|
-
true. Put exact checks and acceptance criteria in the workflow prompt, use an
|
|
925
|
-
independent verification step, and keep consequential actions behind a human
|
|
926
|
-
gate.
|
|
927
|
-
|
|
928
|
-
The harness does not provide exactly-once external effects. If a publish step
|
|
929
|
-
is interrupted after a remote action succeeds but before it checkpoints, a
|
|
930
|
-
resumed execution receives the same declarative step permissions. Publish
|
|
931
|
-
prompts should query the remote effect first, skip only proven-complete actions,
|
|
932
|
-
and pause on ambiguous state.
|
|
933
|
-
|
|
934
|
-
## Development
|
|
935
|
-
|
|
936
|
-
```bash
|
|
937
|
-
bun install
|
|
938
|
-
bun run check
|
|
939
|
-
```
|
|
940
|
-
|
|
941
|
-
Tests cover graph validation, prompt confinement, command conflicts, project
|
|
942
|
-
ceilings, deterministic transitions, configuration reconciliation, pause/resume
|
|
943
|
-
state, gate handling, MCP isolation, Bash policy, extension tool selection,
|
|
944
|
-
main-agent completion, built-in feedback/approval, subagent request correlation
|
|
945
|
-
and cancellation, child policy enforcement, and dependency preflight,
|
|
946
|
-
including bounded automatic recovery after replay-safe terminal errors,
|
|
947
|
-
timeouts, budget exhaustion, and nonzero exits; duplicate-failure stopping;
|
|
948
|
-
opaque gate artifacts; workspace binding and cwd reuse; workflow liveness
|
|
949
|
-
diagnostics; and fail-closed legacy checkpoints.
|
|
950
|
-
`bun run check` also launches real Pi RPC subprocesses, invokes
|
|
951
|
-
`/work`, and verifies fresh `scout`, `worker`, and `reviewer` children receive
|
|
952
|
-
only the explicit compact handoff from the immediately preceding step. The
|
|
953
|
-
real-Pi scenario binds a sibling workspace, revisits its worker once, and
|
|
954
|
-
verifies that every downstream visit keeps the bound cwd and receives no
|
|
955
|
-
undeclared `replan` outcome.
|
|
956
|
-
|
|
957
|
-
## Publishing checklist
|
|
958
|
-
|
|
959
|
-
Before publishing:
|
|
960
|
-
|
|
961
|
-
1. Confirm the package name and repository metadata.
|
|
962
|
-
2. Run `bun run check`.
|
|
963
|
-
3. Merge a Conventional Commit PR and verify its GitHub Release artifact.
|
|
3
|
+
# Pi Workflows
|
|
964
4
|
|
|
965
|
-
|
|
5
|
+
**Make repeatable Pi agent work explicit, durable, and safe to continue.**
|
|
966
6
|
|
|
967
|
-
|
|
7
|
+
Pi Workflows is a declarative, pauseable workflow harness for Pi. Define steps,
|
|
8
|
+
tools, prompts, approvals, and outcomes in YAML; it provides bounded execution,
|
|
9
|
+
durable checkpoints, isolated subagent work, and a live status view without
|
|
10
|
+
dictating your language, framework, or delivery process.
|
|
968
11
|
|
|
969
|
-
|
|
970
|
-
extensions, without hard-coding them into the orchestrator, are:
|
|
12
|
+
## Why Pi Workflows
|
|
971
13
|
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
| Parallel groups and join policy | Run independent steps together and declare fail-fast, quorum, or all-success behavior. |
|
|
977
|
-
| Generic gates | Add ticket, CI, chat, or custom approval providers behind the same versioned gate contract. |
|
|
978
|
-
| Output schema and named artifacts | Pass structured data between steps instead of relying only on a summary. |
|
|
979
|
-
| Cost and token ceilings | Bound model spend independently from turn and tool-call budgets. |
|
|
980
|
-
| Environment and secret references | Select named credentials without embedding secret values in workflow files. |
|
|
981
|
-
| Logging and retention | Configure progress events, redaction, child artifact retention, and checkpoint history. |
|
|
14
|
+
- Turn multi-step agent work into clear, reviewable workflow definitions.
|
|
15
|
+
- Pause for human approval and resume from the same durable checkpoint.
|
|
16
|
+
- Keep worktree-bound iterations safe, including follow-up enhancements.
|
|
17
|
+
- Enforce declared resources and stop unsafe loops before they run away.
|
|
982
18
|
|
|
983
|
-
##
|
|
19
|
+
## Explore
|
|
984
20
|
|
|
985
|
-
-
|
|
986
|
-
|
|
987
|
-
-
|
|
988
|
-
|
|
989
|
-
-
|
|
990
|
-
|
|
21
|
+
- [Getting started guide](./GETTING_STARTED.md) — install Pi Workflows and
|
|
22
|
+
run your first workflow.
|
|
23
|
+
- [Contribution guide](./CONTRIBUTING.md) — set up the project, validate a
|
|
24
|
+
change, and open a focused pull request.
|
|
25
|
+
- [Documentation → OpenWiki](./openwiki/quickstart.md) — architecture,
|
|
26
|
+
workflow authoring, security, integrations, and development references.
|
|
991
27
|
|
|
992
28
|
## License
|
|
993
29
|
|
|
994
|
-
|
|
30
|
+
[MIT](./LICENSE)
|