Агент-планавальнік на LangGraph: план, выкананне, перапланаванне, справаздача
Агент-планавальнік з чатырох вузлоў LangGraph для фінансавых даследаванняў: структураваныя планы, рэестр інструментаў з прасторамі імёнаў, ліміты перапланавання і прыклад запуску з трасіроўкай.
Крыніцы: Your AI Agent Isn’t Smart. Here’s How to Build One That Actually Thinks
Большая частка агентаў — гэта фактычна простыя ланцугі запытанняў пад маскай
Гэта некалькі некамфортных фактов аб агентах AI: багато з іх — гэта проста паўэліцаваныя ланцугі запытанняў, адзначаныя як «агенты». Схема знаёмая: сістэмны запыт, калькі засобаў і, можа, цыкл ReAct, і рэзультат называецца агентам. У дэманстрацыях і ў спрыяючых умовах такі падход працюе. Але калі засоб выдае памылку, даныя выглядаюць дзівнаюча, або запыт трэба адпрацаваць больш чым за тры крокі, весь прыем прыпыніваецца.
Альтэрнатыўнае рашэнне — агент планавання. Ён стварае полны план даследжэння прытым, пры выкарыстоўванні будзь-якога інструмента, працуе па гэтым плану па шагоў і, калі проміжныя рэзультаты суперчаць ачакванням, перапісвае тое, што засталося. Дэманстрацыя — гэта фінансавая сістэма даследжэння. Дайце ёй запіт на простай англійскай мове, напрыклад: «Пораўняйце кацэннія NVDA і AAPL і скажыце, калі з іх зараз выглядае лепшая», і ёна стварае багаташаговы план, выконвае кожны шаг за дапамогою інструментаў з дадзеннямі, практычна сама лагодзіце ся, калі ў чымсь з’яўляюцца проблемы, і піша справаздача у стылі аналітыка. Ёна працуе на LangGraph, можа выкарыстоўваць хмарныя мадэлі праз Groq або локальныя праз Ollama, і ўмішчаецца прыблізна у чатыры файлы.
Чаму просты ReAct не падходзіць
ReAct (Reason-Act-Observe) — гэта шаблон, з якога зазвычай пачынаюць большасць агентаў. LLM разумее свой наступны крок, вызывае інструмент, чытае атрыбуты, якія ўзьявіш, зноў разумее і вызывае наступны інструмент. Гэты падход популярны, просты і падходзіць для невялікіх задач.
Асновная слабасць — жада, адколі агент на модэлі ReAct плануе толькі адны крок наперад. Калі папросіць даныя па пяці акціях за трохі метрыкаў плюс апошнія новыні, ён проста пачынае з, скажамо, коефіцыента P/E акцій NVDA, і першы рэзультат адвярае яго увагу на іншыя аспекты. Адны з пратыпаў выкорыстаў семь вызоў інструментоў для кожнай метрыкі Tesla, перш чым запамятаў задачу пораўняць кілька акцій, а яго заканчыцкі атлас складаўся з кантакту пра доходы Tesla плюс адной фразы пра іншыя акціі.
Прычына проблемы не ў можымасці модэлі, а ў яе архітэктурэ. Калі падчас аднаго працэса аналізу трэба выбраць, што доследжваць, як гэта зрабіць і як расценіць рэзультаты, ніякі з гэтых рашэнняў не атрымлея правільнага акцэнту. Агент планавання раздзеляе мысленне і дзеянне: спачатку плануе, потым выкананае, а пасля пераканваецца, чы план все ўсё актуальны. Кожны вузел обрабоцвае адну задачу, і яны выкананыя адні за іншымі.
Чатыры вузлы і адна петля
Агент планавання — гэта спрамованы граф з чатырма вузламі, падобны дыяграме прабегу, дзе кожны блакет обрабоцвае адну задачу і перадае стан далей.
START --> Planner --> Executor <--> Replanner --> Reporter --> END
- Planner прыёмляе запыткі корыстніка і стварае структураваны, пашагоўны план даследжэння. Кожны пашаг пераказвае, які інструмент трэба выкліканы, якія ўсілкі і чаму.
- Executor берае наступны пашаг, выклікае заданы інструмент і фіксуе рэзультат у спецыяльным дзяленні для запісаў.
- Replanner пераглядае ўсё, што было зібрана да гэтага часу пасля кожнага выканання. Калі інструмент дапусіў памылку або даныя паказваюць нечаканае, ён перапісвае застаўшыяся пашагі. У іншым случае ён не чыніць нічога з планам.
- Reporter ператварае всі запісы з дзялення для запісаў у заканчальны аналітычны атлас, у якім ёсць конкрэтныя цыфры і рэкамендацыі.
Тэкст праекта кантролюецца цыклам Выкананнік-Планавальнік. Два вузлы адна за іншым выкананыя дзеянняя, пакуль не будзе створан план, і гэта зміна спрыяе самаўтвэрджаючымся практыкам, адтуды пасля кожнага дзеяння агент можа пераглянуць свае рашэнні.
Стан: спяльная памяць
У LangGraph станам ёсць усё – спяльная памяць, якая перадаецца между вузламі. Полная вялічына:
import operator
from typing import Annotated, TypedDict
from pydantic import BaseModel, Field
class StrategyState(TypedDict, total=False):
"""Global state that flows through the LangGraph nodes."""
query: str
plan: list[dict]
scratchpad: Annotated[list[dict], operator.add]
current_step: int
final_report: str
replan_count: int
У гэтым стане query зберагае первоначальны запіт корыстніка без змян, plan — абаротаваны спіс крокаў, scratchpad скупляе рэзультаты кожнага з інструментаў, current_step паказывае на пункт у плане, а replan_count падтрымлівае максімальны ліміт MAX_REPLANS.
Важна анотацыя Annotated[list[dict], operator.add] у scratchpad. Яе reducer, operator.add, паведамляе LangGraph прыўяжваць новыя елементы і залішаць існуючыя на своіх месцах. Калі Executor вяртае {"scratchpad": [new_entry]}, LangGraph прыўяжвае яго да тэкушчага спіска, таму вузлы ніколі не обрабоцваюць спіскі вручную і не выклікаюцца багі з мутацыямі.
Структураваныя планы і рашэнні
«The Planner» ніколі не выдае просты тэкст. Яго выходам являецца модэль Pydantic, таму LLM павінен ствараць планы у фармаце, які можа аналізаваць:
AVAILABLE_TOOLS_TEXT = """
- get_metrics(ticker, metric?): Return stock metrics. 'metric' is optional
(P/E, EPS, Revenue, Market Cap, Sector).
- search_news(ticker): Return recent news headlines for a ticker.
- compare_metrics(tickers: list, metric): Compare one metric across
multiple tickers.
"""
class PlanStep(BaseModel):
"""A single executable step inside an analysis plan."""
step_id: int = Field(description="Sequential step number")
tool: str = Field(
description=f"Tool to use. Must be one of:\n{AVAILABLE_TOOLS_TEXT}"
)
args: dict = Field(description="Arguments for the tool call")
purpose: str = Field(description="Why this step is needed")
class Plan(BaseModel):
"""The full plan generated by the planner node."""
goal: str = Field(description="The overall analysis goal")
steps: list[PlanStep] = Field(
description="Ordered list of steps to execute"
)
Поле purpose апроцэнаваецца як болей ціннае, чым чакалася. Яно паведамляе Replannerу, чаму існуе тыя чы ілі што саме яны выканаюць. Калі замест простага „call compare_metrics,“ пісаецца „Compare P/E ratios to identify relative valuation,“ Replanner лепшае можа вырашыць, чы рэшыцца застаўіць, змяніць чы адмовіцца ад данага крока.
У Replannerа ёсць свойяя схема:
class ReplanDecision(BaseModel):
"""Output of the replanner node."""
reasoning: str = Field(
description="Analysis of current progress and findings"
)
should_replan: bool = Field(
description="Whether the plan needs modification"
)
updated_steps: list[PlanStep] = Field(
default_factory=list,
description="Remaining steps if replan is needed. Empty if no changes.",
)
Якшто зробіць should_replan логічным значэннем, гэта змусіць LLM прыйняць адзін з двух вароў: план зменшыцца чы не? Якшто залішыць LLM пэўную свабоду дзеяння ў структураваным выходзе, ён будзе дзейсці неаўтаматычна ў кожны момент.
Сістэма інструментаў
Тры інструментаў фінансавых даследжэнняў працуюць на рэалістычных сімуляваных даных. У рэальных умовах вікорыстоўваліся бы рэальныя запыты API, але сімуляваныя даныя маюць вялікую перавагу пад час стварэння: дэтэрміністычнае адлучэнне бягаў. Калі агент дзейсціць незвычна, адразу стае ясна, чы прычына крыўды крыўціцца ў яго логіцы чы ў API.
Дзеянні патэрн дызайну, які заслугоўвае на большую увагу, — гэта рэйстры інструментаў, якія ведаюць прастор імен; яго вікорыстоўваюць замест таго, каб даваць кожнаму вузлу кожны інструмент:
from langchain_core.tools import BaseTool
from typing import Iterable, Mapping, Any
class ToolRegistry:
"""Namespace-aware container for LangChain tools."""
def __init__(self) -> None:
self._tools_by_toolset: dict[str, dict[str, BaseTool]] = {}
def add_tools(self, toolset: str, tools: Iterable[BaseTool]) -> None:
bucket = self._tools_by_toolset.setdefault(toolset, {})
bucket.update({t.name: t for t in tools})
def get_tools(self, toolset: str) -> tuple[BaseTool, ...]:
return tuple(self._tools_by_toolset.get(toolset, {}).values())
def invoke(
self, toolset: str, tool_name: str, tool_args: Mapping[str, Any]
) -> Any:
t = self._tools_by_toolset.get(toolset, {}).get(tool_name)
if t is None:
raise ValueError(
f"Unknown tool '{tool_name}' in toolset '{toolset}'"
)
return t.invoke(dict(tool_args))
Рэгістрацыя выконвалася ў прасторах імен "planner", "executor" і "replanner". Усе інструменты ўвідны для Planner, ўсёлякія планавання можа выконваць з іхаючымі, але толькі Executor можа іх вызваць. Нават калі баг у Replanner якім-і чынам выдалі вызов інструмента, рэгістры забарыць гэты вызов, таму што у гэтага прастора імен няма прав на вызов. Гэта і ёсць контроль даступу на аднойчыні з ролямі для агентаў, а раздзелэнне абавясцей таксама служыць механізамам безпекі, які блакуе небажаныя змяны стану пад час планавання.
Узел Planner
def planner_node(state: StrategyState) -> dict:
"""Create a step-by-step research plan using structured output."""
planner = model.with_structured_output(Plan)
prompt = PLAN_PROMPT.format(
available_tools=AVAILABLE_TOOLS_TEXT,
ticker_choices=ticker_choices_text(),
metric_choices=metric_choices_text(),
query=state["query"],
)
plan: Plan = planner.invoke(prompt)
steps = [s.model_dump() for s in plan.steps]
return {"plan": steps, "current_step": 0}
model.with_structured_output(Plan) выклікае у LLM адказку у вачынку JSON, сумесную з Pydantic, а некорэктная адказка проста выклікае павторную спробу. Гэта значна перавышае эфектывнасць парсінгу звычайнага тэксту за дапамою regex.
Нормы ў запіце плану
PLAN_PROMPT = """\
You are a financial research planner. Given a user's analysis request,
create a step-by-step research plan using the available tools.
Available tools:
{available_tools}
Rules:
- Use only the tools listed above.
- Every plan step must be executable with one of those tools.
- When a tool accepts 'ticker' or 'tickers', use only these exact values:
{ticker_choices}
- When a tool accepts 'metric', use one of these exact values:
{metric_choices}
- There are no other tools available. Final synthesis is handled separately.
Create an efficient plan. Group related lookups. Aim for 4-8 steps.
User request: {query}"""
Два моменты выдзеляюцца. У запіту пераказаны дзеяжыя значэнні параметраў, таму LLM не павінен здагадвацца, якія тыкеры чыста паметры існуюць. Гэта можа быць найэфектывнейшы спосаб прыбліжэння да рэальнасці для агентаў, якія выкорыстоўваюць інструменты. Без гэтага мадэль адважна плануе крокі на кшталт get_metrics(ticker="BITCOIN", metric="vibes"), а потым выглядае здзівленайя, калі яны не выконваюцца.
Іншы момент — рэчыца "Іншых інструментоў няма". Калі яе няма, LLM-ы выдумваюць крокі на кшталт analyze_sentiment(ticker="NVDA") чыста generate_report(findings=...) — інструменты, якіх не існуе.
Інструкцыя «старайцеся выконваць 4–8 крокаў» ўмышлена ёсць мяккай. Жорсткія ліміты, такія як «роўна 5 крокаў», мелі працоўны эфект — прымусвалі простыя запіты выканваць зайвыя крокі, а складныя запіты — запхвалі ў перанасытаныя крокі. Дыяпазон дае модэлю можлівасць адаптавацца, і калі ёсць толькі рэкамендацыі заместо обавязковых правілаў, ён зазвычай прыме правыя рашэнні.
Узел Выканавальнік
Узел Выканавальнік умышлена ёсць найпростэйшым: ён берае наступны крок, запускае інструмент праз рэжыстр і зберагае рэзультат.
MAX_STEPS = 12 # Safety limit on total steps
def executor_node(state: StrategyState) -> dict:
"""Execute the next pending step from the plan."""
plan = state.get("plan", [])
current_step = state.get("current_step", 0)
if current_step >= len(plan):
return {}
if current_step >= MAX_STEPS:
return {"current_step": len(plan)}
step = plan[current_step]
tool_name = step["tool"]
tool_args = step["args"]
try:
result = str(
TOOL_REGISTRY.invoke(
AgentName.EXECUTOR.value, tool_name, tool_args
)
)
status = "Error" if result.startswith("Error:") else "Success"
except Exception as exc:
result = f"Error: {exc}"
status = "Error"
entry = {
"step": current_step + 1,
"tool": tool_name,
"args": tool_args,
"result": result,
"status": status,
}
return {
"scratchpad": [entry],
"current_step": current_step + 1,
}
MAX_STEPS = 12 выступае як строгія межа. Калі Replanner будзе продовжваць дадзіць новыя крокі або застрагне, агент не можа безканцэсантна выкарыстоўваць крэдыты API. Калі досягнута гэтая межа, Executor ставіць current_step на значэнне len(plan), і працэс пераходзіць да Reporterа з саставленымі да гэтага часу дадзеннямі.
Пра бягучыя проблемы ведаюць за стандартам: status = "Error" якщо result.startswith("Error:") іншым чынам "Success". Кожны з трохох інструментаў дадае сваеяе паведамленнія пра адказы прэфікс "Error:", таму Executor можа пазначыць проблему без паводлівання JSON або спецыяльнага адрабатавання асобых выключэнняў. Replanner чытае гэты статус, калі выбірае між праказой зноў або скорэкаваным планам.
Узел Replanner
Этый вузел паказывае разлік межа агентам для планавання і простым оркестраторам. Пасля кожнага запуску інструмента ён аналізуе всі дапамогі і выявляе, чы рэшткі плану ўсё ўсходзіць у сэнс:
MAX_REPLANS = 2 # Prevent infinite replanning
def replanner_node(state: StrategyState) -> dict:
"""Review progress and optionally modify the remaining plan."""
plan = state.get("plan", [])
current_step = state.get("current_step", 0)
replan_count = state.get("replan_count", 0)
scratchpad = state.get("scratchpad", [])
remaining = plan[current_step:]
if len(remaining) = MAX_REPLANS:
return {}
scratchpad_text = "\n".join(
f"Step {e['step']}: {format_tool_call(e['tool'], e['args'])} "
f"-> [{e['status']}] {e['result'][:150]}..."
for e in scratchpad
)
remaining_text = "\n".join(
f"Step {s['step_id']}: {format_tool_call(s['tool'], s['args'])} "
f"- {s['purpose']}"
for s in remaining
)
replanner = model.with_structured_output(ReplanDecision)
prompt = REPLAN_PROMPT.format(
goal=state["query"],
scratchpad=scratchpad_text,
remaining_steps=remaining_text,
)
decision: ReplanDecision = replanner.invoke(prompt)
if decision.should_replan and decision.updated_steps:
new_steps = plan[:current_step] + [
s.model_dump() for s in decision.updated_steps
]
return {"plan": new_steps, "replan_count": replan_count + 1}
return {"replan_count": replan_count + 1}
Паглядзіце на e['result'][:150]. Апарат Replanner бачыць кожны рэзультат інструмента, скорачаны да 150 сімваў, таму што ёму патрэбны толькі галоўныя моменты, а не весь JSON-дача, тады калі журналіст пазней отрымае нескорачаныя даны. Токены зберагаюцца там, дзе дэталі не маюць значэння, і выкарыстоўваюцца там, дзе яно маюць.
Калі выканана перэпланаванне, plan[:current_step] + [s.model_dump() for s in decision.updated_steps] захоўвае завершаныя крокі і заменяе толькі незавершаныя, не параджаючы історыю без змян.
Запрос на перэпланаванне
REPLAN_PROMPT = """\
You are a financial research planner reviewing progress on a research task.
Original goal: {goal}
Completed steps and findings so far:
{scratchpad}
Remaining steps in the plan:
{remaining_steps}
Based on the findings so far, should the remaining plan change?
If an expected tool failed or revealed something unexpected, add a step
to investigate.
If a step is now redundant, remove it.
Use only the available executable tools already shown in the plan.
Do not add recommendation, summary, or report-writing steps."""
Пасульны радок выпрацоўвае важную працу. Як толькі адмахнуцца ад фразы «Не дадаваць рэкамендацый, падсумакоў чы крокаў пісьмовага стварэння справаздачы», прыстройка Replanner дадае крок сінтэзу да кожнага плану, хоць гэтыя обавязкі належаць прыстройцы Reporter. Падказкі павінны адстаўляць межы межы між вузламі.
Ліміт MAX_REPLANS = 2 ўзьяўся ідэальна. У аднай з ранніх версій для задання з трыма крокамі было выкарыстана шасць раундоў перэпланавання, пры чым LLM знаходзіла «паліпшэнні», якія нічога не паліпшалі. Два раунды дастатковы для справжняй самакорэкціі, напрыклад, для рашэння проблемы з неякім інструментам чы выдалення зайвага крока, без можлівасці аналітычнага паралічу. У певны момент агенту павінна быць сказана, каб ён перастаў думаць і завершыў працу.
Рэпортар атрымлее цэлы некасаны скрапбэд і піша структураваны адчытак у фармаце Markdown. У яму выклікаецца model.invoke(prompt).content, што дае просты тэкст, а не структураваны выход, таму ЛЛМ можа сама адпрацаваць інфармацыю так, як яна сачытае за потрэбным. Адна інструкцыя дае найбольшы эфект: «Будзьце конкрэтны, наводзіце цыфры з дадзеных». Без яе адчытакі стаюць расплывчатымі, напрыклад, пішацца «NVDA паказвае сільныя фундаменталы», пры чым не наводзяцца рэальныя показнікі P/E і выручкі.
Спаўненне ўсьго ў LangGraph
Хутчэй тут суцэльваецца чатыры вузлы:
from langgraph.graph import StateGraph, END
from enum import Enum
class AgentName(Enum):
PLANNER = "planner"
EXECUTOR = "executor"
REPLANNER = "replanner"
REPORT = "report"
def build_graph():
"""Build and compile the LangGraph planning-agent workflow."""
workflow = StateGraph(StrategyState)
workflow.add_node(AgentName.PLANNER.value, planner_node)
workflow.add_node(AgentName.EXECUTOR.value, executor_node)
workflow.add_node(AgentName.REPLANNER.value, replanner_node)
workflow.add_node(AgentName.REPORT.value, report_node)
workflow.set_entry_point(AgentName.PLANNER.value)
workflow.add_edge(AgentName.PLANNER.value, AgentName.EXECUTOR.value)
workflow.add_edge(AgentName.EXECUTOR.value, AgentName.REPLANNER.value)
workflow.add_conditional_edges(
AgentName.REPLANNER.value,
should_continue_execution,
{
AgentName.EXECUTOR.value: AgentName.EXECUTOR.value,
AgentName.REPORT.value: AgentName.REPORT.value,
},
)
workflow.add_edge(AgentName.REPORT.value, END)
return workflow.compile()
def should_continue_execution(state: StrategyState) -> str:
"""Return the next node name after re-planning."""
if state.get("current_step", 0) >= len(state.get("plan", [])):
return AgentName.REPORT.value
return AgentName.EXECUTOR.value
Графік працы выглядае па-разлічна ад англійскай мовы. Планавальнік пераходзіць да Выконавця, Выконавець — да Перапланавальніка, а Перапланавальнік, калі застаюцься крокі, пераходзіць знову да Выконавця, а калі все завершанае — да Звярніка. Звярнік пераходзіць да Канцэлярскага канца.
Энумерацыя AgentName здаецца незначной, але ёй можна паверыць. Простыя стрынговыя літэралы, такія як "planner", распаўшыся па кодзе, спрыяюць памылкам у напісанні, а "plannr" бы таямна стварыў нез’ўязаны вузел. За дапамогою энумерацыі памылка стае відна ў момент імпорту.
Механізм маршрутацыі пераканальваецца ў адной умове: чы всі крокі завершаны? Калі current_step >= len(plan), керуванне пераходзіць да Звярніка, а інакш — знову да Выконавця. Цыкл завершваецца таму, што current_step зрастае з кожным выкананнем, а MAX_STEPS = 12 обмежвае колькасць крокаў, нават калі Перапланавальнік дадае новыя крокі.
Адна запытка, працавана
У зразку запіту прасіцца, каб агент разглянуў компаніі NVDA і AMD, практычна вылічыў для яных коефіціянты P/E і практычна аналізав апошнія новыні, а пасля выбраў адну з іх.
Планаванне. Програма-планавальнік стварае пяць крокаў: повныя показнікі для NVDA, повныя показнікі для AMD, прымітныя порэвананні коефіціянтав P/E, пошук новын для NVDA і пошук новын для AMD. Спачатку практычна паказаны індывідуальныя профілі, ўсё для болей чыткага абразу, пасля — прымітныя порэвананні, а новыні — апошнія, таму што яны ўжо ўжо ўзмацнюючы кантэкст, а не основныя даныя для ацэнкі.
Выкананне. Крокі 1 і 2 вяртаюць чысты JSON з показнікамі, і ў кожны раз Програма-планавальнік паўтарае перакананне, што даныя правільныя і план не змяніўся. Крок 3 вяртае порэвананне значэнняў коефіціянтав P/E:
{
"metric": "P/E",
"values": {
"NVDA": 58.3,
"AMD": 102.5
}
}
Оба значэння ўсё ў прымесці і ў правільным фармаце, таму нічага не патрэбна перапланаваць. Крокі 4 і 5 кожны вяртаюць по тры новыя статыі. Калі крок 5 завершыцца, current_step будзе равны len(plan), і сістэма перадае керуванне Рапортавальніку.
Рапорт. Прымавшы пяць заполненых запісаў, Рапортавальнік запісвае конкрэтныя цыфры; напрыклад, K/P NVDA у розмерэ 58,3 працоўна проты 102,5 у AMD, што указвае на тое, што NVDA мае лепшую абсалютную цэну, незважаючы на большую рыночную капіталізацыю апошней у розмерэ або 2,8 трыльйона долераў. Полны працэс выканання займае або 8-10 секунд на Groq і або 30-40 секунд на локальным Ollama з вядомаю 4B-модэлю.
Найважлівэйшыя абнаўленні
Чынная версія выкарыстоўвае фальшывыя даны, але архітэктура гатова да практычнага выкарыстоўвання. Найважлівейшыя ўсьмо тры абнаўленні:
- Рэальныя фінансавыя даны. Заменіце пошук у словніку вызовамі служб Yahoo Finance або Alpha Vantage. Падпісы застаюцца такімі ж, а змінююцься толькі тэлы функцый, завдака шаблону дэкаратара
@tool; такім чынам Planner і Executor ніколі не дазнаюць, чыі ці цыфры выйшлі з файла у фармаце JSON чы роштыні REST API. - Пастая памяць. Сэргодні тэмпарарыйя для працы існуе толькі пры адной працы. За дапамою сховішча вектарных даных, такога як ChromaDB або Pinecone, агент мог бы ацэніць пакульнія аналізы, адпавядаючы на запыткі на кшталт „Як NVDA парабяляецца з тым, што мы бачылі мінулага месца?“ і стаць развіваючымся аналітыкам, а не інструментам без стану.
Што структура не можа запрацаваць
Цыкл планавання-выканання-перапланавання выпрацоўвае сваю задачу. Структураваны выхід дапамагае агенту заставацца на правым шляху, рэестры інструментаў запобiegаюць хаосу, а меры безпекі стрымваюць неконтрольаваныя выдаткі. Дызайн застаецца стабільным, а код застаецца апранутым.
Нават так, інтэлігэнцыя сістэмы в цэлым залежыць ад LLM, які знаходзіцца пад структурой. Моцнейшыя мадэлі ствараюць лепшыя планы, болей легка адчуваюць аберанціі пад час перэпланавання і прадаюць болей дэталізаваныя аналізы, тады калі слабейшыя мадэлі проста следуюць заданай структуры і даюць сярэднія рэзультаты. Граф не можа зробіць мадэль умнейшай, а ўсё, што ён робіць, — гэта дае модэлі крашчую рамку для выкарыстоўвання інтэлігэнцыі, якая ў ёй вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі час вялікі ч
- Паспрацаванне з DS-STAR: агент дадзейнаўскай наукі Google і прычыны ўспеху яго падходу — Дэтальны апісанне агента дадзейнаўскай наукі DS-STAR ад Google: яго семь модуляў, цыкл стварэння атласа DS-STAR+, опублікованыя запіты, рэзультаты тэстаў і існуючыя абмежэнні.
- Агент AI для DevOps на Python: LangChain, Claude і інструменты Guarded Bash — Стварэнне агента, які запускае скрыпты bash, чытае логі і выконвае запыты да Kubernetes: спачатку правілы безпекі, потым інструменты, цыкл ReAct, памяць, обгортка FastAPI і способы выправлення частых проблем.