# Onsager Run Workflow

> Fire an Onsager workflow's manual trigger to start a new run and surface the resulting artifact. Triggers include "run this workflow", "execute the pipeline", "trigger a run", "kick off the digest workflow", "fire the backfill once", "run the manual workflow named go". Allowed tools cover the manual-trigger fire, recent-runs lookup (to discover the artifact the runtime materialises asynchronously), and an initial inspection. Deep diagnosis lives in `onsager-triage-run`.

- Skill: `onsager-ai/onsager-run-workflow` (Agent Skill)
- Install (CLI): `npx skillmds@latest add onsager-ai/onsager-run-workflow`
- Raw SKILL.md: https://api.skillmd.com/api/skills/onsager-ai/onsager-run-workflow/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: onsager-ai (https://skillmd.com/u/onsager-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/onsager-ai/onsager-run-workflow

---


# onsager-run-workflow

A workflow's `manual` trigger is a named door — fire it with `run_workflow` and the workflow runtime materialises a new artifact (one artifact == one run). This skill covers the "I want this workflow to run *now*" path. Scheduled / webhook-triggered runs fire on their own; you don't need this skill for them.

## When this skill triggers

Phrases that should route here:

- "run the morning-digest workflow"
- "fire the backfill once"
- "trigger a run of the PR-review pipeline"
- "kick off the workflow named `nightly`"
- "execute the manual workflow `go`"

If the user wants to *design* a workflow, hand off to `onsager-design-workflow`. If they want to *triage* a failing run, hand off to `onsager-triage-run`.

## Operating procedure

### Step 1 — find the workflow

If the user names the workflow by id (`wf_…`), use it directly. Otherwise call `list_workflows` against the workspace and match by name:

```json
{ "workspace_id": "<ws>" }
```

The response is `{ "workflows": [ { "id": "wf_…", "name": "…", "active": true, "trigger": { … } }, … ] }`. Pick the row whose `name` matches and confirm `active: true` (an inactive workflow can't fire — point the user at the dashboard's activate switch).

Also confirm the trigger is `manual`. If it's `cron` / `github_*` / `spine_event` / etc., this skill doesn't apply — runs of that workflow happen on their own schedule or in response to external events. Tell the user that and don't call `run_workflow`.

### Step 2 — pick the trigger name

`manual` triggers have a `name` field (set when the workflow was designed). If the user said "fire the `nightly` trigger", pass `trigger_name: "nightly"`. Otherwise read the workflow's trigger payload from step 1 — `trigger.kind == "manual"` carries a `name` field; use exactly that string.

### Step 3 — call `run_workflow`

```json
{
  "workflow_id": "wf_…",
  "trigger_name": "go",
  "payload": { "user_note": "manual fire from chat" }
}
```

`payload` is optional. Canonical fields (`workflow_id`, `workspace_id`, `name`, `actor`, `source`, `fired_at`, `trigger_kind`) always override any colliding keys, so you can pass arbitrary structured data without worrying about clobbering the trigger's own metadata.

The tool returns:

```json
{
  "workflow_id": "wf_…",
  "trigger_event_id": 123456,
  "fired_at": "2026-…"
}
```

Note: `run_workflow` does **not** return an `artifact_id`. It emits the `workflow.trigger.fired` event onto the spine; the workflow runtime materialises the artifact asynchronously a moment later (typically <1s). The `trigger_event_id` is the audit pointer back to the fire — useful for log searches, not for deep-linking the run.

### Step 4 — discover the new artifact

Call `list_runs` against the workflow to find the artifact the runtime just materialised:

```json
{ "workflow_id": "wf_…", "limit": 5 }
```

Look for the newest row whose `started_at` is at or after the `fired_at` you got back from `run_workflow`. That's the new run; its `artifact_id` is the deep-link target — surface it as `<portal-url>/runs/<artifact_id>` to the user.

If the newest row's `started_at` is still earlier than `fired_at`, the runtime hasn't materialised the artifact yet (rare; usually <1s lag). Tell the user the fire succeeded and to refresh the dashboard in a moment; don't loop polling.

### Step 5 — first-look inspection

Once you have the artifact id, call `inspect_run`:

```json
{ "artifact_id": "<artifact_id>", "event_limit": 20 }
```

The response carries:

- `artifact.state` — one of `draft`, `in_progress`, `under_review`, `released`, `archived`. Right after fire the runtime advances the artifact through these as stages enter/exit (`in_progress` for `agent-session` stages, `under_review` for `external-check` / `governance` / `manual-approval` stages).
- `artifact.current_stage_index` — 0 right after fire; advances as stages pass.
- `artifact.workflow_parked_reason` — `null` for a healthy run. **Non-null means the run is parked at the current stage** (and is **not** a fire-success path): hand off to `onsager-triage-run`.
- `recent_events` — newest first. Look for `workflow.trigger.fired` (your fire) and the subsequent `stage.entered` events as the workflow advances.

Report back to the user: "Started run `<artifact_id>`, currently on stage `<index>` (`<gate_kind>`). Open the run at `/runs/<artifact_id>`." Don't loop polling — one read is enough; the user opens the dashboard for live state.

## Common shapes

### "Fire workflow X now"

```json
{ "workflow_id": "wf_abc", "trigger_name": "go" }
```

### "Fire workflow X with some context"

```json
{
  "workflow_id": "wf_abc",
  "trigger_name": "go",
  "payload": {
    "reason": "ad-hoc backfill, requested by @alice",
    "scope": "open issues created before 2026-01-01"
  }
}
```

## Failure modes to watch for

- **`InvalidParams: workflow <id> does not declare manual trigger `<name>` …`** — the workflow's trigger is scheduled or webhook-driven, or `trigger_name` doesn't match the configured `name`. Re-read the workflow's `trigger` field from `list_workflows`; if it's not `manual`, this skill doesn't apply.
- **`InvalidParams: workflow is inactive — activate before firing`** — workflow exists but `active: false`. Tell the user to activate it in the dashboard first; this skill cannot activate it (per `onsager-design-workflow`'s headers limitation).
- **`Unauthorized`** — PAT doesn't have workspace access.
- **`artifact.workflow_parked_reason` non-null on first inspect** — hand off to `onsager-triage-run`.

## Related skills

- `onsager-design-workflow` — create or modify the workflow blueprint.
- `onsager-explore-artifacts` — list past runs or fetch a specific artifact.
- `onsager-triage-run` — diagnose a run that failed or got stuck.

