Articles

Implementation

Do You Need an Agent Framework? Direct Code vs. LangChain, LangGraph, and Microsoft Agent Framework

An agent framework earns its place only when it solves an execution, state or recovery problem that your team would otherwise need to build and maintain.

October 28, 202615 min read
A person compares a printed financial document with an online form on a laptop.
Photo by SumUp on Unsplash

An invoice exception exposes the real framework decision

An invoice arrives with a purchase-order mismatch and an ambiguous description. A model classifies the discrepancy and proposes a reason code. Application code reads the supplier and purchase-order records, writes the recommendation to the finance system and decides whether the case needs review.

A person must approve any action that could release or change a payment. After approval, the application calls the payment system. That call times out. The team can see that it sent a request, but it cannot yet tell whether the payment system accepted it.

This is where a seemingly simple AI feature becomes an operating-system decision. The important question is not whether a framework can connect a model to a tool. It is whether the chosen design can preserve the right state, bind approval to the right action, reveal what happened and recover without repeating a financial effect.

Start with direct deterministic application code. Keep the sequence in ordinary functions, use the model only for the classification that genuinely needs it, validate the result and route uncertain cases to a manual queue. If rules and manual review can handle the exception economically, the simpler non-AI route may be better still.

Add an agent framework only when its model loop, interruption, persistence or orchestration abstractions solve requirements that the team would otherwise have to build and maintain. That principle keeps the choice tied to the workflow rather than to a framework demonstration.

Fix the release context before comparing capabilities

This comparison uses the official documentation available in October 2026. For the LangChain family, that means the v1-era Python documentation and changelog, together with the LangGraph v1 JavaScript release context. For Microsoft Agent Framework, the specific Python release context is 1.23.0, supported by the 2026 significant changes guide.

That context matters because a product name does not establish identical behavior across languages, packages or integrations. The LangGraph changelog, for example, identifies some timeout and error-handler capabilities as Python-only while retry policies continue in Python and TypeScript. Microsoft documents its Go framework as public preview, with several capabilities not yet available, and explains that packages installed through its Python meta-package can have different lifecycle labels.

The comparison therefore relies on documented product roles rather than assuming universal parity:

  • LangChain documents create_agent as a configurable agent harness assembled from a model, tools, prompts and middleware.

  • LangGraph documents a lower-level orchestration framework for mixing deterministic and model-driven steps, with persistence and human-in-the-loop support.

  • Microsoft Agent Framework documents agents, an opinionated harness, and functional or graph-based workflows with explicit execution paths.

Those are documented capabilities. The recommendations below are architectural judgments about when those capabilities justify their operational cost.

Ask four questions before choosing any framework

Collect evidence from one bounded workflow before comparing products. Four questions expose most of the meaningful differences.

1. How many decisions are genuinely uncertain?

Separate model judgment from ordinary business logic. In the invoice example, interpreting an ambiguous description might justify a model. Checking whether the invoice total exceeds an approval threshold does not. Neither does looking up whether a supplier is blocked.

Mark each model decision, the inputs it may use and the range of outputs the application will accept. A single classification followed by deterministic handling rarely demands elaborate orchestration. Several model-directed choices about which tool to call, what information to gather and when to stop may justify a harness.

2. Must execution pause and resume later?

A synchronous request that finishes in seconds has different state needs from a workflow waiting hours for finance approval. Record where execution can stop, what event restarts it and how the application will identify the exact case being resumed.

If pausing is merely “write a pending status and process the approval event later,” direct code may remain sufficient. If many long-running branches need checkpointed execution and controlled resumption, a workflow runtime becomes more attractive.

3. Which external effects are safe to repeat?

Inventory every write and external call: updating the invoice record, creating an approval task, releasing a payment and sending a notification. Classify each as repeatable, conditionally repeatable or unsafe to repeat without verification.

This question often matters more than the number of model calls. A short workflow with one payment effect can demand stricter recovery design than a long read-only research task.

4. Who owns recovery?

Name the person or team that decides what happens after a timeout, invalid model output, rejected approval or partial business-system failure. Also identify what evidence they will receive.

A framework may preserve execution state or provide traces. It does not decide whether a disputed invoice should be paid, reversed, held or escalated. That remains a business and application responsibility.

Choose where sequencing and model control should live

The four options place control in different locations.

Direct application code

Direct code keeps the sequence visible in the application: load invoice, call classifier, validate response, write recommendation, request approval and dispatch an approved action. Branching is expressed through normal language constructs, jobs and database records.

This is strongest when the workflow is bounded and mostly deterministic. The model can recommend a classification without choosing arbitrary tools or rearranging the process. The limit appears when the team starts building its own general-purpose state machine, resumable scheduler or agent loop.

LangChain

LangChain’s documented role is a configurable agent harness. The model operates inside a loop with selected tools, prompts and middleware. In the invoice workflow, this could help when the model must decide whether to retrieve supplier history, request more evidence or call a classification tool before returning a recommendation.

The harness reduces the need to assemble a model-and-tool loop from scratch, but it also moves some sequencing into model-directed behavior. It is less compelling when the desired sequence is already known and should remain explicit application logic.

LangGraph

LangGraph places orchestration in a graph of state, nodes and edges. Its documented model allows deterministic steps and LLM-driven steps to coexist. The invoice classification can be a model node, threshold checks can remain deterministic nodes, and approval can be represented as an interruption in the execution path.

This is useful when the graph itself expresses a real operating requirement: multiple branches, durable resumption or deliberate recovery routes. For a short linear request, the graph can add structure without removing meaningful complexity.

Microsoft Agent Framework

Microsoft Agent Framework presents both agent abstractions and explicit workflows. Its overview recommends agents for open-ended or conversational work and workflows for well-defined steps requiring control over execution order. It also explicitly advises using a function when a function is sufficient.

For the invoice case, a contained agent could perform model-and-tool work, while a workflow could coordinate deterministic functions, approvals and agents. The integrated model is attractive when it fits the team’s Microsoft-oriented architecture and supported language. It is unnecessary if ordinary application functions already express the process clearly.

Decide what must survive a pause or restart

For the invoice workflow, durable state is more than conversation history. It includes:

  • the invoice and exception identifiers;

  • the source data or version used for classification;

  • the proposed reason and action;

  • the approval request, allowed decisions and approver identity;

  • the current execution position;

  • a record of completed external effects.

With direct code, the application owns all of this. A database row can represent a state machine, and a job or event can continue work after approval. This is often enough when there are few states and transitions.

LangChain agents are built on LangGraph according to the official overview, which makes persistence and human-in-the-loop facilities available beneath the higher-level harness. The application still has to choose and configure its persistence boundary and decide which business data is authoritative.

LangGraph makes checkpointed state and interruptions central to its orchestration model. That can reduce custom machinery for a process that genuinely needs to pause and continue. A checkpoint is execution state, however, not automatically the finance system’s authoritative invoice or payment record.

Microsoft Agent Framework documents sessions for agent state and workflows for explicit paths, including long-running and human-in-the-loop scenarios. Its Python changes also show why approval binding matters: local approval responses must correspond to a pending request in the same authoritative session. The application must preserve that association and must not treat free-form transcript text as approval authority.

Across all four options, store business facts in the system that owns them. Persist enough execution context to resume or reconstruct the run, but bind every approval to the specific action, arguments and business object it authorizes.

Keep permissions and payment effects outside the model’s discretion

A model can propose an action. It should not create its own authority to perform it. The surrounding application decides which tools exist, which arguments are accepted, which credentials are used and which calls require approval.

In direct code, keep the classifier separate from the payment client. Validate the model’s output against an allowed schema, calculate approval requirements deterministically and call the payment service only from an authorized application path.

In LangChain, expose only the tools needed for the task and enforce policy in application code or middleware rather than relying on prompt instructions. A tool wrapper should verify business identifiers, caller context and approval before it reaches the finance system.

In LangGraph, deterministic nodes can enforce those checks before an effect node runs. Graph structure makes the control point visible, but it does not make the external call repeatable.

Microsoft’s documentation places authorization boundaries on the application. Its Python 1.23.0 changes require an explicit authorization ownership mode for AG-UI endpoints and warn that authentication alone does not scope sessions, checkpoints, detached runs or approval state. That is a useful design lesson even outside that endpoint: authorization context must be bound to persisted execution state.

For a payment-affecting call, use a stable business operation identifier where the external system supports it. Record the intended effect before dispatch, record the provider’s response when received and query authoritative status after an ambiguous timeout. If the local database uses stricter PostgreSQL isolation, the application must still be prepared to retry transactions after serialization failures, as described in the PostgreSQL transaction-isolation documentation. Such a transaction protects database work within its boundary, not a remote payment call.

Make failures inspectable and assign recovery before launch

The goal of observability is not merely to collect a model transcript. An operator handling the timed-out invoice needs evidence that answers four questions:

  1. What was the last confirmed workflow step?

  2. Which proposal did the person approve, and under which identity?

  3. Did the payment effect occur in the authoritative system?

  4. Which documented recovery action is available now?

With direct code, the application must emit structured logs and metrics, correlate them with the invoice and effect identifiers, and expose failed cases through an operational queue or equivalent interface.

LangChain and LangGraph documentation points to LangSmith for tracing requests, tool calls and state transitions. LangSmith is a separately configured observability offering, not an automatic substitute for business monitoring. Framework traces can help explain the execution path, while the application still needs alerts, exception queues and reconciliation against finance systems.

LangGraph’s persisted execution state can help identify where orchestration stopped. Its Python changelog also documents controls such as per-node timeouts, retry handoff and node-level error handlers in the applicable releases. These controls shape execution, but the business recovery route still needs to be designed.

The Microsoft Agent Framework harness documentation describes OpenTelemetry observability as part of its harness composition, while the broader framework documents workflows and state-management facilities. Operators still need application-level signals that connect technical events to an invoice, approval and payment status.

Assign three responsibilities explicitly: who responds to the alert, who reconciles external effects and who decides the business outcome. If one person owns all three in a small team, record that. Ambiguous ownership is not improved by adding a framework.

For more detail on making operational signals useful, see monitoring the AI operating layer.

Account for the abstraction you will have to maintain

Every option creates maintenance work. The relevant comparison is not “framework versus no maintenance.” It is framework maintenance versus the orchestration code the team would otherwise own.

Direct code has the smallest conceptual surface when the workflow is short and deterministic. The team tests ordinary branches, model-output validation, permissions and failure handling using its existing application practices. Its limit is the accumulated cost of custom pause, resume, branching and inspection mechanisms.

LangChain has a strong case when a contained agent loop is the central requirement. It supplies a configurable harness and integrations instead of requiring the team to assemble those pieces independently. The team must still test tool selection, middleware, provider behavior and model-dependent paths. It must also track changes across the framework and relevant integrations. The Python changelog illustrates this burden with changes to streaming events, human-in-the-loop behavior and MCP packaging.

LangGraph has a strong case when explicit durable orchestration is itself valuable. The graph can make branching, interruption and model boundaries visible. The corresponding cost is learning and testing graph state, checkpoint behavior, replay, persistence compatibility and recovery routes. Persisted-state changes require particular care because an application may not be able to switch representations or roll versions back safely after new records are written.

Microsoft Agent Framework has a strong case when its agents, harness and workflow model fit the team’s language and platform direction. Its practical limits include language differences, mixed package lifecycle labels and upgrade requirements that can affect persisted state, authorization scope and protocol integrations. The Python 1.23.0 guide, for example, documents breaking changes around MCP lifecycle and authorization ownership. Evaluate the exact packages you plan to adopt rather than treating the umbrella framework name as one maturity level.

Team familiarity changes the balance. A framework that maps naturally to the team’s debugging and deployment practices can reduce custom work. An unfamiliar runtime introduced for a two-step workflow may increase the time needed to understand failures. Whichever option you choose, test deterministic branches, model-output boundaries, approval binding, duplicate delivery and ambiguous external-call outcomes.

If the design has grown beyond a simple integration, Workflow & Agent Implementation is the relevant service area for connecting the workflow to existing systems and operating constraints.

Match the requirement to the simplest adequate option

Use the table as a routing decision, not as a product ranking.

Requirement patternSimplest adequate optionStrongest reason to choose itResponsibilities that remainReconsider when
One or a few model decisions inside a known sequence; pauses can be represented as ordinary business statesDirect application codeKeeps sequencing, permissions and exceptions explicit without adding a framework runtimePersist business state, validate outputs, bind approvals, record effects, monitor and recoverThe team is repeatedly building general pause, resume, branching or replay machinery
A contained task needs a configurable model-and-tool loop, but the surrounding business process remains application-controlledLangChainProvides a higher-level agent harness for models, tools, prompts and middlewareLimit tools, enforce authorization, persist authoritative business facts and reconcile effectsThe loop becomes a multi-stage workflow whose execution path and resumable state need explicit control
The workflow needs explicit deterministic and model-driven nodes, durable state, interruption and controlled resumptionLangGraphMakes stateful orchestration and human interruption first-class parts of the designDefine state semantics, configure persistence, secure tools, protect external effects and own business recoveryThe organization needs a different language or ecosystem alignment, or the graph adds more complexity than it removes
The team wants agents and explicit workflows within Microsoft Agent Framework, and its supported languages and package lifecycle fit the environmentMicrosoft Agent FrameworkCombines agent, harness and workflow concepts with documented state, middleware and telemetry building blocksVerify component maturity, define authorization ownership, bind approvals, manage upgrades and reconcile business effectsRequired components are preview or experimental, language capabilities do not align, or simpler application code is sufficient

The default remains direct code. Choose LangChain for a bounded agent loop, LangGraph for explicit resumable orchestration, or Microsoft Agent Framework when its combined model and ecosystem alignment solve requirements you actually have.

Next step: classify one workflow before choosing a framework

Return to a workflow like the invoice exception and classify it before installing anything. The observable result should be a clear choice of the simplest adequate option, plus one condition that would justify adopting more structured orchestration later.

That condition should be concrete, such as needing to resume several approval branches from durable state, rather than a general ambition to build agents. This keeps the architecture proportional to the work it must perform.

Create a one-page choice record

  • Name the bounded workflow and the business outcome it must produce.

  • Mark every genuinely uncertain decision delegated to a model.

  • Identify each pause, approval and resume point.

  • List every external effect and record whether it is safely repeatable.

  • Name the system of record for workflow state and completed effects.

  • Assign owners for monitoring, reconciliation and recovery.

  • Record the dependency and upgrade burden the team will accept.

  • Select the simplest adequate option from the decision table.

  • Write one observable requirement that would trigger reconsideration.

  • Expected artifact: a one-page choice record.

Questions and answers

Do simple AI workflows need an agent framework?

Usually not. If application code can make the sequence explicit, validate the model output and route exceptions to a person, direct code is often the simplest adequate starting point. A framework becomes useful when model-directed tool use, durable resumption or more complex orchestration is a real requirement.

When should I choose LangChain instead of LangGraph?

Choose LangChain when the central requirement is a contained, configurable model-and-tool loop. Consider LangGraph when the workflow needs explicit graph structure, durable state, interruption and resumption, or a deliberate mix of deterministic and model-driven steps.

Does checkpointing make payment retries safe?

No. A checkpoint can help resume framework execution, but it does not prove whether an external payment or business-system call succeeded. The application still needs controls such as idempotency, durable effect records, status verification and reconciliation.

When is Microsoft Agent Framework a strong candidate?

It is a candidate when its documented agent, harness and explicit workflow model aligns with the team’s language and ecosystem needs. Check the lifecycle of the exact language packages and integrations you intend to use because support and maturity differ across components.