# pm_workflow
{{< tier level="sovereign" note="`pm_workflow` gives agents and local automation a supported interface for durable workflow operations." >}}

Use `pm_workflow` to validate or save definitions, start and inspect runs, record supported wait outcomes, and apply explicit recovery actions.

{{< callout type="info" >}}
Use [Valdr UI](/valdr/docs/ui/workflows/) for visual authoring, human approval gates, and day-to-day operation. Use direct MCP when an agent or local automation needs a structured workflow action.
{{< /callout >}}

Call `help` before building automation against a running Valdr installation:

```text
pm_workflow { action: "help" }
pm_workflow { action: "help", topic: "start" }
```

Passing `topic` with one action name returns guidance and examples for that action alone; omitting it (or passing `"all"`) returns the full help payload.

## Actions

| Action | Purpose |
| --- | --- |
| `list` | Find saved workflow definitions; summary rows by default, `detail: "full"` for complete records, `latestOnly: true` for one newest version per key |
| `get` | Read one workflow definition |
| `validate` | Validate definition JSON or YAML without saving it |
| `save_definition` | Validate and save a local workflow definition |
| `delete_definition` | Preview blockers or retire one exact workflow definition |
| `restore_definition` | Restore one exact retired workflow definition |
| `test_definition` | Run an unsaved definition as a durable test |
| `start` | Start a run from a saved workflow version |
| `get_run` | Inspect one run; compact by default, with opt-in step, wait, evidence, dependency, or child detail |
| `list_runs` | Search runs by workflow, scope, hierarchy, or status |
| `events` | Read a run's event timeline |
| `advance` | Advance one ready workflow transition |
| `input` | Record a supported callback outcome for an open await-condition step |
| `override_wait` | Record an authorized, audited override for a stuck workflow-input wait |
| `retry_step` | Add another eligible attempt to a blocked or failed step |
| `rerun` | Start a separate run from a terminal source run |
| `cancel` | Cancel a run tree, or stop one exact running Command attempt |
| `delete_run` | Delete a closed run tree with actor and reason attribution |
| `help` | Return live action guidance and examples |

## Find a definition and version

Discover installed versions before starting a run:

```text
pm_workflow {
  action: "list",
  workflowKey: "valdr-workflow.task.deliver",
  lifecycleStatus: "active",
  detail: "summary"
}
```

Use `packKey`, `capabilityKey`, or `query` to narrow a larger catalog; add `latestOnly: true` when you need only the newest version per key. Lists support `limit` and `cursor`. Read one exact definition with `get` using `workflowKey` plus `version`, or use its `contentHash`. The `get` action also supports `capabilityKey` and the `lifecycleStatus` filter.

## Validate a definition

`validate` accepts one of `definitionJson`, `definitionYaml`, or `capabilityKey`. Execution-ready validation is strict automatically:

```text
pm_workflow {
  action: "validate",
  definitionYaml: "schemaVersion: 1.0\nworkflow:\n  key: example.simple\n  name: Example Simple\n  version: 0.1.0\n  start:\n    mode: manual\n  inputs: {}\n  steps: []"
}
```

Invalid content returns diagnostics without saving a definition.

## Save a definition

`save_definition` accepts the same JSON or YAML source and applies strict validation automatically:

```text
pm_workflow {
  action: "save_definition",
  definitionYaml: "<workflow YAML>"
}
```

Create a new version when behavior changes. If you intentionally update a definition at the same key and version, first reload it and supply `overwrite: true` with its current `expectedContentHash`. Preserve its exact `packKey` and `sourceRelpath` provenance. A stale hash or changed provenance is rejected so one editor cannot overwrite another editor's newer change.

This guarded overwrite also supports pack-managed definitions, but the result becomes locally managed. Prefer updating the source pack so a later import does not reintroduce the old definition. Existing runs retain their frozen routing and child revisions, and reruns reuse those frozen revisions. One explicit same-run exception applies to an eligible manual retry of a saved Command step: the new attempt can snapshot the active saved definition's `command`, `cwd`, and `timeoutSeconds`; prior attempts remain unchanged.

## Retire or restore a definition

Retirement removes one exact version from ordinary catalog use without deleting its historical runs. Preview blockers first:

```text
pm_workflow {
  action: "delete_definition",
  workflowKey: "example.task.delivery-review",
  version: "0.1.0",
  expectedContentHash: "sha256:<content-hash>",
  preview: true
}
```

Valdr blocks retirement while an active definition or nonterminal run depends on that version. Retired versions cannot start or rerun until restored. In Valdr UI, use **Retire**, **Show retired**, and **Restore** for this lifecycle. Ordinary MCP clients can preview retirement blockers, but a preview must omit mutation audit fields such as `actorHandle`, `reason`, and `clientRequestId`. Retirement and restoration are performed by Valdr's trusted UI operator actions with recorded actor, reason, and request identity.

## Test an unsaved definition

`test_definition` validates the supplied definition, starts a test run, and drives it until it reaches a wait or terminal state, or consumes its 50-transition test budget. It returns the durable run and step results without saving the definition to the catalog.

Provide one definition source, a `clientRequestId`, declared inputs, and any scope the workflow requires.

## Start a run

Prefer selecting a workflow by key and version:

```text
pm_workflow {
  action: "start",
  workflowKey: "example.task.delivery-review",
  version: "0.1.0",
  taskKey: "NOVA-42",
  actorHandle: "workflow-operator",
  inputs: {
    taskKey: "NOVA-42",
    executorHandle: "ember-executor",
    reviewerHandle: "sage-reviewer"
  },
  clientRequestId: "automation:start:01EXAMPLE"
}
```

`contentHash` is also available as an exact selector for automation that already recorded it. If both version and content hash are supplied, both must identify the same definition.

`actorHandle` must name a registered agent. If it is omitted and a step needs an actor, Valdr uses the registered `pm` agent.

Before starting, confirm every referenced agent and launcher preset is available. Valdr UI performs this preflight automatically.

## Inspect and advance

Use `get_run` to read current status, steps, waits, declared results, evidence, and child workflows. The default response is compact — run status and loop progress only, which is the right shape for polling. Pass `includeSteps: true`, `includeWaits: true`, or `includeChildren: true` for the matching detail collections, `includeAcceptedInputs: true` for accepted callback and gate evidence, `includeDefinition: true` for the exact definition revision the run froze, and `includeDependencies: true` for the frozen child-version pin map (useful before `rerun`).

Use `list_runs` for discovery; it supports workflow, task, project, context, status, parent/root, `rootOnly`, `query`, `limit`, and `cursor` filters. Use `events` for the timeline. Events omit payload bodies by default and support `afterSeq` or `cursor`, `eventTypes`, and `limit` up to 500; add `includePayload: true` only for targeted detail.

`advance` performs one ready transition:

```text
pm_workflow {
  action: "advance",
  runUlid: "01EXAMPLERUN"
}
```

Repeat only while the returned run has ready work. Stop when it waits, blocks, fails, completes, or is cancelled.

## Record callback input

Direct `input` is for an open await-condition step that exposes a callback token. It cannot be used to impersonate an operator at a human approval gate.

```text
pm_workflow {
  action: "input",
  runUlid: "01EXAMPLERUN",
  stepKey: "await_executor",
  waitUlid: "01EXAMPLEWAIT",
  kind: "callback",
  origin: "agent_session",
  outcome: "executor_completed",
  sourceSessionUlid: "01EXAMPLESESSION",
  callbackToken: "<token returned for this wait>",
  clientRequestId: "agent:input:01EXAMPLE"
}
```

The outcome and any supplied task, review, or session references must match the open wait. Resolve human gates in Valdr UI using the authored decision controls.

## Override a stuck wait

`override_wait` is a reserved recovery action for a trusted operator integration when an open `workflow_input` wait cannot be satisfied through its normal evidence path. Ordinary MCP clients cannot invoke it. Prefer the authored input, retry, cancellation, or a separate rerun; expose an override only through an integration that can provide trusted operator identity and record the actor, reason, and request ID.

## Retry a step

Read the latest run detail first, then use the current attempt number shown for an eligible step:

```text
pm_workflow {
  action: "retry_step",
  runUlid: "01EXAMPLERUN",
  stepKey: "load_task",
  expectedAttempt: 2,
  actorHandle: "workflow-operator",
  reason: "Retry after correcting the task reference.",
  clientRequestId: "automation:retry:01EXAMPLE"
}
```

Retrying creates another attempt and preserves the earlier history. Completed and cancelled runs are closed; failed runs remain retryable when the latest failed or blocked attempt has a safe error category. Valdr also rejects outdated attempt numbers. Authored `retry.maxAttempts` is a reported attempt count; it neither caps manual recovery nor schedules automatic retries or backoff.

## Run again

`rerun` creates a separate run from a completed, failed, or cancelled root run:

```text
pm_workflow {
  action: "rerun",
  sourceRunUlid: "01EXAMPLESOURCERUN",
  inputs: { validationCommand: "npm test" },
  clientRequestId: "automation:rerun:01EXAMPLE"
}
```

The new run uses the same workflow versions and scope. Omit `inputs` to reuse the source run's inputs; when you supply `inputs`, provide the complete non-scope input set for the new run. Start the newer definition directly when you want updated behavior.

## Cancel or delete a run

Whole-run `cancel` stops workflow orchestration; see [cancellation scope](/valdr/docs/workflows/reliability-and-recovery/#cancellation) for which sessions and commands it stops. Active child runs are cancelled by default. `cascade: false` is accepted only when no active child runs exist.

To stop one running Command attempt without cancelling the workflow run, supply both `stepKey` and its current `expectedAttempt`. Do not supply `cascade` for a step-scoped cancellation:

```text
pm_workflow {
  action: "cancel",
  runUlid: "01EXAMPLERUN",
  stepKey: "verify_change",
  expectedAttempt: 1,
  reason: "Stop the long-running validation command.",
  clientRequestId: "automation:stop-command:01EXAMPLE"
}
```

`delete_run` removes a root or child run tree only when every run in it is blocked, failed, completed, or cancelled. Pending, running, and waiting runs must be cancelled first. Valdr does not provide a restore action for deleted runs. Supply the run ULID, a registered `actorHandle`, a non-empty reason, and a `clientRequestId`; externally referenced child runs are rejected.

In Valdr UI, **Delete run** also deletes linked session records, events, transcripts, and session-owned worktrees by default. Select **Keep linked sessions** to preserve them before confirming. Direct `pm_workflow delete_run` removes workflow history only; session cleanup is a separate UI operation.

## Handle detailed results carefully

`get_run` and `events` return compact records unless you opt into detail, so the default calls are already safe for routine polling. Request only the detail collections your automation needs, avoid logging callback tokens or sensitive agent output, and prefer declared workflow results for ordinary integrations.

## Next step

Use the [Workflow Steps reference](/valdr/docs/workflows/steps/) to author supported nodes, or ask [Verdandi](/valdr/docs/valdr-packs/what-comes-with-valdr/starter-packs/verdandi/) to author, operate, or diagnose a workflow through the same MCP surface. Keep [Workflow Troubleshooting](/valdr/docs/workflows/troubleshooting/) nearby for recovery.

