latentSource

Agentic Workflows: Orchestrating Multi-Step AI Pipelines

Single-prompt AI is hitting its ceiling. Agentic workflows chain multiple LLM calls with tools, branching, and feedback loops to tackle complex tasks reliably.

·6 min read
Share
Agentic Workflows: Orchestrating Multi-Step AI Pipelines

A single LLM call can answer a question. Getting actual work done takes an orchestrated sequence of calls.

Why single-call LLMs aren't enough

Throw a complex task at an LLM in one prompt and you'll hit predictable walls.

The task needs external information. The model has to search a database, call an API, or read files it doesn't have in context. The task has dependencies. Step 2 depends on the output of step 1, and you can't specify both up front because you don't yet know what step 1 will produce. The task needs verification. The model writes code, but you want to run it and see if it works before moving on. A single call can't execute and validate its own output. And the task is too big for one pass. A research report means gathering sources, outlining, drafting sections, fact-checking, revising. No single prompt produces publishable quality.

These aren't model capability problems. They're architectural problems. The fix is orchestration: break the task into steps and manage the flow between them.

What agentic workflows are

An agentic workflow is a system where an LLM runs in a loop. Observe the current state, decide what to do next, take an action, observe the result, and repeat until the task is done.

The minimal agent loop:

while not task_complete: # 1. Observe: gather current state and available information observation = get_current_state() # 2. Reason: LLM decides what to do next action = llm.decide( task=original_task, history=action_history, observation=observation, available_tools=tools ) # 3. Act: execute the chosen action result = execute(action) # 4. Update: record what happened action_history.append((action, result)) # 5. Check: is the task done? task_complete = llm.evaluate_completion(action_history)

Drawn as a loop, that's:

That looks simple. The hard part is the patterns you use inside the loop and how you handle the inevitable failures.

Key patterns

ReAct (reasoning + acting)

The most common pattern. The model alternates between thinking (reasoning about what to do) and acting (calling tools). Each reasoning step is explicit in the output, which makes the agent's decisions transparent and debuggable.

Thought: I need to find the quarterly revenue for Acme Corp. Let me search the database.
Action: search_database(query="Acme Corp quarterly revenue 2025")
Observation: [Results: Q1: $12M, Q2: $14M, Q3: $13M, Q4: $16M]
Thought: I have all four quarters. Total annual revenue is $55M. Now I need to compare
         with the previous year.
Action: search_database(query="Acme Corp quarterly revenue 2024")
Observation: [Results: Q1: $10M, Q2: $11M, Q3: $11M, Q4: $13M]
Thought: 2024 total was $45M. Year-over-year growth is 22.2%. I can now write the summary.
Action: write_report(content="...")

That explicit reasoning chain is both the strength and the overhead. It costs tokens to think out loud, but you get auditable decision traces in return. Here it is for real — recorded ReAct runs of a movie-clip agent, replayed with the actual thinking, tool calls, and results:

Each movie query loops through web search, YouTube search, timestamp location, and clip building before finishing; the out-of-scope run (a song) refuses on the first step. This is the ReAct pattern doing exactly what the trace above describes, on live tools.

Plan-and-execute

Instead of deciding one step at a time, the agent first generates a complete plan, then executes each step. This works better for tasks where the overall structure is predictable and you want to minimize model calls.

# Phase 1: Planning plan = llm.generate_plan(task) # Output: ["1. Fetch data from API", "2. Clean and transform", # "3. Run analysis", "4. Generate charts", "5. Write report"] # Phase 2: Execution for step in plan: result = execute_step(step, context=previous_results) if needs_replanning(result): plan = llm.replan(task, completed_steps, result)

Replanning is the part most people skip and then regret. Rigid plans break on first contact with reality. A good plan-and-execute agent detects when a step fails or produces unexpected output and regenerates the rest of the plan.

Reflection

After generating output, a second LLM call (or the same model with a different prompt) critiques the result. The critique feeds back into a revision step.

draft = llm.generate(task) for i in range(max_iterations): critique = llm.critique(draft, criteria=quality_criteria) if critique.score >= threshold: break draft = llm.revise(draft, critique.feedback)

This pattern is surprisingly effective for writing tasks, code generation, and any output where quality can be assessed. Two passes with reflection consistently beat a single pass, even when the single pass uses a more detailed prompt.

Tool chaining

The agent orchestrates multiple tools in sequence, where each tool's output feeds the next. Unlike plain function calling, the agent decides at runtime which tools to chain and in what order.

Task: "Summarize the top 3 Hacker News stories about AI"
1. web_search("Hacker News top stories AI") → URLs
2. fetch_page(url_1) → article text
3. fetch_page(url_2) → article text
4. fetch_page(url_3) → article text
5. summarize(articles) → final summary

Frameworks

A few frameworks package these patterns into reusable components.

LangGraph models workflows as directed graphs with state. Nodes are processing steps (LLM calls, tool use, conditional logic). Edges define flow. State is passed between nodes and persisted, which lets you build human-in-the-loop interruption and long-running workflows.

CrewAI defines agents as roles with backstories, goals, and tools. Multiple agents collaborate with defined delegation patterns. It's good for simulating team workflows like researcher, writer, editor.

AutoGen is Microsoft's framework for multi-agent conversations. Agents communicate through messages, which gets you group-chat-style collaboration on complex tasks.

Anthropic's agent SDK is a lightweight Python SDK focused on the core agent loop with tool use, handoffs between agents, and guardrails. Minimal abstraction, maximum control.

The right choice depends on your complexity. For straightforward tool-using agents, a bare agent loop (or a lightweight SDK) is usually enough. For complex multi-agent workflows with branching and persistence, LangGraph or similar graph-based frameworks earn their weight.

Error handling and retries

Agentic systems fail in ways single LLM calls don't.

Tools fail. APIs time out, databases return errors, file operations fail. Every tool call needs try/catch with a meaningful error message fed back to the agent. Infinite loops happen. The agent repeats the same action hoping for a different result. Set maximum iteration limits and detect repetition patterns. Context overflow happens. Long-running agents accumulate history that blows past context limits, so you need summarization of older history or a sliding-window approach. Cost runaway happens. An agent that doesn't converge keeps burning API credits, so set a budget limit per task.

# Practical error handling in an agent loop MAX_ITERATIONS = 20 MAX_COST = 5.00 # dollars for i in range(MAX_ITERATIONS): if total_cost > MAX_COST: return fallback_response("Budget exceeded") try: action = llm.decide(state) result = execute(action, timeout=30) except ToolError as e: state.add_observation(f"Tool failed: {e}. Try an alternative approach.") continue except TimeoutError: state.add_observation("Action timed out. Simplify the approach.") continue state.update(action, result) if is_complete(state): return state.final_output

Evaluation and observability

You can't improve what you can't measure. Agentic workflows need a few things.

Tracing. Every LLM call, tool invocation, and decision point should be logged with timestamps, inputs, outputs, and token counts. LangSmith, Arize, and Braintrust handle this. Step-level evaluation. Don't just evaluate the final output. Evaluate intermediate steps. Did the agent pick the right tool? Did it read the tool's output correctly? Cost tracking per task. Know exactly how many tokens each workflow consumes, so you can find expensive patterns. Regression testing. Build a test suite of tasks with expected behaviors and run it whenever you change prompts, tools, or orchestration logic.

Real-world examples

A research agent. Given a topic, the agent searches the web, reads multiple sources, identifies key findings, cross-references claims, and produces a structured report with citations. That's 10 to 30 tool calls across search, fetch, and analysis steps.

A code reviewer. The agent reads a pull request diff, picks the files to review, checks for common patterns (security issues, performance problems, style violations), runs the relevant tests, and produces a structured review with inline comments. It integrates with Git, test runners, and static analysis tools.

Customer support triage. The agent reads an incoming ticket, searches the knowledge base for relevant articles, checks the customer's account status and history, classifies the issue, and either auto-responds or routes to the right human team with a summary attached.

When it's overkill

Not everything needs an agent. If a task can be done with a single well-crafted prompt, adding an orchestration layer just buys you latency, cost, and new failure modes for no benefit.

Use agentic workflows when the task genuinely needs multiple steps with external tool use, when the steps have dependencies you can't resolve in a single call, when the task benefits from self-correction through reflection, or when you need human-in-the-loop approval at intermediate steps.

Stick with single calls when the task is well-defined and self-contained, when all the necessary context fits in one prompt, when latency matters more than quality (agent loops are slow), and when the failure modes of multi-step orchestration aren't worth the quality improvement.

The overhead of agentic systems is real. But for complex multi-step tasks that have to interact with the outside world, they're the only architecture that actually works.