LangGraph, OpenAI Agents SDK lub Claude Agent SDK: dopasuj prymityw do zadania.
Cztery przykładowe obciążenia pracy – głos, trwałe zwroty pieniędzy, migracja kodu oraz operacje MCP – pokazują, który framework agentów nadaje się w danym przypadku, wraz z uwagami na temat efektu blokującego, trwałości i pracy w czasie rzeczywistym.
Źródła: The Best Agent Framework in 2026: LangGraph vs OpenAI Agents SDK vs Claude Agent SDK
Porównania z 2026 roku wciąż dotyczą trzech frameworki dla agentów, a każdy z nich opiera się na innej podstawowej koncepcji. LangGraph to środowisko wykonawcze grafów, w którym węzłami są zwykłe funkcje, a krawędzie określają przejścia pomiędzy nimi. SDK OpenAI Agents koncentruje się na przekazywaniu zadań, przy czym agent przekazuje pracę innemu agentowi poprzez typowane sesje, z natywnym wsparciem dla MCP. SDK Claude Agent jest nieoczekiwanym rozwiązaniem: daje agentowi komputer, ponieważ Anthropic zbudował je w oparciu o wykonywanie poleceń w bashu, zapisy plików oraz hooki, wierząc, że zdolny agent potrzebuje prawdziwego shella.
Prawidłowy wybór zależy od czegoś, o czym porównania architektur rzadko pytają: jakiego rodzaju zadania wykonywa agent?
Trzy podstawowe elementy
LangGraph jest przeznaczony dla procesów pracy z stanem. Deklaruje się schemat stanu, a obiekt typowany przemieszcza się po grafie od pierwszego do ostatniego węzła. Ponieważ mechanizmy kontrolne zapisują ten stan w każdym węźle, proces może być kontynuowany po awarii lub po oczekiwaniu na zatwierdzenie przez człowieka, przy zachowaniu całego kontekstu. Funkcja create_agent, która pojawiła się w LangChain 1.0, dostępnej powszechnie 22 października 2025 roku, jest jedynie fasadą nad tym silnikiem wykonawczym, co kończy dawą debatę o tym, który system wybrać – LangChain czy LangGraph.
SDK OpenAI Agents składa się z dziewięciu podstawowych elementów, w tym Agents, Handoffs, Tools, Guardrails, Sessions i Realtime. Jego podstawową jednostką jest jeden agent przekazujący zadanie innemu. Niezależność od dostawców pojawiła się w 2025 roku dzięki obsłudze ponad 100 modeli za pośrednictwem LiteLLM. MCP stanowi narzędzie pierwszej klasy, a funkcja głosowa jest wbudowana w rodzinę modeli gpt-realtime-2.
SDK Claude Agent opiera się na środowisku wiersza poleceń. Jego zestaw narzędzi zawiera Bash, Read, Write, Edit, Glob i Grep, a także hooki dotyczące cyklu życia o nazwach PreToolUse, PostToolUse i Stop, oraz podagenty uruchamiane w oddzielnych, izolowanych oknach kontekstowych. W końcu 2025 roku Anthropic zmienił nazwę z Claude Code SDK, ponieważ to narzędzie służy również do zaawansowanych badań, tworzenia filmów i robienia notatek, a nie tylko do programowania. Dozwolone są wyłącznie modele Claude, chociaż mogą je hostować Bedrock, Vertex i Azure Foundry.
Przekonanie z 2025 roku, które przeminie
Powszechnie przyjmowane w zeszłym roku założenie mówiło, że SDK OpenAI Agents wymusza użycie modeli OpenAI. Jest to informacja przestarzała o około piętnaście miesięcy. Oficjalny repozytorium obsługuje API OpenAI Responses oraz około 100 innych modeli dzięki integracjom LiteLLM i Any-LLM.
# Install: pip install "openai-agents[litellm]"
# Env: export GEMINI_API_KEY=...
import os
from agents import Agent, Runner, function_tool
from agents.extensions.models.litellm_model import LitellmModel
@function_tool
def current_time_utc() -> str:
"""Return the current UTC time as an ISO-8601 string."""
from datetime import datetime, timezone
return datetime.now(timezone.utc).isoformat(timespec="seconds")
# OpenAI Agents SDK using Gemini via LiteLLM. No OpenAI key required.
gemini_model = LitellmModel(
model="gemini/gemini-2.5-pro",
api_key=os.environ["GEMINI_API_KEY"],
)
agent = Agent(
name="time-agent",
instructions="Answer time questions using the current_time_utc tool.",
model=gemini_model,
tools=[current_time_utc],
)
result = Runner.run_sync(agent, "What is the current UTC time?")
print(result.final_output)
# -> "The current UTC time is 2026-07-06T14:32:11+00:00."
Tworzenie LitellmModel przy użyciu nazwy modelu Gemini pokazuje, że framework ten umożliwia integrację poza ekosystemem OpenAI, a dekorator @function_tool zachowuje się identycznie niezależnie od tego, jaki model leży u jego podstawy. Ścieżki niebędące częścią OpenAI są dokumentowane jako realizowane w maksymalnym możliwym stopniu, przy czym równoważność funkcjonalności różni się w zależności od dostawcy. Bez ścisłych ograniczeń dotyczących modeli, frameworki konkurują ze sobą pod względem swoich architektonicznych elementów bazowych.
Firma testowa z czterema agentami
Weźmy średniej wielkości firmę z sektora fintech, nazwijmy ją Meridian, która ma w trakcie budowy cztery agenty w oddzielnych zespołach.
- Agent obsługi telefonicznej, który zajmuje się pytaniami dotyczącymi fakturowania przez telefon.
- Proces zwrotów pieniędzy z udziałem wielu agentów, który sprawdza zasady przeciwdziałania oszustwom przed przekazaniem zgłoszenia do działu finansowego.
- Agent do migracji kodu wewnętrznego, który przegląda duży repozytorium w języku Java, stosuje transformacje składniowe i tworzy prośby o połączenie kodu.
Poniższe cztery wersje oprogramowania pokazują, który framework jest do nich odpowiedni.
Zadanie nr 1: transmisja głosu i w czasie rzeczywistym
Zespół zajmujący się transmisją głosu musi przestrzegać ścisłego limitu opóźnienia – nie więcej niż 500 ms przy transmisji, a także musi radzić sobie z przypadkowym włączeniem się użytkowników. Proces konwersji mowy na tekst, następnie tekstu na mowę jest zbyt wolny, ponieważ każdy skok w sieci powoduje dodatkowe opóźnienie.
Odpowiedni okazuje się SDK OpenAI Agents. Model gpt-realtime-2 przesyła tokeny audio w sposób natywny, a RealtimeAgent umożliwia wykorzystanie tej funkcji. Ani LangGraph, ani Claude Agent SDK nie oferowały w połowie 2026 roku natywnych narzędzi do pracy w czasie rzeczywistym na tym poziomie.
# Install: pip install openai-agents
# Env: export OPENAI_API_KEY=...
import asyncio
from agents import function_tool
from agents.realtime import RealtimeAgent, RealtimeRunner
@function_tool
def lookup_billing_balance(account_id: str) -> str:
"""Return the current outstanding balance for an account."""
# In production, this hits the billing service. Here it is a stub.
return "42.17 USD outstanding as of 2026-07-06."
voice_agent = RealtimeAgent(
name="meridian-billing-voice",
instructions=(
"You are Meridian's billing voice assistant. Answer politely, briefly. "
"Confirm the account_id before disclosing any balance."
),
tools=[lookup_billing_balance],
)
async def main():
runner = RealtimeRunner(
starting_agent=voice_agent,
config={"model_settings": {"model_name": "gpt-realtime-2.1"}},
)
# session handles the audio stream and tool calls
session = await runner.run()
async with session:
# Wire the audio input source here via sounddevice or pyaudio
async for event in session:
if event.type == "history_updated":
# The item contains the finalized transcript once the turn ends
print(f"History updated with item: {event.item}")
elif event.type == "error":
print(f"Error: {event.error}")
break
asyncio.run(main())
RealtimeAgent i RealtimeSession zajmują się strumieniami audio przychodzącymi i wychodzącymi oraz pętlą wywoływania narzędzi, a narzędzia zadeklarowane za pomocą @function_tool działają w sesji w czasie rzeczywistym tak samo jak w agencie tekstowym. Framework ujawnia pętlę zdarzeń, podczas gdy stan WebSocket pozostaje niewidoczny.
Wykonywanie tego w LangGraph lub Claude Agent SDK oznaczałoby konieczność stworzenia własnego kodu WebSocket, systemu wykrywania aktywności głosowej oraz skomplikowanych zasad przerw, co przekształca projekt agenta w projekt pipeline mediów. Jeśli polityka firmy wymaga użycia modelu głosowego Claude lub Gemini, odpowiedź się zmienia. Anthropic dodał funkcje czasu rzeczywistego później, więc osoby czytające tekst po połowie 2026 roku powinny sprawdzić zgodność funkcji.
Zadanie drugie: trwała orkiestracja z zatwierdzeniem człowieka
Proces zwrotu pieniędzy wymaga sprawdzenia na podstawie danych o oszustwach, następnie przekazania sprawy do zatwierdzenia finansowego, oczekiwania na ludzką weryfikację w przypadku zwrotów przekraczających 500 dolarów oraz ostatecznej decyzji zapisanej z powrotem do Postgresa. Musi funkcjonować nawet w przypadku awarii serwera i radzić sobie z asynchronicznymi przerwami ze strony ludzi bez utraty kontekstu.
LangGraph doskonale się do tego nadaje. Punktery kontrolne w połączeniu z mechanizmem przerw zapewniają dokładnie taki przepływ sterowania, jakiego potrzebują długotrwałe procesy biznesowe. Zespoły produkcyjne popierają tę architekturę: Uber donosi o zaoszczędzeniu około 21 000 godzin pracy programistów dzięki użyciu LangGraph w systemach AutoCover i Validator, a LinkedIn opublikował artykuł na temat hierarchicznego drzewa pamięci semantycznej dla swojego narzędzia Hiring Assistant, przy czym kwestie związane z jego projektowaniem jako nadzorcy i podagentów są omawiane osobno w prezentacjach technicznych LangChain.
from typing import TypedDict, Literal
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver
from langgraph.types import interrupt, Command
from langchain_google_genai import ChatGoogleGenerativeAI
# LangGraph is provider-agnostic. Here it uses Gemini.
llm = ChatGoogleGenerativeAI(model="gemini-2.5-pro", temperature=0)
class RefundState(TypedDict):
order_id: str
amount_usd: float
customer_reason: str
fraud_risk: Literal["low", "medium", "high"] | None
finance_decision: Literal["approved", "denied"] | None
human_review_needed: bool
def fraud_check(state: RefundState) -> RefundState:
"""Run the LLM-backed fraud check against the customer's stated reason."""
prompt = (
f"Assess fraud risk for refund of ${state['amount_usd']:.2f}. "
f"Customer reason: {state['customer_reason']!r}. "
"Respond with one word: low, medium, or high."
)
verdict = llm.invoke(prompt).content.strip().lower()
if verdict not in {"low", "medium", "high"}:
verdict = "high" # fail-closed on ambiguous LLM output
return {**state, "fraud_risk": verdict}
def finance_approval(state: RefundState) -> RefundState:
"""Above $500 or medium risk, pause for a human. Otherwise auto-approve."""
needs_human = state["amount_usd"] > 500 or state["fraud_risk"] in {"medium", "high"}
if needs_human:
# Pause the graph. On resume, interrupt returns the human's decision.
human_decision = interrupt({
"order_id": state["order_id"],
"amount_usd": state["amount_usd"],
"fraud_risk": state["fraud_risk"],
"prompt": "Approve (yes/no)?",
})
return {**state, "human_review_needed": True, "finance_decision": human_decision}
return {**state, "human_review_needed": False, "finance_decision": "approved"}
# Build the graph
graph = StateGraph(RefundState)
graph.add_node("fraud_check", fraud_check)
graph.add_node("finance_approval", finance_approval)
graph.add_edge(START, "fraud_check")
graph.add_conditional_edges(
"fraud_check",
lambda s: "finance_approval" if s["fraud_risk"] != "high" else END,
)
graph.add_edge("finance_approval", END)
# Checkpointer. For production, swap MemorySaver for PostgresSaver.
compiled = graph.compile(checkpointer=MemorySaver())
# Run it. Interrupt fires on the $850 refund and the graph pauses.
config = {"configurable": {"thread_id": "order-4291"}}
result = compiled.invoke(
{
"order_id": "4291",
"amount_usd": 850.00,
"customer_reason": "arrived damaged, no photo",
"fraud_risk": None,
"finance_decision": None,
"human_review_needed": False,
},
config=config,
)
# Later, a human reviewer says yes. Resume with Command.
final = compiled.invoke(Command(resume="approved"), config=config)
Wzorzec pauzy i wznowienia pokazuje trwałe wykonywanie kodu. Wywołanie funkcji interrupt() węzłem zatwierdzania transakcji finansowych zapisuje bieżący stan do checkpointera, a system może w tym momencie zostać wyłączony. Kilka godzin później polecenie z ustawieniem resume na „approved” kontynuuje pracę od miejsca pauzy przy tym samym identyfikatorze wątku, bez ponownego przeprowadzania sprawdzenia oszustwa.
Istnieje jednak ograniczenie dotyczące trwałości. Oprogramowanie open-source do wykonywania kodu zapisuje stan w MemorySaverze, który znajduje się w pamięci procesu. Rzeczywiste przywracanie po awarii pod obciążeniem wymaga platformy LangGraph zasilanej przez Postgres lub specjalnego narzędzia PostgresSaver.
SDK OpenAI Agents oferuje Sessions do przechowywania stanu rozmowy oraz Sandbox Agents do pracy na dłuższy horyzont czasowy, ale nie posiada funkcji porównywalnej z zapisywaniem stanu na poziomie węzłów w dowolnym grafie. SDK Claude Agent przechowuje lokalnie stan sesji w formacie JSONL lub wykorzystuje Managed Agents dla zapewnienia trwałości danych, co jednak wiąże się z koniecznością korzystania wyłącznie z modeli dostępnych w Claude. Na razie LangGraph posiada funkcje umożliwiające trwałą orkiestrację zadań.
Zadanie trzecie: praca z plikami i wierszem poleceń
Agent migracyjny z zespołu odpowiedzialnego za doświadczenie programisty musi przeszukać repozytorium w Javie składające się z 400 000 linii kodu, zastosować zmiany składniowe, uruchomić testy jednostkowe oraz otworzyć prośby o połączenie kodu. Oznacza to czytanie i edycję plików, wykonywanie poleceń w wierszu poleceń oraz reagowanie na błędy kompilatora. Bash i Edit stanowią niemal całość tego zadania.
SDK Claude Agent mapuje się bezpośrednio na to, ponieważ założeniem Anthropic jest dostarczenie agentom komputera. Zawiera wbudowane narzędzia do Bash, Read, Write, Edit, Glob i Grep, a jego hooki pełnią rolę interfejsu sterowania. Hook PreToolUse może wprowadzać ograniczenia przeciwko destruktywnym poleceniom, natomiast hook PostToolUse może uruchamiać narzędzia do formatowania lub sprawdzania kodu. Podagenty dzielą pracę przekształceniową pomiędzy izolowane konteksty, dzięki czemu długi log błędów kompilatora przekazany podagentowi nie zanieczyszcza okna głównego agenta.
# Install: pip install claude-agent-sdk
# Env: export ANTHROPIC_API_KEY=...
import anyio
from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions,
AgentDefinition,
HookMatcher,
)
# PreToolUse hook: block Bash calls that look like rm -rf
async def block_dangerous_bash(input_data, tool_use_id, context):
if input_data.get("tool_name") == "Bash":
cmd = input_data.get("tool_input", {}).get("command", "")
if "rm -rf" in cmd or "rm -rf" in cmd:
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "rm -rf blocked by policy",
}
}
return {}
# Subagent: runs in isolated context to lint one file
lint_agent = AgentDefinition(
description="Run linters on a single file and return a concise report.",
prompt=(
"You are the lint subagent. Given a file path, run the project's linter "
"on it and return a one-paragraph summary of failures. Do not fix anything."
),
tools=["Bash", "Read"], # Note: tools is deprecated in favor of skills in recent SDKs
)
options = ClaudeAgentOptions(
system_prompt=(
"You are Meridian's code migration agent. Walk the target directory, "
"apply the migration, run tests, and open a PR. Prefer small commits."
),
allowed_tools=["Bash", "Read", "Write", "Edit", "Glob", "Grep"],
hooks={"PreToolUse": [HookMatcher(hooks=[block_dangerous_bash])]},
agents={"lint": lint_agent},
# resume="mig-run-2026-07-06-01", # uncomment to resume a prior session
)
async def main():
async with ClaudeSDKClient(options=options) as client:
await client.query(
"Migrate services/payments/ from Java 17 to Java 21. "
"For every file you touch, delegate to the `lint` subagent afterward. "
"Do NOT commit or open PRs yet. Stop after changes are on disk."
)
async for message in client.receive_response():
print(message)
anyio.run(main)
Lista allowed_tools określa środowisko agenta. Hooki stanowią mechanizm ochronny działający wewnątrz pętli agenta, a nie wokół niej: hook PreToolUse jest wykonywany przed użyciem narzędzia, natomiast decyzja deny natychmiast zatrzymuje jego wywołanie. Podagent lint posiada własne narzędzia oraz okno kontekstowe. W najnowszych wersjach SDK pole tools w obiekcie AgentDefinition zostało zastąpione przez pole skills, chociaż nadal funkcjonuje. Opisana linia kodu ilustruje przywracanie stanu sesji z plików JSONL na lokalnym dysku.
W LangGraph te podstawowe elementy systemu muszą być zapisane jako niestandardowe funkcje w Pythonie. Agenty Sandbox SDK OpenAI działają w kontenerach, które mają podobną architekturę, ale zbiór tych elementów nie jest nazwany ani udostępniony w taki sam sposób oparty na plikach. Problemem jest tu blokada modelu – zespół, który ma ścisłe zasady przeciwko blokadzie na poziomie modelu, nie może korzystać z SDK Claude Agent i musi zwrócić się do LangGraph, tworząc samodzielnie elementy do obsługi bash i edycji.
Zadanie czwarte: zintegrowana orkiestracja oparta na MCP
Panel sterowania zespołu platformy odpowiada na jedno pytanie zadane przez inżyniera. W tle agent pobiera błędy z Sentry, zgłoszenia z Linear, incydenty z PagerDuty oraz dane użytkowników z Postgresa. Prawie całe jego wysiłki są skupione na koordynacji serwerów MCP dostarczanych przez strony trzecie, a bardzo niewiele na tworzeniu odpowiedzi.
Tutaj SDK OpenAI Agents i SDK Claude Agent są na równi. W obu przypadkach MCP stanowi podstawowy element budulcowy, a serwery działają jak lokalne funkcje. LangGraph również może korzystać z MCP, ale w połowie 2026 roku wymaga to większej ilości kodu szablonowego, a zespoły zazwyczaj same pakują serwery w narzędzia. Decydujący czynnik pomiędzy tymi dwoma liderami to drugorzędny ograniczenie.
- Wybierz SDK OpenAI Agents w przypadku śledzenia działań wewnątrz aplikacji, ścisłych zasad bezpieczeństwa i przekazywania zadań specjalistycznym podagentom, lub gdy korzystne jest kierowanie prostych zadań syntezy do tańszych dostawców za pośrednictwem LiteLLM.
- Wybierz SDK Claude Agent ze względu na cykl życia hooków, ścisłą izolację podagentów oraz niezawodność wykorzystywania narzędzi przez Claude’a.
Specjalne otulacze API dla popularnych narzędzi SaaS pochłaniają czas inżynierów. Standard MCP standaryzuje kontekst oraz proces znajdowania narzędzi, dzięki czemu framework musi jedynie nie przeszkadzać, a oba SDK obsługują ten wzorzec w sposób natywny.
Podsumowanie według obciążenia pracy
- Głos w czasie rzeczywistym z możliwością wtrącania się: OpenAI Agents SDK.
- Trwałe procesy wielu agentów z akceptacją człowieka: LangGraph.
- Przenoszenie plików, shella i kodu: Claude Agent SDK.
- Złożona orkiestracja MCP: OpenAI Agents SDK lub Claude Agent SDK.
Uwaga na temat CrewAI
Wielu czytelników oczekuje obecności CrewAI w takim porównaniu. Po sprawdzeniu okazało się, że dowody dotyczące jego obecnej wersji, adopcji Flows oraz studiów przypadków w środowiskach korporacyjnych nie były tak solidne jak w przypadku pozostałych trzech rozwiązań, dlatego zostało ono pominęte, zamiast wypełniać tekst mniej wiarygodnymi źródłami.
Prawdziwy wybór
Cztery agenty znalazły się w trzech frameworkach: agenci głosowi i platformowi w OpenAI SDK, proces zwrotu pieniędzy w LangGraph oraz agent migracyjny w Claude Agent SDK. Dyskusja o tym, który framework wygrywa, jest błędnym podejściem. Zadaniem jest dostosowanie podstawowych elementów danego frameworku do charakteru wykonywanej pracy.
Następny etap prawdopodobnie ponownie rozpocznie debatę na temat trwałości, gdy LangGraph Platform będzie konkurować z Managed Agents firmy Anthropic. LangGraph może otrzymać zaawansowane narzędzia do pracy w czasie rzeczywistym, albo Anthropic może otworzyć swój SDK dla innych dostawców modeli. Do tego czasu to właśnie te narzędzia określają architekturę.
Literatura pokrewna
- Stwórz Multi-Agent Router z LangGraph i agentem nadzorczym — Jak podzielić jeden przeciążony agent na specjalistów przy użyciu agenta nadzorczego w LangGraph, wykorzystując gotowe narzędzia pomocnicze oraz ręcznie tworzony StateGraph, a także omówić projektowanie stanów i typowe pułapki.
- Samolecząca zespół multi-agentów w LangGraph: architekt, tester, debugger — Stwórz maszynę stanów w LangGraph w Pythonie, w której architekt, programista, środowisko testowe pytest, debugger i recenzent współpracują i powtarzają procesy, aż testy się udają.