Skip to main content

Fold an Agent in Nushell

Submitted by Lennart on
reduce based agent

In agent.nu, we explored using generate to build an LLM agent. That pattern is an unfold: starting from a seed, you grow a stream of values. It's perfect for UI-centric agents where you want to stream "thoughts" to the user as they happen.

You can read more about it here: A very simple and slightly better way to create an AI agent using nushell generate instead of a normal agent loop | docujAI

But what if you view an agent's task as a single transformation of a prompt into a completed conversation history? That's a fold.

The reduce Pattern

Nushell's reduce command (often called fold in other functional languages) is usually used for math (summing a list) or merging records. However, it's also a powerful way to manage stateful loops with a fixed maximum depth.

In agent_reduce.nu, we treat the conversation history as the accumulator:

1..$max_turns | reduce --fold $initial_history {|turn, history|
    let last_msg = $history | last
    
    # Early exit logic
    if ($last_msg.role == "model" and (not_calling_tools $last_msg)) {
        $history 
    } else {
        let next_step = call_llm $history
        $history | append $next_step
    }
}

Why use reduce?

1. The Result is the Context

While generate returns a stream of messages, reduce returns the final state. If you are building a tool that needs the complete transcript to save to a database or pass to another function, reduce gives it to you in one clean package.

2. Built-in Safety Rails

Agents can occasionally "hallucinate" loops or get stuck in tool-call cycles. By folding over a range like 1..10, you get a hard cap on iterations for free. You don't need to manually increment a counter or check a depth variable; the sequence provides the limit.

3. Clearer Intent for Batch Processing

If your agent is running as a background job (e.g., summarizing 100 documents), you don't care about the intermediate stream. You care about the final history. reduce makes this intent explicit: "Take these potential turns and condense them into a result."

Which one should you choose?

  • Use generate if you are building an interactive agent (CLI, Chatbot) where the process is as important as the result.
  • Use reduce if you are building a data pipeline agent where the agent is just a complex function that maps inputs to outputs.

Nushell gives you the choice. Whether you're unfolding a stream or folding a history, you can keep your AI logic functional, immutable, and simple.