YAML Reference
This is the complete schema reference for SWEny workflow YAML files. Every field, every validation rule, every constraint.
Top-level fields
Section titled “Top-level fields”| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique workflow identifier. Used in CLI commands, exports, and event payloads. |
name | string | Yes | Human-readable display name. Shown in CLI output, Studio, and notifications. |
description | string | No | What this workflow does. Defaults to empty string. |
entry | string | Yes | ID of the entry node. Execution starts here. |
nodes | object | Yes | Map of node ID to node definition. Keys are the node IDs. |
edges | array | Yes | Array of edge objects defining the graph structure. |
Node definition
Section titled “Node definition”Each key in the nodes object is a node ID (an arbitrary string you choose). The value is a node definition:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | — | Display name for this node. |
instruction | string | Yes | — | Natural language instruction telling Claude what to do at this step. |
skills | string[] | No | [] | Skill IDs whose tools should be available at this node. |
output | object | No | — | JSON Schema for structured output validation. |
Instructions
Section titled “Instructions”The instruction field is the core of each node. Write it as you would write a prompt for Claude — clear, specific, and focused on a single task. Claude receives the instruction along with the workflow input and all prior node results as context.
Good instructions:
- Focus on one task per node
- List explicit steps (numbered or bulleted)
- Specify what tools to use and what to look for
- State what output is expected
Skills
Section titled “Skills”The skills array lists skill IDs that should be available at this node. Each skill provides a set of tools that Claude can call.
Available skill IDs:
| Skill ID | Category | Tools provided |
|---|---|---|
github | git | Repository operations, PRs, issues, file read/write, code search |
linear | tasks | Issue CRUD, project/team queries, comments |
sentry | observability | Error search, issue details, event data, releases |
datadog | observability | Log search, metric queries, monitor status |
betterstack | observability | Incident list, log search |
slack | notification | Send messages, search channels |
notification | notification | Discord, Teams, webhook, and email notifications |
Output schema
Section titled “Output schema”The output field accepts a JSON Schema object. When present, Claude’s response is validated against this schema, and the resulting structured data is available to downstream nodes and routing conditions.
output: type: object properties: severity: type: string enum: [critical, high, medium, low] root_cause: type: string is_fixable: type: boolean required: [severity, root_cause]Any valid JSON Schema is accepted. Common patterns:
enumto constrain values for routing conditionsrequiredto ensure key fields are always presenttype: arraywithitemsfor lists
Edge definition
Section titled “Edge definition”Each entry in the edges array is an edge object:
| Field | Type | Required | Description |
|---|---|---|---|
from | string | Yes | Source node ID. |
to | string | Yes | Target node ID. |
when | string | No | Natural language condition. Claude evaluates this at runtime. |
Unconditional edges
Section titled “Unconditional edges”An edge without a when clause is unconditional — the executor always follows it. Use these for linear sequences:
edges: - from: gather to: analyze - from: analyze to: reportIf a node has exactly one outgoing edge and that edge is unconditional, the executor follows it without invoking Claude for a routing decision.
Conditional edges
Section titled “Conditional edges”An edge with a when clause is conditional. The when value is natural language that Claude evaluates against the current node’s result:
edges: - from: analyze to: fix when: "The issue is fixable with a simple code change" - from: analyze to: escalate when: "The issue requires infrastructure changes or human review"When a node has multiple outgoing conditional edges, the executor presents all conditions as choices and asks Claude to pick the one that matches. If one edge is unconditional among conditional siblings, it acts as the default/fallback path.
Terminal nodes
Section titled “Terminal nodes”A node with no outgoing edges is a terminal node. When the executor reaches a terminal node, the workflow ends. Every workflow must have at least one terminal node (otherwise execution would never stop).
Complete example
Section titled “Complete example”id: deploy-checkname: Deployment Health Checkdescription: Verify a deployment succeeded and take action if it didn'tentry: check_health
nodes: check_health: name: Check Deployment Health instruction: | Check the health of the most recent deployment: 1. Look at error rates in the last 15 minutes 2. Check for new error types that appeared after deploy 3. Compare latency metrics before and after deploy skills: [datadog, sentry] output: type: object properties: status: type: string enum: [healthy, degraded, failing] error_rate_change: type: number new_errors: type: array items: type: string latency_p99_ms: type: number required: [status]
rollback: name: Trigger Rollback instruction: | The deployment is failing. Create an urgent issue recommending rollback. Include the specific errors and metrics that indicate failure. skills: [github, slack]
investigate: name: Investigate Degradation instruction: | The deployment shows degraded performance. Investigate whether this is expected (e.g., cache warming) or a real problem. Check if metrics are trending back toward normal. skills: [datadog, github]
report_healthy: name: Report Healthy instruction: | Deployment looks good. Post a brief confirmation to the team channel. skills: [slack]
edges: - from: check_health to: rollback when: "Deployment status is failing" - from: check_health to: investigate when: "Deployment status is degraded" - from: check_health to: report_healthy when: "Deployment status is healthy"Validation rules
Section titled “Validation rules”SWEny validates workflows before execution. The sweny workflow validate command runs the same checks. Every rule is listed below.
| Rule | Error code | Description |
|---|---|---|
| Entry exists | MISSING_ENTRY | The entry value must match a key in nodes. |
| Valid edge sources | UNKNOWN_EDGE_SOURCE | Every edge from must reference an existing node ID. |
| Valid edge targets | UNKNOWN_EDGE_TARGET | Every edge to must reference an existing node ID. |
| No self-loops | SELF_LOOP | An edge cannot have the same from and to value. |
| All nodes reachable | UNREACHABLE_NODE | Every node must be reachable from the entry node via BFS traversal. |
| Known skills | UNKNOWN_SKILL | If a skill catalog is provided, all referenced skill IDs must exist in it. |
Validation runs in two phases. First, structural checks (entry exists, edges reference valid nodes, no self-loops). If those pass, reachability is checked via breadth-first search from the entry node.
JSON Schema
Section titled “JSON Schema”SWEny publishes a static JSON Schema for workflow files. Use it for editor autocomplete, CI validation, or integration with other tools:
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://sweny.ai/schemas/workflow.json", "title": "SWEny Workflow", "description": "A DAG workflow definition for skill-based orchestration", "type": "object", "required": ["id", "name", "nodes", "edges", "entry"], "additionalProperties": false, "properties": { "id": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1 }, "description": { "type": "string" }, "entry": { "type": "string", "minLength": 1, "description": "ID of the entry node" }, "nodes": { "type": "object", "additionalProperties": { "type": "object", "required": ["name", "instruction"], "additionalProperties": false, "properties": { "name": { "type": "string", "minLength": 1 }, "instruction": { "type": "string", "minLength": 1, "description": "What Claude should do at this node" }, "skills": { "type": "array", "items": { "type": "string" }, "description": "Skill IDs available at this node" }, "output": { "type": "object", "description": "Optional JSON Schema for structured output" } } } }, "edges": { "type": "array", "items": { "type": "object", "required": ["from", "to"], "additionalProperties": false, "properties": { "from": { "type": "string", "minLength": 1 }, "to": { "type": "string", "minLength": 1 }, "when": { "type": "string", "description": "Natural language condition — Claude evaluates at runtime" } } } } }}Reference it in your YAML editor by adding a schema comment:
# yaml-language-server: $schema=https://sweny.ai/schemas/workflow.jsonid: my-workflowname: My Workflow# ...CLI commands
Section titled “CLI commands”| Command | Description |
|---|---|
sweny workflow validate <file> | Validate a workflow YAML/JSON file. Exit 0 if valid, 1 if errors. |
sweny workflow run <file> | Execute a workflow file. |
sweny workflow run <file> --dry-run | Validate and show structure without running. |
sweny workflow run <file> --json | Output results as JSON on stdout. |
sweny workflow export triage | Print the built-in triage workflow as YAML. |
sweny workflow export implement | Print the built-in implement workflow as YAML. |
sweny workflow create <description> | Generate a workflow from a natural-language description. |
sweny workflow create <description> --json | Generate and output as JSON (non-interactive). |
sweny workflow edit <file> [instruction] | Edit a workflow file with natural-language instructions. |
sweny workflow list | List all available skills. |
sweny workflow list --json | List skills as JSON array. |