LangGraph Workflows: Sequential & Parallel LangGraph supports sequential and parallel workflow patterns for arranging agent steps, with sequential execution running each node one after another and parallel execution running independent nodes concurrently, according to a technical tutorial using an essay-reviewer example. The tutorial splits essay evaluation into four nodes — clarity, depth, language and grammar, and an overall feedback node — each backed by its own Pydantic schema and invoked via llm_model.with_structured_output. In the sequential pattern, the clarity check finishes before the depth check starts, and depth finishes before the language and grammar check begins. A workflow in LangGraph is a series of steps or tasks arranged to accomplish a specific goal. LangGraph supports a few fundamental patterns for arranging these steps, and in this post I’ll focus on the two simplest ones: sequential and parallel. Most real applications end up combining multiple patterns into one graph, but it helps to understand each in isolation first. I’ll use the essay reviewer here, with a slightly expanded state: python from typing import TypedDictclass EssayState TypedDict : essay: str clarity: str depth: str language and grammer: str overall score: int overall feedback: str Instead of reviewing the essay in one giant LLM call, I’m splitting the evaluation into separate nodes, one for each parameter clarity, depth, language and grammar , plus a final node that combines them into an overall score and summary. This is what actually lets us demonstrate the difference between sequential and parallel execution. Each check gets its own Pydantic schema, so every node only asks the LLM for one thing at a time. python from pydantic import BaseModel, Fieldclass ClarityCheck BaseModel : clarity: str = Field description="Feedback on the clarity of the topic in the essay" class DepthCheck BaseModel : depth: str = Field description="Feedback on the depth of the topic in the essay" class LanguageCheck BaseModel : language and grammer: str = Field description="Feedback on the language and grammar presented in the essay" class OverallEvaluation BaseModel : overall score: int = Field description="Overall score out of 10 based on all three checks", ge=0, le=10 overall feedback: str = Field description="Overall feedback summarizing the essay" And the corresponding node functions: python def check clarity state: EssayState : prompt = f"""You are an essay grading assistant. Evaluate only the clarity of the following essay, how well the ideas are expressed and easy to follow.Essay: {state "essay" } """ clarity llm = llm model.with structured output ClarityCheck response = clarity llm.invoke prompt return {"clarity": response.clarity}def check depth state: EssayState : prompt = f"""You are an essay grading assistant. Evaluate only the depth of the following essay, how well the topic is explored and substantiated. Essay: {state "essay" } """ depth llm = llm model.with structured output DepthCheck response = depth llm.invoke prompt return {"depth": response.depth}def check language state: EssayState : prompt = f"""You are an essay grading assistant. Evaluate only the language and grammar of the following essay. Essay: {state "essay" } """ language llm = llm model.with structured output LanguageCheck response = language llm.invoke prompt return {"language and grammer": response.language and grammer}def generate overall feedback state: EssayState : prompt = f"""You are an essay grading assistant. Based on the following three pieces of feedback, give an overall score out of 10 and a concise overall summary. Clarity feedback: {state "clarity" } Depth feedback: {state "depth" } Language and grammar feedback: {state "language and grammer" } """ overall llm = llm model.with structured output OverallEvaluation response = overall llm.invoke prompt return { "overall score": response.overall score, "overall feedback": response.overall feedback } With these four nodes in place, we can now wire them into a graph two different ways. This is the simplest type of workflow you can build with LangGraph. It contains steps arranged in a single sequence, executed one after another. If node A finishes, node B runs next, every time, no branching or looping involved. For the essay reviewer, running the checks sequentially means clarity finishes before depth starts, and depth finishes before language and grammar start. seq workflow = StateGraph EssayState seq workflow.add node "check clarity", check clarity seq workflow.add node "check depth", check depth seq workflow.add node "check language", check language seq workflow.add node "generate overall feedback", generate overall feedback seq workflow.add edge START, "check clarity" seq workflow.add edge "check clarity", "check depth" seq workflow.add edge "check depth", "check language" seq workflow.add edge "check language", "generate overall feedback" seq workflow.add edge "generate overall feedback", END seq workflow = seq workflow.compile Every edge here is a plain add edge, a fixed path from one node to the next. This is functionally identical to what a LangChain chain would already handle well. The three checks don’t depend on each other’s output, but running them one after another still works, it’s just slower than it needs to be. A parallel workflow lets you run multiple independent tasks at the same time, instead of one after another. This matters whenever steps don’t depend on each other’s output, running them sequentially in that case is just wasted time. In our essay reviewer, check clarity, check depth, and check language are a perfect fit for this. None of them need the output of the others, they all just need the raw essay text. So instead of chaining them, we fan them out from START and let LangGraph run them concurrently, converging on generate overall feedback once all three are done. par workflow = StateGraph EssayState par workflow.add node "check clarity", check clarity par workflow.add node "check depth", check depth par workflow.add node "check language", check language par workflow.add node "generate overall feedback", generate overall feedback par workflow.add edge START, "check clarity" par workflow.add edge START, "check depth" par workflow.add edge START, "check language" par workflow.add edge "check clarity", "generate overall feedback" par workflow.add edge "check depth", "generate overall feedback" par workflow.add edge "check language", "generate overall feedback" par workflow.add edge "generate overall feedback", END par workflow = par workflow.compile All three checks branch off START directly, and all three feed into generate overall feedback. LangGraph waits for all three to finish before running that final node, this is often called a fan out, fan in pattern. Same nodes as the sequential version, same final result, but the three independent checks now run at the same time instead of waiting on each other. The difference here isn’t in what the graph produces, both versions land on the same overall score and overall feedback. The difference is in how the work is scheduled. Sequential is simpler to reason about and is the right choice when steps genuinely depend on each other. Parallel is faster whenever steps are independent, which is exactly the case with our three essay checks. Next up, I’ll cover conditional and iterative workflows, using a different example better suited to branching and looping logic. LangGraph Workflows: Sequential & Parallel https://pub.towardsai.net/langgraph-workflows-sequential-parallel-0924548089f5 was originally published in Towards AI https://pub.towardsai.net on Medium, where people are continuing the conversation by highlighting and responding to this story.