Multi-Step Conversation Design: Structuring Complex Workflows with Claude
AI generated
Claude
>_
Claude AI · Prompt Engineering · Conversation Design
Multi-Step Conversation Design
structuring complex workflows with Claude

A complex business process rarely fits into a single request to Claude. Multi-step conversation design breaks a large task down into traceable stages with clear state, so every step can be checked, corrected and repeated, instead of hoping for one perfect answer.

17 min read State Management · Control Flow · Multi-Turn Claude API · Python · Workflow Design

1. Why one request is not enough for complex tasks

A single prompt works well for clearly scoped tasks with an unambiguous answer. But once a process requires multiple decisions, intermediate results or external data lookups, a single request quickly reaches its limits. A multi-step conversation design breaks the overall task down into smaller, clearly defined stages that each build on the result of the previous stage.

The advantage of a multi-step conversation design lies not only in better answer quality per step, but above all in traceability: every intermediate step can be logged, validated and, if needed, repeated in isolation without restarting the entire process. With a monolithic prompt meant to handle everything at once, an error in the middle of the process is hard to locate and even harder to fix in a targeted way.

This article shows how state management, message history and control flow are concretely built in a multi-step conversation design, which patterns have proven themselves for typical workflows, and where human-in-the-loop checks make sense.

2. State management: what persists between steps

The Claude API itself is stateless: every request contains the entire history so far, which the application must manage itself. A multi-step conversation design therefore needs a clear separation between the conversation history sent to Claude and the application state maintained outside the conversation, for example which stage of the process the flow is currently in.

A proven pattern is an explicit state object that, alongside the message history, also holds structured intermediate results: the current step, data already collected, and open decisions. This state object is updated at every step and can be persisted and later resumed after a crash or interruption, without the conversation having to start over from scratch.


from dataclasses import dataclass, field
from enum import Enum

class WorkflowStep(Enum):
    GATHER_REQUIREMENTS = "gather_requirements"
    DRAFT_SOLUTION = "draft_solution"
    REVIEW = "review"
    FINALIZE = "finalize"

@dataclass
class ConversationState:
    """Explicit application state, separate from the raw message history."""
    current_step: WorkflowStep = WorkflowStep.GATHER_REQUIREMENTS
    collected_data: dict = field(default_factory=dict)
    messages: list = field(default_factory=list)
    open_questions: list[str] = field(default_factory=list)

    def advance(self, next_step: WorkflowStep) -> None:
        """Move the workflow forward and log the transition."""
        print(f"Transitioning: {self.current_step.value} -> {next_step.value}")
        self.current_step = next_step

    def to_dict(self) -> dict:
        """Serialize state for persistence between sessions."""
        return {
            "current_step": self.current_step.value,
            "collected_data": self.collected_data,
            "messages": self.messages,
            "open_questions": self.open_questions,
        }

3. Message history as the conversation's memory

The message history is the actual memory of a multi-step conversation design: every user message and every Claude response is appended to the list and sent in full with the next request. Without this history, Claude would have no memory whatsoever of previous decisions, gathered information, or already rejected alternatives at each step.

A common mistake is letting the message history grow unchecked without reviewing which parts are actually relevant to the current step. In a multi-step conversation design with many stages, targeted curation pays off: intermediate steps no longer relevant to the current decision can be compressed or replaced with a short summary to keep the context lean and focused without losing important information.

4. Controlling control flow between stages

Control flow determines which step runs next, based on the result of the previous step. A simple but effective pattern uses tool use so that Claude itself signals which next step makes sense, instead of the application having to reconstruct that decision from text patterns. A tool advance_workflow with an enum field for the next step makes this decision explicit and machine readable.

For processes with clear, predictable stages, a linear control flow is suitable, where the application itself dictates the order of steps and Claude only handles the substantive work within each stage. For processes with variable order, for example a diagnosis where different next steps make sense depending on the result, a branched control flow is suitable, where Claude itself determines the next step via tool use.


import anthropic

client = anthropic.Anthropic()

advance_tool = {
    "name": "advance_workflow",
    "description": "Signal which workflow step should run next",
    "input_schema": {
        "type": "object",
        "properties": {
            "next_step": {
                "type": "string",
                "enum": ["gather_requirements", "draft_solution", "review", "finalize"]
            },
            "reasoning": {"type": "string", "description": "Why this step is next"}
        },
        "required": ["next_step", "reasoning"]
    }
}

def run_step(state: ConversationState) -> ConversationState:
    """Execute one workflow step and let Claude decide the next transition."""
    state.messages.append({"role": "user", "content": build_step_prompt(state)})

    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=2048,
        tools=[advance_tool],
        tool_choice={"type": "tool", "name": "advance_workflow"},
        messages=state.messages,
    )

    decision = next(b.input for b in response.content if b.type == "tool_use")
    state.messages.append({"role": "assistant", "content": response.content})
    state.advance(WorkflowStep(decision["next_step"]))
    return state

5. Intermediate checks and human-in-the-loop

Not every stage of a multi-step conversation design should run fully automated. For processes with financial, legal or safety related consequences, explicit human approval before the next step makes sense. The design should model such checkpoints as their own stage, where the process pauses and waits for external confirmation, instead of squeezing the check into an existing stage as a side effect.

A proven pattern: at the end of a stage, Claude generates a compact summary of the decisions made so far and the proposed next steps, which is presented to a human for approval. Only after explicit confirmation does the process continue, with the confirmation as additional context for the next Claude call. This intermediate check prevents errors from an early stage from silently propagating into subsequent stages of the multi-step conversation design.


CRITICAL_STEPS = {WorkflowStep.FINALIZE}

def request_human_approval(state: ConversationState, proposed_summary: str) -> bool:
    """Pause the workflow and wait for an explicit external confirmation."""
    print(f"--- Approval required before step: {state.current_step.value} ---")
    print(proposed_summary)
    decision = input("Approve and continue? [y/N]: ").strip().lower()
    return decision == "y"

def run_step_with_gate(state: ConversationState) -> ConversationState:
    """Run a step, and if it is critical, gate it on human approval."""
    state = run_step(state)  # from the control flow example above

    if state.current_step in CRITICAL_STEPS:
        summary = summarize_state_for_human(state)  # application specific
        if not request_human_approval(state, summary):
            raise RuntimeError("Workflow halted: human approval declined")

    return state

6. Error handling across multiple steps

Errors in a multi-step conversation design can occur at any stage: a tool call fails, an external API does not respond, or Claude returns an answer that does not match the expected format. Without explicit error handling, an error from an early stage silently propagates into all subsequent steps and leads to a final result built on a faulty foundation.

Each stage should therefore run its own validation before passing on to the next stage, and offer a defined fallback in case of failure: either a retry of the current stage with enriched context, or a controlled rollback to an earlier, known good stage. A state object persisted after every successful stage makes this rollback technically simple, because the last valid state is always available.


import copy

checkpoint_history: list[ConversationState] = []

def persist_checkpoint(state: ConversationState) -> None:
    """Save a deep copy after every successful step, for rollback on failure."""
    checkpoint_history.append(copy.deepcopy(state))

def run_step_with_recovery(state: ConversationState, max_retries: int = 1) -> ConversationState:
    """Retry the current step once, then roll back to the last good checkpoint."""
    for attempt in range(max_retries + 1):
        try:
            new_state = run_step(state)
            persist_checkpoint(new_state)
            return new_state
        except Exception as error:
            print(f"Step failed on attempt {attempt}: {error}")
            if attempt == max_retries:
                if not checkpoint_history:
                    raise
                print("Rolling back to last known good checkpoint.")
                return checkpoint_history[-1]
    return state

7. Context length and summarization strategies

As the number of stages grows, so does the message history, and eventually a multi-step conversation design approaches the limits of the context window. Instead of dragging the entire history along unchanged, a targeted summarization strategy pays off: completed stages that are no longer decisive for the further course are replaced by a compact summary generated by Claude itself.

This summary should contain the essential decisions and data, but not the full wording of the original interaction. A practical approach lets Claude generate a structured summary in JSON format at the end of each stage, which is then used instead of the detailed messages of that stage in the further course. This keeps the context manageable even in long multi-step conversation designs.


def compress_completed_stage(state: ConversationState, stage_messages: list) -> None:
    """Replace verbose messages of a finished stage with a compact summary."""
    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=300,
        messages=stage_messages + [{
            "role": "user",
            "content": "Summarize the key decisions and data from this stage as compact JSON."
        }]
    )
    summary_text = response.content[0].text

    # Drop the verbose exchange, keep only the compact summary in history
    state.messages = [m for m in state.messages if m not in stage_messages]
    state.messages.append({"role": "user", "content": f"Prior stage summary: {summary_text}"})

8. Proven conversation patterns for typical workflows

For recurring use cases, a few patterns have established themselves for multi-step conversation designs. The "gather, draft, review" pattern is suitable for creation processes: first requirements are gathered, then a draft is created, then checked against the requirements, with optional feedback loop to the gathering phase if gaps appear. The "plan then execute" pattern strictly separates a planning phase, where Claude outlines the steps up front, from the execution phase, where each planned step is worked through individually.

A third pattern, the "iterative refinement" design, is suitable for creative or analytical tasks where a first draft is improved step by step: each stage receives targeted feedback on the previous version and produces an improved version, until a stopping criterion is reached. All three patterns share the basic idea of a multi-step conversation design: clearly delimited stages with explicit state instead of a single, overloaded request.

9. Comparing designs: linear, branched, iterative

The choice of the right conversation design depends on the structure of the underlying process. The following table compares the three common base designs.

Design Control flow Suitable for Complexity
Linear Application dictates fixed order Predictable processes with fixed stages Low
Branched Claude determines next step via tool use Diagnosis, variable decision paths Medium
Iterative Repeated refinement until stopping criterion Creative and analytical improvement tasks Medium to high

In practice, many real applications combine elements of all three designs: a rough linear framework with individual branched decision points and an iterative refinement loop within a single stage. What matters is choosing the design deliberately, instead of letting it emerge implicitly from a growing number of special cases in the prompt.

Mironsoft

Claude workflow design and agentic automation

Automate complex processes reliably with Claude?

We design multi-step conversation designs with clear state management, control flow and human-in-the-loop checkpoints that automate your complex business processes in a traceable way.

Workflow analysis

Breaking down existing processes into clearly delimited stages

State management

Persistent state objects for robust, resumable processes

Human-in-the-loop

Checkpoints for critical decisions in the automation process

10. Summary

Multi-step conversation design breaks complex tasks down into traceable stages with explicit state, instead of a single overloaded request. A separate state object holds process progress, collected data and open questions independently of the raw message history. Control flow can be dictated linearly by the application or determined by Claude itself via tool use, depending on how predictable the process is.

Human-in-the-loop checkpoints before critical decisions, robust error handling with defined rollback points, and summarization strategies against growing context length are the three most important building blocks for production ready multi-step conversation designs. Anyone who plans for these building blocks from the start builds workflows that stay traceable and maintainable even for longer, more complex processes.

Multi-Step Conversation Design: Key Takeaways

Separate state

Explicitly separate application state from the raw message history and persist it.

Choose control flow deliberately

Linear for predictable processes, branched via tool use for variable decision paths.

Involve humans

Critical stages with explicit approval instead of a fully automated run.

Curate context

Summarize completed stages instead of letting the full history grow without bound.

11. FAQ: Multi-Step Conversation Design

1What is a multi-step conversation design?
Breaking a complex task into several stages that each build on the previous result, instead of a single request.
2Why isn't one request enough for complex processes?
Becomes unmanageable, errors in the middle are hard to locate. Stages make the process traceable.
3Difference between application state and message history?
Message history goes to Claude, application state holds structured extra info outside the conversation.
4How do you control flow?
Linear, dictated by the application, or branched via tool use determined by Claude.
5When to involve humans?
For financial, legal or safety related consequences, explicit approval instead of full automation.
6Errors in early stages?
Each stage validates before passing on, retry or rollback to known good state on failure.
7Context getting too long, what now?
Replace completed stages with compact summaries instead of dragging the full history along.
8What conversation patterns exist?
Gather-draft-review, plan-then-execute, and iterative refinement for different process types.
9Can designs be combined?
Yes, linear framework with branched decision points and iterative loops within individual stages.
10Is tool use strictly required for control flow?
Not for purely linear processes, but far more reliable than text interpretation for branched flows.