Deep Agents w LangChain: planowanie, podagenty i bramka bankowa
W jaki sposób DeepAgents wykorzystują planowanie, system plików oraz podagenty w pętli narzędziowej, w czym różnią się od ReAct oraz jak rozdzielać narzędzia pomiędzy agentami dziedzinowymi za bramką.
Źródła: Beyond Simple Agents: Engineering DeepAgents for Enterprise with LangChain
Wiele zespołów może zatrudnić agenta pracującego na laptopie. Znacznie mniej z nich potrafi utrzymać takiego agenta w użyciu w rzeczywistych zastosowaniach, i to właśnie w tym rozdźwięku powstają zaawansowane agenci. To nie jest tylko modny termin – to odpowiedź na konkretną ograniczoność: prosty cykl wywoływania narzędzi zawodzi, gdy praca staje się długa, składająca się z wielu elementów lub skomplikowana.
Ograniczenia prostego cyklu
Najprostszym agentem jest LLM działający w cyklu i wywołujący różne narzędzia. Taki agent jest zazwyczaj powierzchowny, co oznacza, że nie potrafi planować długotrwałych zadań ani sprostać skomplikowanym, wieloetapowym procesom. Dobrze radzi sobie z pojedynczym pytaniem, ale napotyka trudności przy zadaniach większej skali.
Produkty takie jak Deep Research, Manus i Claude Code poradziły sobie z tym dzięki czterem elementom: narzędziu do planowania, podagentom, systemowi plików oraz szczegółowemu poleceniu. Projekt deepagents powstał w wyniku próby zrozumienia, co sprawia, że Claude Code jest tak uniwersalny, oraz dalszego rozwijania tej koncepcji. LangChain nazywa takie agenty „deep agents”, ponieważ potrafią one planować złożone zadania i wykonywać je przez dłuższy czas. W praktyce jest to sposób LangChain na stworzenie autonomicznych agentów w stylu Claude Code, które potrafią radzić sobie z rzeczywistymi, wieloetapowymi zadaniami, a nie tylko jednorazowymi pytaniami.
deepagents to samodzielna biblioteka stworzona na bazie podstawowych elementów budujących agenty w LangChain i działająca w środowisku LangGraph, które zapewnia trwałe wykonywanie zadań, transmisję danych w czasie rzeczywistym oraz możliwość udziału człowieka w procesie. Dobrym opisem jest „uprząż dla agenta”: ten sam cykl wywoływania narzędzi co w innych frameworkach, ale wzbogacony o dodatkowe wbudowane narzędzia i funkcje.
Cztery składniki
Planowanie. Wbudowane narzędzie write_todos umożliwia agentowi podzielenie dużego zadania na pojedyncze kroki, śledzenie postępów oraz modyfikację planu w miarę pojawiania się nowych informacji.
System plików do przechowywania kontekstu. Narzędzia takie jak ls, read_file, write_file i edit_file umożliwiają agentowi przechowywanie obszernego kontekstu w pamięci lub na dysku, dzięki czemu okno kontekstu nie przepełnia się i można obsłużyć wyniki narzędzi dowolnej wielkości. Starsze wiadomości są automatycznie podsumowywane, gdy rozmowa staje się zbyt długa.
Podagenty. Wbudowane narzędzie do zadań tworzy specjalistycznych podagentów z izolowanym kontekstem. Główny agent pozostaje uporządkowany, podczas gdy pomocnik skupia się na konkretnym zadaniu.
Długie instrukcje systemowe. Instrukcje odbudowane z Claude Code są długie i zawierają szczegółowe wskazówki dotyczące używania narzędzi oraz przykłady z kilkoma scenariuszami pokazującymi, jak postępować w konkretnych sytuacjach. Bez nich te agenty byłyby znacznie mniej skuteczne. Instrukcje nadal odgrywają kluczową rolę.
Jego miejsce w stacku LangChain
Istnieją trzy warstwy, z których każda opiera się na tej poniżej. LangGraph to środowisko działania agentów, odpowiednie do łączenia różnych procesów roboczych i agentów. LangChain to framework dla agentów, przydatny do korzystania z podstawowego cyklu działania oraz tworzenia promptów i narzędzi od zera. Deep Agents to zestaw narzędzi służący do tworzenia autonomicznych agentów działających przez długi czas, które korzystają z wbudowanego planowania, systemu plików oraz innych dodatkowych funkcji. Ten zestaw jest zbudowany na abstrakcji agentów z LangChain, która z kolei opiera się na LangGraph.
Przykład z bankowości
Załóżmy, że bank udostępnia pięć narzędzi specjalistycznych: wyszukiwanie bankomatów według kodu pocztowego, wyświetlanie listy specjalistów od inwestycji w danym mieście, pobieranie informacji o firmach z portfela inwestycyjnego banku, dostarczanie szczegółów na temat planów emerytalnych oraz wyszukiwanie oddziałów w różnych regionach. Każde z tych narzędzi dobrze radzi sobie z jednym, określonym zadaniem. Problemy pojawiają się, gdy użytkownik prosi o coś, co wymaga jednoczesnego wykorzystania kilku z tych narzędzi:
Czy może Pan podać listę punktów obsługi bankomatami XYZ Bank wraz z firmami znajdującymi się w jego portfelu inwestycyjnym, a także informacje o lokalizacjach pracowników ds. inwestycji w Chicago?
Odpowiedź na to pytanie wymaga wykrycia kilku intencji w jednej prośbie, wyboru i skoordynowania odpowiednich narzędzi, utrzymania kontekstu w różnych domenach danych oraz połączenia wszystkich wyników w jedną spójną odpowiedź. Architektury zaprojektowane do procesów jednoetapowych lub liniowych często zawodzą w takich sytuacjach. Właśnie do tego stworzono zaawansowane agenty.
Sekwencja działa w następujący sposób.
- Planowanie. Główny koordynator analizuje złożone pytanie i używa funkcji
write_todos, aby podzielić je na trzy zadania: uzyskanie listy punktów obsługi bankomatami, pozyskanie informacji o firmach z portfela inwestycyjnego oraz znalezienie lokalizacji pracowników w Chicago.
get_atm_centers(zipcode=...), get_trusted_portfolio_companies() oraz get_investment_officers(city="Chicago").Prosty agent do wywoływania narzędzi obsługiwałby wszystkie trzy zadania kolejno w ramach jednego kontekstu. Mógłby zapomnieć o wcześniejszych wynikach, stracić poczucie, na jakie pytanie odpowiada, lub osiągnąć limit kontekstu. Zaawansowany agent trzyma poszczególne zadania oddzielnie i śledzi postępy w liście zadań do wykonania, dzięki czemu nawet jeśli jedno wywołanie się nie powiedzie lub zwróci tylko część danych, koordynator wie, w jakim jest stanie.
Struktura jest prosta:
from deepagents import create_deep_agent
agent = create_deep_agent(
tools=[
get_atm_centers, # your ATM tool
get_investment_officers, # your officers tool
get_portfolio_companies, # your portfolio tool
get_retirement_plans, # your retirement tool
get_bank_locations, # your locations tool
],
system_prompt="You are XYZ Bank's AI assistant. Always answer completely and cite sources."
)
result = agent.invoke({"messages": [{"role": "user", "content": "Can you give me a list of ATM centers for XYZ bank and also list the name of companies XYZ has in its investment portfolio? Also can you give me the location of XYZ investment agents in Chicago?"}]})
Agent decyduje, jakie narzędzia wywołać, w jakiej kolejności oraz jak połączyć uzyskane wyniki. Nie musisz sam piszeć logiki routingu, a to jest prawdziwa wartość tego rozwiązania.
ReAct wobec zaawansowanych agentów, gdy brakuje narzędzia
Weźmy tę samą prośbę i dodajmy czwarte pytanie, na które nie istnieje żadne narzędzie: lista opcji kart kredytowych dla studentów. Oto jak każdy z tych podejść radzi sobie z tym zadaniem.
Agent głęboki sprawdza swój rejestr narzędzi i tworzy listę zadań do wykonania przed podjęciem działań, dzięki czemu od razu widzi, że nie ma żadnego narzędzia do obsługi kart kredytowych. Uruchamia podagenty do trzech zadań, które wykonywane są równolegle i kończą się pomyślnie, oznacza pozycję dotyczącą karty kredytowej jako „brak dostępnych narzędzi” i zwraca jedną syntetyczną odpowiedź. Ta odpowiedź w pełni odpowiada na wszystkie trzy pytania i jasno informuje użytkownika, że nie skonfigurowano żadnego narzędzia do obsługi kart kredytowych i że może być konieczne jego dodanie. Nic się nie psuje, a częściowy sukces jest dokładnie zgłaszany.
ReAct, skrót od Reasoning plus Acting, postępuje zgodnie z ścisłym cyklem Myśl, Działanie, Obserwacja, krok po kroku, bez wcześniejszego planu. To powoduje trzy problemy:
- Działa sekwencyjnie – najpierw bankomaty, potem portfel, a następnie pracownicy. Problem z kartami kredytowymi pojawia się dopiero na końcu, po zakończeniu wszystkich pozostałych działań.
ReAct nadaje się do krótkich, dobrze zdefiniowanych zadań, w których wiadomo, że wszystkie narzędzia istnieją. Agenci typu Deep są przeznaczone dla bardziej skomplikowanego świata rzeczywistego, gdzie pytania są złożone, narzędzia mogą być nieobecne, a mimo to chce się osiągnąć jak największą wartość z tego, co się ma.
Pytanie projektowe: jeden agent ze wszystkimi narzędziami?
Czy to oznacza, że powinniśmy stworzyć wiele narzędzi i udostępnić je wszystkie za pośrednictwem jednego agenta? Nie. Jeden agent zawierający 50 lub więcej narzędzi stanowi antypatern. Lepszym rozwiązaniem jest hierarchia agentów. Wyobraź sobie agenta, którego konfiguracja wymienia setki narzędzi – od wyszukiwania w internecie i e-maili po rezerwację lotów i starty rakiet – z poleceniem „sam to rozwiąż”. Może to czasami zadziałać, a od czasu do czasu odpowiada na skargi dotyczące opóźnionych dostaw, rezerwując lot, składając podatki i zamawiając pizzę. Nikt tego nie chce.
Własność domeny
Główną zasadą jest to, że każdy agent domeny zarządza małą, spójną grupą narzędzi – idealnie od trzech do pięciu – pochodzących z jednej dziedziny biznesowej. Agent bramkowy nigdy nie dotyka narzędzi; jedynie odczytuje intencję, kieruje ją do odpowiedniego agenta domeny i łączy uzyskane odpowiedzi. To ta sama separacja zadań, którą stosuje się w mikrosługach.
W przypadku bankowości naturalny podział jest następujący:
- Agent oddziału i bankomatu z metodami
get_atm_centersorazget_bank_locations, odpowiadający za lokalizację fizyczną: kody pocztowe, miasta, godziny otwarcia. - Agent ds. inwestycji z metodami
get_portfolio,get_officersorazget_retirement_plans, zajmujący się zarządzaniem finansami, w tym przepisami prawnymi, certyfikatami pracowników i typami planów emerytalnych. - Agent produktów z metodą
get_credit_cards, gdy taka istnieje, a także produktami kredytowymi i kontami oszczędnościowymi, odpowiadający za katalog produktów. Gdy brakuje jakiegoś narzędzia, tylko ten agent zgłasza tę lukę, a pozostali kontynuują pracę bez zmian.
Kod odzwierciedla tę strukturę:
from deepagents import create_deep_agent
# Each domain agent is self-contained
branch_agent = create_deep_agent(
tools=[get_atm_centers, get_bank_locations],
system_prompt="You are the Branch & ATM specialist for XYZ Bank..."
)
investments_agent = create_deep_agent(
tools=[get_portfolio, get_officers, get_retirement_plans],
system_prompt="You are the Investments specialist for XYZ Bank..."
)
products_agent = create_deep_agent(
tools=[get_credit_cards], # sparse now, grows over time
system_prompt="You are the Products specialist for XYZ Bank..."
)
# Gateway knows nothing about tools — only about agents
gateway = create_deep_agent(
tools=[
branch_agent.as_tool(name="branch_atm_agent"),
investments_agent.as_tool(name="investments_agent"),
products_agent.as_tool(name="products_agent"),
],
system_prompt="""You are the XYZ Bank assistant gateway.
Parse the user's intent, delegate to the right domain agent(s),
and synthesize a unified response. Never answer directly — always route."""
)
Dlaczego to działa skutecznie
Gdy bank dodaje nowe funkcje, brama i inne agenty domenowe pozostają niezmienione. Można dodać narzędzie do odpowiedniego agenta domenowego lub stworzyć nowy, np. do obsługi pożyczek lub zwalczania oszustw, i zarejestrować go w bramie. Każda zmiana dotyczy tylko jednej domeny.
Porównaj to z „lasem narzędzi”. Agent posiadający 30 takich narzędzi nie ma świadomości swojej domeny i może wywołać funkcję get_retirement_plans podczas odpowiadania na pytanie o godziny pracy bankomatu, po prostu dlatego, że obie te czynności należą do jego zakresu działania. Agenci domenowi unikają tego, nadając każdemu z nich precyzyjną tożsamość poprzez specjalne instrukcje systemowe oraz zestaw narzędzi. Agent, który wie, kim jest, podejmuje bardziej trafne decyzje w swojej specyficznej dziedzinie.
Potrzebny test: jeśli spierasz się o to, czy dany narzędzie należy do agenta A, czy do agenta B, oznacza to albo, że narzędzie robi zbyt wiele i powinno zostać podzielone, albo że potrzebny jest trzeci domen. Granica ta powinna być tak oczywista, jak wiedza o tym, czy pytanie skierować do kierownika oddziału, czy do doradcy inwestycyjnego.
Otwarte pytania
Pozostają dwie kwestie: czy zaawansowani agenci w dużej mierze zależą od wyboru podstawowego modelu oraz czy można z ich pomocą stworzyć kompletną rozwiązanie end-to-end. Odpowiedź na drugie pytanie brzmi „tak”, a naturalnym następnym krokiem jest praktyczne zbudowanie tego scenariusza bankowego.
Powiązane materiały
- Obserwowalność dla agentów AI w przedsiębiorstwach przy użyciu Langfuse i OCI — Dlaczego logi, metryki i ślady nie wystarczają dla agentów GenAI oraz jak śledzić prompty, wywołania narzędzi, tokeny i sesje za pomocą open-source Langfuse w OCI Agents.
- Inżynieria contextu dla agentów AI działających przez długi czas: wzorce i bufor KV — Dlaczego kontekst agenta pogarsza się podczas długotrwałej pracy i jak na to zadziałać: zapisywanie, selekcja, kompresja, izolacja, aspekty ekonomiczne bufora KV oraz różnice między trzema produktami.