The feedback Step
Use a feedback step when you want a workflow to pause and wait for a human decision or edit before continuing. The step seeds an initial value, validates it against a schema (either inferred or explicit), and then blocks the task until feedback is submitted.
Key characteristics of a feedback step:
- Pauses execution: The graph stops at the feedback node and the task is marked as waiting for feedback. Downstream steps do not run until a response is provided.
- Seeded value: You provide an initial
value(orinitial) that is shown as the starting point. It can be a string, object, array, or any JSON payload built from templates. - Schema validation: Bosun validates both the seeded value and the submitted feedback against a JSON schema. When you do not provide a schema, Bosun infers one from the initial value.
- Structured output: Once approved, the submitted value is stored under the step id in
outputs.<id>so later steps can consume it just like any other JSON output.
Basic configuration
At minimum, a feedback step needs an id and a feedback block with a value field:
steps:
- id: draft
run: "printf '%s' 'ready' > draft.txt && cat draft.txt"
- id: review
feedback:
value:
summary: "Draft release notes are ready"
accepted: true
- id: persist
run: "printf '%s' '{{ outputs.review | json_encode() }}' > approved.json"
starts_with: draft
edges:
- from: draft
to: review
- from: review
to: persist
In this example:
- The
draftstep prepares a file and prints its contents. - The
reviewstep pauses the workflow and exposes the seededvaluefor editing. - When feedback is approved, the submitted JSON is available as
outputs.reviewand the graph continues topersist.
Bosun automatically infers a JSON Schema from the value when schema is omitted. For objects it uses the keys as required fields and disallows additional properties so the submitted feedback cannot drift into an unexpected shape.
Seeding the value with templates
value supports the same templating as other step fields. You can reference inputs, prior outputs, or loop variables and build arrays or objects dynamically.
- id: summarize_changes
structured_prompt:
prompt: "Summarise key changes in a bullet list."
returns: string_array
- id: review
feedback:
value:
summary: "Proposed release summary"
bullets: "{{ outputs.summarize_changes }}"
Under the hood, strings in value are rendered first. Bare template expressions (for example "{{ outputs.some_step }}") preserve typed JSON values such as arrays, objects, booleans, and numbers. Mixed text templates still resolve to strings. Arrays and objects are traversed recursively so you can mix literals and templates.
You can also use the legacy initial key as a synonym for value:
- id: review
feedback:
initial: '{{ outputs.summarize_changes }}'
Controlling the feedback schema
By default the step infers a schema from the seeded value. When you need more control, set schema to a primitive shortcut or a full JSON Schema, reusing the same shapes as structured_prompt.returns and Custom Schemas.
Primitive schemas
Use primitives when you only care about the top-level type:
- id: review
feedback:
value:
- feature-a
schema: string_array
Here the schema requires an array of strings. Both the seeded value and the submitted feedback must be string arrays or validation fails.
Supported primitive values are:
stringintegernumberbooleanstring_arrayinteger_arrayboolean_array
Custom schemas
For richer structures, provide a JSON Schema snippet under schema:
- id: review
feedback:
value:
summary: "ready"
accepted: true
schema:
type: object
required: [summary, accepted]
additionalProperties: false
properties:
summary:
type: string
accepted:
type: boolean
This schema is used both to validate the initial value and the final feedback payload. If validation fails, the step records a failure instead of continuing.
Branching on approval vs refusal
Feedback steps can route the graph differently depending on whether the feedback was approved or refused. Use success and failure edges from the feedback step id, just like any other step. See Task Graphs and Branching for more on edge conditions.
steps:
- id: draft
run: "printf '%s' 'ready' > draft.txt && cat draft.txt"
- id: review
feedback:
value:
- feature-a
schema: string_array
- id: approved
run: "echo approved > approved.txt"
- id: refused
run: "echo refused > refused.txt"
starts_with: draft
edges:
- from: draft
to: review
- from: review
to: approved
on: success
- from: review
to: refused
on: failure
When the feedback is approved, the step reports success and the graph follows the success edge. When the feedback is refused, the step reports failure and the graph follows the failure edge.
Error handling
Feedback steps can fail in several ways:
- Rendering the
valuetemplate raises an error. - The seeded
valuedoes not satisfy the inferred or explicit schema. - The submitted feedback payload does not satisfy the schema.
- A user explicitly refuses the feedback, signalling that the workflow should not proceed on the success path.
By default a failure stops the task. Set continue_on_error: true on the step to record the failure and keep going. The error details are stored with the step outcome and surfaced under errors.<step> so later steps can inspect what went wrong or summarise rejected feedback. See Error handling for strategies.