Agent development frameworks increasingly expose similar vocabulary: tools, sessions, memory, handoffs, and streaming. That vocabulary hides substantial architectural differences. Defining tools for an OpenAI agent, embedding Claude Code through the Claude Agent SDK, and compiling a stateful LangGraph workflow place different parts of the system under framework control. Comparing them through a list of supported features misses the decision that will determine most of the integration work: which execution responsibilities the application keeps, and which it delegates.

The useful starting point is a layered architecture:

Product             chat UI, task API, acceptance criteria
                         |
Control flow        model/tool loop, routing, workflow transitions
                         |
State               conversation, business records, run checkpoints
                         |
Execution           application functions, files, shell, external services
                         |
Infrastructure      workers, isolation, storage, identity, telemetry

A framework can span several layers. Its name does not establish where the boundary lies.

This comparison covers nine agent-development stacks: OpenAI Agents SDK, Claude Agent SDK, Codex SDK, Google ADK, Vercel AI SDK, LangChain/LangGraph, Pydantic AI, Microsoft Agent Framework, and CrewAI. Each provides agent execution or orchestration abstractions. Their useful differences concern reusable agent loops, developed coding harnesses, typed application contracts, and explicit workflows. Those responsibilities overlap, so the comparison follows execution behavior rather than treating every framework as an interchangeable package.

The scope is architectural behavior documented and inspected on October 15, 2026. Source links point to inspected commits; documentation links can evolve. These are qualitative engineering judgments, not benchmark results or adoption rankings. Language implementations within a project may expose different capabilities.

1. Establish the execution boundary

Consider an incident assistant. It reads telemetry, inspects a repository, proposes a patch, requests approval, and applies a change. Every implementation needs model inference, but that is only one step. Someone must schedule tool calls, preserve evidence, decide whether another model turn is necessary, authenticate approvals, and recover after a worker disappears.

The first comparison is therefore about ownership:

IntegrationPrimary abstractionMain execution responsibilityApplication responsibility to examine
OpenAI Agents SDKAgent and runnerRepeated model/tool execution and agent handoffsDeployment, tool implementations, storage and approval policy
Claude Agent SDKProgrammable Claude Code sessionAn existing harness with tools and context managementProcess hosting, workspace lifecycle and isolation
Codex SDKCodex thread and turnProgrammatic execution of the Codex harnessLocal runtime, workspaces and thread lifecycle
Google ADKAgents, runner, events and servicesAgent execution with structured workflow componentsService backends, state design and tool boundaries
Vercel AI SDKModel/provider interface and agent loopTypeScript generation, tool execution and product streamingChoice of in-memory or workflow execution and persistence
LangChain / LangGraphHigh-level agent and state graphReady-made agent loops or explicit checkpointed transitionsChoice of abstraction, node logic and external-effect semantics
Pydantic AITyped agent, dependencies and outputTool execution with typed application interfacesSemantic validation, storage and durable-engine integration
Microsoft Agent FrameworkAgents, sessions and workflowsAgent execution and explicit multi-agent coordinationHosting, checkpoint storage and durable-extension configuration
CrewAIAgents, tasks, crews and flowsRole/task collaboration and event-driven workflow logicTask boundaries, persistence and validation of delegated work

The table describes integration surfaces rather than hard capability ceilings. A coding-harness SDK starts with an established file/tool execution model. An agent-loop SDK starts with an application-defined tool contract. A workflow framework gives transitions and state their own explicit representation. For the incident assistant, the relevant decision is whether the product primarily needs repository work, bounded tool use, or a business process that must survive interruption.

I would start a design review by drawing this boundary before discussing model quality. Moving the loop from application code into a framework changes debugging and lifecycle responsibilities even when the underlying model remains identical.

2. Follow one tool call through each architecture

2.1 OpenAI Agents SDK: delegate the recurring loop

The OpenAI Agents SDK moves recurring agent execution into a runner. An agent definition groups instructions, tools and related behavior; the runner handles repeated execution and handoffs. The inspected Runner.run implementation and its underlying runner make the control flow explicit: final output ends a run, a handoff changes the active agent, and tool calls can lead to another turn. See also the SDK overview.

A handoff and a specialist exposed as a tool have different ownership semantics. With a handoff, the active conversational role changes. With a specialist tool, the caller can retain responsibility for assembling the answer. This distinction is more useful than simply counting supported agents: it determines which component must enforce the final response contract. The official orchestration guide describes these patterns.

My preference would be to use the runner when its execution contract matches the product. Reimplementing a standard tool loop adds maintenance without much differentiation. Conversely, forcing a transaction-oriented workflow into model-directed handoffs can obscure the business states that operations teams need to inspect.

2.2 Claude Agent SDK: embed a developed harness

Claude Agent SDK starts from another point in the stack: it exposes the agent loop, tools and context management used by Claude Code. Python and TypeScript applications can operate that harness programmatically, including built-in file and command tools, sessions, hooks and MCP integrations. The overview explicitly distinguishes it from direct client-SDK access.

In the inspected Python source, query() delegates to InternalClient.process_query(), which selects a transport and uses the subprocess CLI transport by default. The Python wrapper is therefore not the complete implementation of the underlying agent. Some behavior lives across a process boundary.

For repository maintenance, that is an attractive starting point: file inspection, editing and command execution already have a coherent interaction model. For a narrow customer-service product, those capabilities may introduce more runtime surface than the application needs.

The engineering question becomes whether the product wants this harness’s working model. Its host must account for workspaces, subprocesses, cancellation and tool permissions. Those responsibilities belong in deployment design, even if the integration begins with a short query() call. Anthropic’s hosting guidance addresses the operating environment separately from the library API.

2.3 Codex SDK: program a coding agent through threads

Codex SDK also embeds an existing coding harness, making it a direct architectural peer of Claude Agent SDK. The official SDK documentation describes starting, continuing and resuming local Codex threads. In the inspected TypeScript implementation, Codex.startThread() and resumeThread() create thread handles, while Thread.run() and runStreamed() drive turns. The CodexExec transport manages interaction with a Codex executable.

For an incident assistant that must inspect a repository and attempt a patch, this provides a concrete execution environment to integrate. It also makes the thread and workspace separate lifecycle resources. Resuming a conversation cannot, by itself, establish that the checked-out branch or generated files still match the earlier turn.

I would compare Codex SDK and Claude Agent SDK on repository behavior, permission boundaries, cancellation, event handling and workspace recovery. For a product that needs detailed interactive lifecycle control, OpenAI separately documents Codex app-server; that integration should be evaluated on its own terms. Neither harness should be scored as though it were simply a provider-neutral business-tool loop.

2.4 Google ADK: agents within an event and service architecture

Google ADK gives agent behavior a runtime context composed of runners, events and backing services. The inspected Python Runner coordinates execution and session-service interactions. This makes session persistence and event processing visible architectural components rather than incidental message-list handling. The runtime documentation explains the separation.

ADK also exposes explicit sequential, parallel and loop workflow agents. In SequentialAgent._run_async_impl, execution advances through child agents; the sequence is represented by application structure rather than inferred afresh by a model. The workflow-agent documentation distinguishes these template workflows from model-directed behavior.

That separation suits pipelines whose stages are known: retrieve evidence, analyze it, then validate a report. A model can reason inside a stage while the application controls the stage order. Parallel branches still need deliberate data ownership; sharing an invocation does not make concurrent writes into independent fields automatically coherent.

I would evaluate ADK when the service architecture fits the surrounding application, then verify the particular language implementation and persistence backend. A framework’s cloud integrations are useful options, but they do not by themselves establish deployment requirements or guarantee provider equivalence.

2.5 Vercel AI SDK: connect the loop to a product interface

Vercel AI SDK combines provider abstractions, generation primitives and UI integration. Its ToolLoopAgent packages a reusable tool loop around generation and streaming. The inspected stop-condition source exports isStepCount; current examples use that name. Older examples using other spellings should be checked against the installed package.

A minimal configuration shape looks like this:

import { ToolLoopAgent, isStepCount } from 'ai';

// model and tools are application-supplied, provider-compatible objects.
const incidentAgent = new ToolLoopAgent({
  model,
  tools,
  instructions: 'Investigate the incident and cite the evidence used.',
  stopWhen: isStepCount(8),
});

This snippet illustrates configuration only. It leaves provider credentials, tool schemas, persistence and the HTTP route to the application. The loop-control documentation explains stopping and per-step customization.

The product-facing advantage is the connection between server-side tool activity and interactive UI. The chatbot documentation describes message handling and streaming integration. This can reduce translation work for a TypeScript application whose main complexity is presenting partial text, tool activity and user responses.

It would nevertheless be outdated to characterize the entire ecosystem as request-bound. The separately packaged WorkflowAgent runs inside a workflow and adds durable execution and resumable approvals. Choosing that integration changes the runtime contract. It should be evaluated separately from an ordinary in-memory ToolLoopAgent.

2.6 LangChain and LangGraph: choose the level of workflow control

LangChain and LangGraph occupy related layers. LangChain’s create_agent constructs a graph-based agent runtime, giving applications a higher-level entry point for models, tools and middleware. The agent documentation describes that ready-made loop. An application does not have to design a custom graph merely to use an agent in this ecosystem.

LangGraph becomes the more direct interface when workflow transitions need explicit application structure. Its inspected StateGraph and compile() expose state updates, graph construction and checkpointer configuration. The persistence documentation distinguishes checkpointed thread state from stores used across threads.

For an incident assistant, I would start with the higher-level agent when the task is mainly repeated tool use. A custom graph earns its additional state and transition definitions when investigation, review and remediation must remain separately inspectable across failures. Using a graph provides a place to represent those obligations; the application must still define them correctly and make external operations safe to replay.

2.7 Pydantic AI: make application contracts explicit

An incident assistant eventually needs to return something the application can act on: an incident identifier, evidence references, a proposed action and a review status. Pydantic AI makes typed dependencies and output definitions central to that integration. Its Agent implementation connects these contracts to agent execution; the official dependency guide explains how tools receive application services through run context.

That separation gives the model a tool interface while keeping a tenant-scoped database client or policy service in application code. It also gives a Python team a concrete seam for dependency substitution during testing. The output guide describes validating returned data against output types.

A valid schema still cannot prove that the cited evidence supports a diagnosis. I would use typed output to reject malformed results, then apply domain checks to verify identifiers, evidence and allowed transitions. This distinguishes interface correctness from task correctness.

Durability remains a separate execution choice. Pydantic AI documents integrations with engines including Temporal and DBOS in its durable-execution guide. A typed agent definition alone does not mean a run survives worker replacement. I would evaluate the chosen engine’s replay behavior, serialization constraints and deployment cost alongside the agent API.

2.8 Microsoft Agent Framework: connect agents and explicit workflows

Microsoft Agent Framework provides another useful comparison for applications that combine autonomous tool use with application-controlled coordination. Its overview describes agents, session state, middleware and graph-based workflows. Microsoft identifies it as the successor to the agent work in Semantic Kernel and AutoGen; this article evaluates the current framework rather than counting those predecessor APIs as separate contemporary choices.

The inspected Python Agent, Workflow and WorkflowBuilder expose both agent execution and workflow composition. The official workflow capabilities cover external input, checkpoints and orchestration patterns. For the incident assistant, these provide a place to distinguish an investigative agent from a mandatory review transition.

The hosting boundary deserves a separate decision. Microsoft’s Durable Extension adds durable agent and workflow execution through Durable Task infrastructure, with Azure Functions and self-hosted options. Persistence and recovery therefore depend on the selected integration, storage and workers; they should not be inferred from the core agent definition.

I would evaluate this stack when its application interfaces and deployment options fit the team. The trade-off is integration breadth: verify the exact language, package and hosting path instead of assuming every documented capability is available in every configuration.

2.9 CrewAI: separate role collaboration from workflow control

CrewAI expresses collaboration through agents, tasks and crews. Its crew documentation describes coordinating task execution through a configured process. The inspected Crew.kickoff() is a concrete entry point into that execution model.

The incident assistant could express investigation and review as separate tasks, each with an expected result and assigned responsibility. This can make specialist responsibilities easy to describe. My concern would be whether each delegation produces additional evidence or merely another model-generated opinion. A reviewer role needs a concrete evidence contract and an independent check to provide meaningful assurance.

CrewAI also exposes Flows for event-driven application logic, branching and state. Its inspected Flow implementation and Flow documentation provide a separate surface for controlling how work advances. A flow can coordinate crew execution while application logic determines what follows.

I would inspect flow persistence and resume configuration independently of crew memory. Restoring state does not by itself establish that an interrupted external write cannot happen twice. The appeal is a role/task model connected to explicit flow control; the evaluation burden is to make task outputs, delegation cost and recovery semantics observable.

3. Separate conversation memory from execution recovery

All nine stacks can participate in a stateful application. That statement provides almost no guidance until the kind of state is specified.

Conversation state contains messages and tool results. Business state contains authoritative records such as an approved incident action. Execution state records what the runtime has completed and where it can resume. A workspace adds another resource: files may survive even when the worker or conversation does not.

ApproachState surface to inspectRecovery question
OpenAI Agents SDKSessions, run results and resumable run stateWhich objects are persisted, and who schedules continuation?
Claude Agent SDKSession identity and persisted session dataCan a replacement worker access both the session and its workspace?
Codex SDKPersisted thread history and a separate workspaceDoes the restored thread still refer to the intended repository state?
Google ADKSession service, events and stateWhat survives with the selected backend and resume configuration?
Vercel AI SDKStored messages; workflow state when using WorkflowAgentIs only the transcript durable, or is execution durable too?
LangChain / LangGraphAgent state, thread checkpoints and cross-thread storesWhat work re-executes when the graph resumes?
Pydantic AIMessage history and the selected durable engineWhich model/tool steps are recorded, and can dependencies be reconstructed?
Microsoft Agent FrameworkSessions, workflow checkpoints and optional Durable Task integrationWhich backing store and hosting model provide recovery?
CrewAICrew memory, flow state and configured persistenceWhat state is restored, and which unfinished work can repeat?

The OpenAI Agents SDK results and state guide describes result and continuation surfaces. Claude’s session guide describes continuing earlier sessions. ADK’s state guide makes persistence dependent on the selected session service; an in-memory service does not survive a process restart. These are different contracts, even though each is described with the word “session.”

For the incident assistant, I would store the approved action independently of chat history. If approval means “apply patch X to revision Y,” a resumed agent must not reinterpret it as permission to apply a different patch after the branch changes.

Recovery also has an external-effect problem. Suppose a tool updates an incident ticket, then the process crashes before saving its result. Replaying the call may create a duplicate update. A persisted transcript cannot resolve whether the external service committed the first attempt. A workflow checkpoint reduces repeated work but does not automatically provide an atomic transaction across an unrelated service.

The application needs a stable operation identifier, an idempotent endpoint or deduplication record, and a way to reconcile ambiguous outcomes. Vercel’s WorkflowAgent documentation explicitly distinguishes completed-step replay from exactly-once effects. LangGraph’s interrupt documentation likewise warns about work that can re-execute around interruption. These are implementation constraints to test, not reasons to reject durable runtimes.

Context compaction solves a different problem again: fitting relevant evidence into the next inference. A summary can preserve the gist while losing an exact revision identifier. Durable authority belongs in typed application records, with the model receiving the subset needed for the current decision.

4. Treat tool permissions as a runtime contract

A tool schema describes what arguments look like. It does not establish that the current user may perform the requested action.

For an incident assistant, restart_service(service_id) must enforce tenant identity, environment, resource scope and approval status outside model-generated arguments. A well-formed request to restart another customer’s production service is still unauthorized.

The frameworks provide different interception points. OpenAI Agents SDK documents guardrails and human review. Claude Agent SDK exposes a permission system for deciding which tool actions can proceed. Vercel’s current agent-building guide exposes toolApproval for the ordinary tool loop; its workflow integration documents a different approval configuration. Those mechanisms need to be connected to application identity and policy.

My preferred approval unit is a concrete operation: tool name, validated arguments, tenant, target revision and expiry. The service should verify those values immediately before execution. A chat message saying “approved” is insufficient unless it is authenticated and bound to the pending operation.

Typed dependencies and structured outputs strengthen the application boundary in a different way. Pydantic AI emphasizes these contracts; other frameworks expose their own schema and validation surfaces. Across stacks, an output that names a valid service can still prescribe the wrong remediation. Validation must check the relationship between evidence, requested action and current business state.

The containment boundary matters as much as the permission callback. A shell-capable agent can invoke a network client through an allowed command. An application function can access credentials even when it never launches a subprocess. Tool admission, operating-system isolation and downstream authorization protect different boundaries.

This distinction changes framework selection. If the application needs repository exploration, a developed filesystem harness may save substantial implementation work. If it only needs three business APIs, deliberately narrow functions can simplify the authority model. The relevant comparison is the amount of executable capability the product actually needs.

5. Compare observed behavior on the same workload

Framework features do not establish task success, latency or cost. A useful evaluation must hold enough variables constant to make the comparison interpretable.

For the incident assistant, I would begin with the same evidence corpus, tool contracts, task budget and acceptance criteria. Where model compatibility permits, use the same model. Where a harness is tied to a different model or execution environment, report that difference explicitly and avoid attributing the entire outcome to the SDK.

Provider portability should also be tested as behavior. Two adapters can accept similar tool schemas while differing in supported output modes, parallel calls or native tools. A useful substitution test changes the model and reruns the same acceptance suite; successfully changing a model name is only the first step.

The evaluation should include failure as well as completion:

ScenarioEvidence to collect
Routine incident investigationCorrect diagnosis, cited evidence, tool and model-call counts
A tool returns a malformed resultValidation outcome and whether the agent invents missing evidence
A typed result cites unrelated evidenceWhether domain validation catches a semantically wrong answer
A specialist delegates work to another agentAdditional evidence, model-call overhead and final-answer ownership
A worker dies after an external updateDuplicate effects, reconciliation and restart behavior
Approval arrives after a deployment changesWhether the stale action is rejected or reauthorized
A document includes malicious instructionsWhich tool requests reach the authorization boundary
The user cancels during a slow commandWorker termination, pending effects and reported task state

These are proposed experiments, not results obtained for this article.

Telemetry should connect the task, model requests, tool calls, approvals and external operation identifiers. OpenAI documents SDK tracing and observability; other runtimes have their own integration surfaces. A useful trace explains the execution without requiring storage of private reasoning. It should also support redaction: incident evidence and tool results may contain credentials or customer data.

Cost comparison should include failed attempts, repeated context, retry behavior and operating overhead. A framework with fewer lines of integration code can still generate more model turns. A more structured workflow can reduce repeated work while increasing implementation and maintenance cost. Both effects need measurement under the intended workload.

6. Choose the abstraction that matches the product

My selection would follow the dominant engineering constraint. These are starting points for evaluation, not exclusive capabilities. Several stacks can satisfy the same requirement through different integrations.

Dominant requirementStarting point I would evaluateMain trade-off to verify
Application-defined tools and agent delegationOpenAI Agents SDKFit between runner semantics and business transitions
Repository work with file and command toolsClaude Agent SDK or Codex SDKHarness assumptions, worker hosting, thread/workspace recovery and isolation
Composable agent pipelines with explicit service backendsGoogle ADKState ownership, backend configuration and language parity
TypeScript product with interactive model/tool streamingVercel AI SDKIn-memory loop versus durable workflow integration
A ready-made agent loop with ecosystem middlewareLangChain agentsWhether high-level customization is enough before introducing a custom graph
Explicit branching, checkpoints and delayed human decisionsLangGraphGraph complexity and replay-safe external operations
Typed Python dependencies and structured application resultsPydantic AISchema validity versus semantic correctness; chosen durable engine
Agent/workflow composition with Microsoft application integrationsMicrosoft Agent FrameworkLanguage/package parity and the hosting/durability boundary
Role-based specialist tasks coordinated by an explicit flowCrewAIDelegation overhead, task-output quality and persistence semantics

These choices can coexist. A TypeScript UI can stream events from a separate agent worker. A durable workflow can call a model client for bounded decisions. A repository harness can be one specialized stage inside a broader business process. Combining them is useful when ownership remains explicit; overlapping schedulers and competing session stores make failures harder to explain.

Three trade-offs remain central. More harness behavior reduces integration work while increasing dependence on the harness’s execution model. More explicit workflow structure improves inspectability while requiring the team to maintain that structure. Broader provider abstraction can ease model substitution while leaving differences in tools, state and output semantics unresolved.

I would therefore prototype the difficult lifecycle first: interrupt a run, replace its worker, deliver a delayed approval, and inspect the external effects. A framework that makes that sequence understandable is a stronger foundation than one that only makes the first successful response easy to produce.

The open question is how much of the product’s execution model should become a dependency. The answer comes from the application’s state, authority and recovery requirements. Model access is the entry point; the runtime contract determines what happens afterward.