##  [Editorial workflows with reduce and generate in Nushell](/articles/editorial-workflows-with-reduce-and-generate-in-nushell)

    *Submitted by Lennart on Mon, 2 Feb 2026 - 13:41*

For a simple editorial workflow, I would almost certainly choose **`reduce`**, but the "cool" choice (and the one that feels more like an autonomous agent) is **`generate`**.

Here is how to decide based on what your "workflow" actually looks like:

### Option 1: Use `reduce` (The "Linear Polisher")

Use `reduce` if you have a **fixed set of operations** you want to run on a piece of text (e.g., "Fix Grammar" "Shorten" "Change Tone").

In this scenario, you are "folding" a list of instructions over your text.

```
let tasks = ["fix grammar", "make it sound more professional", "convert to markdown"]
let original_text = "i is writing a nushell script for agents"

let final_draft = ($tasks | reduce -f $original_text {|task, current_text|
    # Each step takes the output of the previous LLM call
    call-brain $"Apply this edit: ($task)" $current_text
})

```

- **Best for:** Consistency. You know exactly how many steps are involved.
- **Logic:** .

### Option 2: Use `generate` (The "Iterative Refiner")

Use `generate` if you want the agent to **keep editing until it’s happy**. `generate` creates a stream, which is perfect for an "Editorial Loop" where the agent looks at its own work and decides if it needs another pass.

```
# generate {|state| {out: <value_to_emit>, next: <next_state>} } <initial_state>
let initial_state = { text: "The draft...", count: 0, done: false }

let editorial_history = (generate {|state|
    if $state.done or $state.count > 3 { return null } # Exit condition

    let feedback = (call-brain "Review this text. Is it perfect? Respond with 'YES' or feedback." $state.text)

    if ($feedback | str contains "YES") {
        {out: $state.text, next: {done: true}}
    } else {
        let new_text = (call-brain $"Apply this feedback: ($feedback)" $state.text)
        {out: $new_text, next: {text: $new_text, count: ($state.count + 1), done: false}}
    }
} $initial_state)

let final_result = ($editorial_history | last)

```

- **Best for:** Quality. It mimics a human editor who sends back a draft multiple times.
- **Logic:** Start Is it good? No? Edit and Repeat.

### Comparison Table

| Feature | `reduce` | `generate` |
|---|---|---|
| **Flow** | Deterministic (1 2 3) | Dynamic (Loop until done) |
| **Termination** | Ends when the list of tasks is empty | Ends when a condition is met (or limit reached) |
| **Visibility** | Harder to see intermediate steps mid-stream | Emits every version as a stream member (great for logging) |
| **Use Case** | Batch processing | Self-correcting agents |

### My Recommendation

If you are building an **Agent System** with `xs`, use **`generate`**.

Why? Because `generate` allows the LLM to decide the "next state." It can output the current draft to an `xs` stream at every iteration, giving you a perfect audit trail of how the "editorial brain" evolved the text.

**Would you like me to show you how to wrap that `generate` loop so it writes every "revision" to an `xs` stream in real-time?**

Be sure to stay tuned if you want to learn more about xs (cross.stream), event sourcing and nushell with AI and LLMs.