Будуем абвязку DeepAgents: дазволы, субагенты і пацвярджэнне чалавекам
Будуем абвязку DeepAgents для планавальніка сістэмнага дызайну: файлавыя бэкэнды, правілы доступу, субагенты, фільтры пацвярджэння чалавекам, навыкі і MCP-інструменты.
Крыніцы: The DeepAgents Architecture, Part 2: Building the Agent Harness
У дасяглівых матэрыялах іх лёгкая спадзяваць, але ў практыцы іх важкааць оцаніць. У цім апісанні рассказваецца пра тое, што адбылася, калі архітэктура DeepAgents была выкарыстоўана для стварэння цэлага, функцыональнага прыемніка, пры чым былі выкорыстаны рэальныя багатыяэтапныя дыялогі з праектаванням, а рэзультаты пераканаліся з адпаведнымі доказамі. Гэта практычныя запытанні: як дасяглівыы прыемнік карацецца з файламі і правамі, як выглядае дэлегаванне, як функцыонуе затверджэнне з боку чалавека, і дзе ўсё ж такі адбываюцца прычыны памылак модэлю, нават калі каркас выпалоў сваю ролю.
Эты ўтварэнне ўособліва падходзіць для арганізацыяў, якія выкананяюць свае задачы з апрацоўкі дадзэнняў і штучнага інтэлекта на платформе Azure за дапамогою Databricks. Такі выбар быў няканонічны. Чы ўважаць канкрэтны інструмент „натыўным“, наразе неясна, аднойчы як Databricks і тэхналогіі Azure AI ад Microsoft сталаўся настолькі тыснай зв’язанымі, і саме такая неяснасць, якая вырастае ўнаследке мнагаэтапнага прыему рашэння, і ёсць там, чым павінна дапамагаць гэтая архітэктура. Полны тэкст публікуецца як абявлены рэпазітарый.
Настройка
git clone https://github.com/shubhodayahampiholi/system-design-planner.git
cd system-design-planner
uv sync
cp .env.example .env # fill in real API keys
Патрэбны Python 3.11 або новейшая версія, а таксама каманда управління пакетамі uv. У прыкладах выкарыстоўваюцца мадэлі як Anthropic, так і OpenAI, таму для правільнага выканання всіх заведамацтваў патрэбны клучы API для обох. Клуч Tavily і доступ да працоўнай зоны Databricks неабходны толькі для тых раздзялов, дзе яны выкарыстоўваюцца.
Файлы і кантроль даступу ў DeepAgents
Дзе знаходзяцца файлы агента
Ёнколкі агент не можа нічытаць, ні пісаць, яму патрэбна адна ўстанова для зберагання файлаў. DeepAgents прысвячае гэтаму кілька варыянтов бэкенда, сярод яых StateBackend, FilesystemBackend і варыянты, якія базуюцца на сховішчы або сэндбоксе. У гэтым праекце выкарыстоўваюцца два такіх варыянты з розных прычын.
Калі create_deep_agent() вызываецца без дадатковых аргументаў, агенту задаецца StateBackend, які зберагае файлы ў сэрвэрскім стане LangGraph агента. Паколькі гэты стан фіксуецца пасля кожнага крока, файлы дзейсна застаюцца на месцы, паколькі трывае розмова. Але ёсць проблема: збераганне ўзаемна прыяўязана да конкрэтнага потока — тое, што запісана ў однам потоку, не ўзірмаецца ў іншам. Для багато застосоўваń гэта цэлкам правільна. Але тут так не ёсць, таму што агент павінен чытаць рэальныя даследныя дакументы з дыска, незалежна ад таго, у якой розмове ён знаходзіцца.
FilesystemBackend рашае гэту проблему. Ён направляе агента да рэальнай папкі, і кожна операцыя чытання, запісу чы перыядаўвання стосуецца рэальных файлаў, якія застаюцца пасля завершэння працы. Усі прыклады выкананы на адной функцыі-фабрыканцы:
# src/system_design_planner/agent.py
from deepagents import create_deep_agent
MODEL = "claude-sonnet-5"
def build_planner_agent(*, system_prompt=PLANNER_SYSTEM_PROMPT, **kwargs):
return create_deep_agent(model=MODEL, system_prompt=system_prompt, **kwargs)
Кожны прыклад стварае свой агента праз тую функцыю. Калі трэбаецца рэальны доступ да файлу, вызов прымее backend=FilesystemBackend(root_dir=...). root_dir задае межу, в межах якой працюе агент – гэта спецыяльны корневы катэгорыя, з якой агент па значэнні не можа выйсці, нават калі ён спробуе такі шлях, як ../../. Чым саме можа займацца агент унутрь гэтай межы, тыя операцыі над якімі шляхамі, – гэта адзінокая кантэкст, які FilesystemMiddleware рэгулюе праз правільнія.
Адліквідаванне таго, чым можа займацца агент
Доступ да папкі – гэта адна з рашынакоў, а точнае абмежэнне таго, што відбываецца ў ёй, – гэта іншая, не менш важлівая рашынака. DeepAgents рашыла гэтыя проблемы праз архітэктуру на базе ароганізаванага спіску правільняў, якія вказываюць, якія операцыі дазволеныя, забороненыя чы ўтрымваныя на чаканні явнага санкцыянавання ад корыстніка, па кожным шляху. Гэтыя правільнія ўпэўнююць работу агентаў у гэтым праекце:
# src/system_design_planner/permissions.py
from deepagents import FilesystemPermission
DESIGN_SESSION_PERMISSIONS = [
FilesystemPermission(operations=["read", "write"], paths=["/.env"], mode="deny"),
FilesystemPermission(operations=["write"], paths=["/knowledge_base/**"], mode="deny"),
FilesystemPermission(operations=["write"], paths=["/memory/AGENTS.md"], mode="interrupt"),
]
Правіла пераглядаюцца па парадку, кожна з іх з сваёй прычыны.
Першая не дазволяе агенту чытаць або запісваць файл .env, дзе знаходзяцца справжнія ключы API. Яна дыяе незалежна ад таго, што ўсё інша робіць агент.
Другая ператварае матэрыялы для адгуку з каталога knowledge_base/ у рэжым толькі для чытання. DeepAgents лічыць операцыю delete як запіс, таму тая ж правіла блакуе і відаленне, а не толькі змены, што значыць, што база дакладных дадзеных, на якую спыраецца агент, не можа быць таямніча пашкодзена яго сабеўнымі дзеяннямі.
Трэцяя мае найбольшую значымасць. Запісы ў файл памяці агента дазволены, але толькі пасля таго, як іх затвердзіў чалавек. Гэты механізм практычна рассказаны ў окрэмых раздзелах ніжэй.
Перагляд таго, чытае агент тое, што яму даўця
Нічыя з гэтых спосабоў не дапамагае, калі толькі агент не выкарыстоўвае іх правільна, і іх трэба перапрацаваць болей шчыльна, чым прыпускаецца. У папцы knowledge_base/ знаходзяцца чатыры короткія даследчыя дакументы, прызначаныя для розгляду кантролі ў Unity Catalog, тэхналогіі Mosaic AI, інтэграцыі з Microsoft Foundry і пытанняў, зв’язаных з сеткамі. Ёжчы пераканацца, што агент дзеўальна чытае іх і не выконвае прыпускі на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адваротнае на адварот
backend = FilesystemBackend(root_dir="knowledge_base")
agent = build_planner_agent(backend=backend)
result = agent.invoke({
"messages": [{
"role": "user",
"content": "List every file in your working directory, then give a one-line summary of what each one covers.",
}]
})
Рэзультатам было чатыры тачныя, адзінаковыя стасумарызаціі — по аднай на кожны файл. Паўедамленне пра нізкую доверлівасць у дакуменце пра ідэнтычнасць і сеткавыя звязкі засталося цэлым, а не было адчынена да болей упэўненага тону трох вялікіх стасумараў. Ход выканання паяснюе, чаму гэта мае значэнне: агент вызваў ls, ўбачыў, што існуе, а пасля для кожнага дакумента выканаў адзін вызов read_file — усьго чатыры, прычым ніжоўка слова з стасумараў не была напісана. Адпаведзь базавалася на рэальных чытаннях.
Дэлегаванне падагентам
Што значыць дэлегаванне тут
Дзеянні, які выконваець самастае, лепей падходзяць спецыялісту, чым калі іх трэба аднаёсіць да іншых задач, якія ужо трэба выконваць галоўны агент. DeepAgents падтрымляе гэта за дапамою сабагентоў – самастойных агентоў, яых галоўны агент можа запрашаць для выканання конкрэтнай задачы. Сабагент працуе ў сваёй саўстаяной ізольаванай асяроддзі, не бачачы всей історыі, якая прывела да запрошэння, і пасля завершэння выканання задачы падае рэзультат назад да таго, хто яе доручыў. Гэта ізоляванне стосуецца прыгожа кантэксту кантакту і не обавязкова распрастраńваецца на зберагачэнне, як паказвае абсцярнутая ніжэй дыскусія пра памяць.
Гэта дае практычныя выгоды. Кантэкст галоўнага агента застаецца сфокусаваным на загальнай задачы, а не на зборы ўсіх проміжных крокаў, якія віконаў спецыяліст, каб дастаць адпаведны адпаведзь. Іншая выгода часта застаецца непазначанай: паколькі кожны падагент налаштаваны самастойна, разныя падагенты можу працаваць на абсалютна разных мадэлях, выбраных па ўзмацненню таго, калі яму трэба выконваць задачу.
Разныя мадэлі для разных падагентаў
Не кожная задача падагента трэбуе найсупэльнейшай і найдорожэйшай мадэлі. У гэтым праекце адзін падагент існуе толькі для выкарыстоўвання фактов з дакументаў-аспамінаў — гэта механічная задача, якой не трэбуе глыбокага аналізу. У замяне таго, каб ён працаваў на модэлі, якая керуе рэштой сістэмы, ёму даецца меншая, дышэўшая мадэль, прыдатная для гэтай вузкай задачы:
from deepagents import SubAgent
REFERENCE_EXTRACTOR: SubAgent = {
"name": "reference-extractor",
"description": (
"Extracts structured, factual capabilities from the knowledge_base "
"reference files for a specific platform or topic. Delegate here "
"before proposing any subsystem design, so decisions are grounded "
"in verified platform facts rather than assumption. Do not use this "
"subagent for design reasoning or tradeoffs - extraction only."
),
"system_prompt": (
"You are a fact-extraction specialist. Given a topic, find the "
"relevant file(s) in your working directory, read them, and return "
"ONLY a bullet list of the concrete facts relevant to that topic - "
"no narrative, no design opinions, no recommendations. If a fact is "
"explicitly flagged as an open question or unverified in the source "
"file, preserve that flag in your output rather than smoothing it "
"over into a confident-sounding statement."
),
"model": "openai:gpt-5.6-luna",
}
Поле model дазваляе гэта здарыцца. Кожны падагент можа назваць свой сабеўтар, незалежна ад таго, на чым працуе галоўны агент. У гэтым варыянце галоўны планавальнік працуе на Claude, тады як этот падагент працуе на модэлі OpenAI.
Аднак заданне значэння поля ёсць толькі канфігурацыяю, і гэта не паводзіцца да таго, што запыткі падаюць там, дзе трэба. Для гэтага патрэбна пераглядка таго, што на самай працэ выйшла. За дапамогою інструментаў для трэйсінгу, якія дазваляюць пераглядаць выконанне агента па кроках, запыткі, якія выканалі галоўны агент, былі показаны пад назвай Claude з самага пачатку і да канца, тады як запыткі, якія былі выкананы падагентам для выкарыстоўвання інфармацыі, былі показаны пад назвай модэлі OpenAI, заданай у яго канфігурацыі. Гэта ўзнікла на рэвэлю падаўцы, якая была выканана і можа быць пераканана, а не тое, што было проста заявлена ў кодзе.
Падагент за замовчаннем зберагае свою сябецю памяць
Ізоляцыя ў DeepAgents — гэта свядомы выбор у дызайне, і яе наследкі выходзяць за межы таго, чаго большасць людзей спачатку чакае. Падагент мае свой сае кантэкст, і ён таксама не мае автаматычнага доступу да нічога, што знаходзіцца ў памяці галоўнага агента, нават да таго, што ўжо стосуецца безпасованага задачы. Доступ павінен быць наданы явна.
Зазвычай гэта правільны стандарт, адколі падагенту не трэба пераглядаць усё, што запісаў галоўны агент, толькі каб выконаць адна конкрэтная задача. Але калі задачэ залежыць ад рашэння, якое ужо было прымечана, доступ павінен быць наданы спецыяльна:
def build_governance_specialist(backend) -> SubAgent:
from deepagents.middleware.memory import MemoryMiddleware
return {
"name": "governance-specialist",
"description": (
"Reasons about Unity Catalog governance, lineage, and the "
"Databricks-Microsoft Foundry governance boundary for this "
"architecture."
),
"system_prompt": (
"You are a governance specialist for an Azure + Databricks AI "
"architecture. Before answering, check /memory/AGENTS.md for any "
"recorded scoping decisions - they are binding constraints on "
"your recommendation, not suggestions."
),
"middleware": [MemoryMiddleware(backend=backend, sources=["/memory/AGENTS.md"])],
}
Этот элемент middleware адмініструець правы на доступ. Спецыяліст атрымлеў сабстычныя звязкі з файлам памяці, які выкарыстоўвае главны агент, і таму можа чытаць пярэйшыя рашэнні прычыму пачатку своіх выкладак.
Людская апраўка і стойкая памяць
Чаму дзеяннія іноды патрабуюць удзеле чалавека
Не кожна дзеянні, якія выконвае агент, павінна выконввацца без нагляду. Запіс у тымчасовы файл — гэта незначны крок. Аднак запіс рашэнні, якое будзе вважацца остаточным фактам у всіх наступных размовах, — гэта зусім іншая справа, адколі памылка не прыводзіць толькі да аднаго паслабленага адказу; яна можа таямна паўніста зменіць усе наступныя адказы. DeepAgents рашае гэтыя проблемы за дапамою удзеле чалавека: выбраныя дзеянні можна налаштавіць так, каб ўзстаўіць ўзнэманне ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ўзнэмання ў
Хутчэй, гэты механізм адпрацоўвае толькі адну дзеяннё — запіс у постацейнае файла памяці агента. Агент можа запропанаваць апдэйт калі толькі захоча, і нічога не запішваецца пакуль чалавек не схваліць.
Як функціонуюць затверджэнне і паўторны запуск
Ёсць два абавесці, якія павінны быць выкананы, каб гэта працавало. Перша — вышэйзгаданая правіла дазволу задае mode="interrupt" для запісаў у файл памяці. Другая, якую часта не бачаюць, — для паўзы патрэбен checkpointer, тое ўзраз, як сахаваць точны стан агента, каб яго можна было прызнесты і паўторна запустыць, а не перзначыць з нуля.
from langgraph.checkpoint.memory import MemorySaver
from langgraph.types import Command
checkpointer = MemorySaver()
agent = build_planner_agent(
backend=backend,
permissions=DESIGN_SESSION_PERMISSIONS,
checkpointer=checkpointer,
memory=["/memory/AGENTS.md"],
)
Калі агент прабуе выконаць запіс з контралем, выконанне насправды зупіняецца, а файл застаецца недастрым. У ныяму варыянце рэалізацыі, адлеглую дзеянню можна прачытаць з стану графа:
state = agent.get_state(config)
if state.interrupts:
action = state.interrupts[0].value["action_requests"][0]
print(f"tool: {action['name']}")
print(f"args: {action['args']}")
Выдрукаваецца самэй тычок інструмента, які агент хочаць выконаць, і самэй тэкст, які ён хочаць зберагчы, без жадных стыктуванняў. Рэвізор можа яго затвердзіць або адхіліць, пры чым павінен прадаць конкрэтную прычыну, якая будзе перадана назад модэлю:
decision = {"type": "approve"}
# or:
decision = {"type": "reject", "message": "Not yet ready — needs client confirmation first."}
result = agent.invoke(Command(resume={"decisions": [decision]}), config=config)
Калі все працуе ад пачатку да канца, гэта ўсуне проблемы. Праналожаны запіс зупініцца, яго незавершаны контэнт можа быць прачытаны цэлым прытым, прычым ніхто ўсё ўжо не вынісла рашэння, а пасля затверджэння запіс будзе адправлены. Гэта было падтверджана праз перагляд файлу на дыску пасля таго, а не праз паверненне ў думкі адноса да таго, што зрабіў агент.
Адхоўкі без адказу
У всіх прыганнях адказ на запрошанне выконаць певную дзеянне без адказу на пытанне, чаму гэта не адбылася, не змусіў мадэль запытацца, што пайшло не так. Мадэль стварыла правдападобную прычыну і продалае далей. У аднам з віпадкаў запіс у памяць быў адхілены без жадных адказаў, а стандартная паведамленне сістэмы для такой сітуацыі проста паведамляе, што дзеянне не выкананае і яго не трэба перапрыбавляць, як толькі корыстнік не папросіць. Тым не менш мадэль адразу ж перапрыбавіла модыфікаваную версію таго ж запісу, практыкуючы такую перапрыбавку на адной з прычын, якіх ніхто не назваў. Гэта ўсё, што мадэль робіць у адказ на тое, што ёй дае механізм адхілення. Сам механізм не вызвалі гэта напрэму.
Практычны урок просты: завжды паўязваць адхіленне з рэальной, конкрэтной прычыной. Чы гэта запобігае такой поведэнцыі ў кожным віпадку, не пераканалі окрэма, але гэта усунула самую явную праслойку, яку мадэль могла бы запаўніць сваімі здагадкамі.
Чаму патрабуецца адзяйчынай атрымліваць калькі рашэнняў
Другі аспект стосуецца таго, як адбываецца аб’еднаванне запраектаваных змян. Калі пад час дыялогу па дызайну выходзіць калькі супаўзялых заключэнняў, агент часта працоўвае з метай запісаць усе яны ў адной змяне: адны блакат новага кантэнту, адна атрымліванне, якае распаўляецца на ўсё, што ў яму ёсць.
Гэта эфектыва, але мае сваю цэну. У аднам з запісаных прыкладаў адна атрымлена змяна мела пяць пунктав. Чатыры з іх былі рашэннямі, якія чалавек явна падтвердзіў. Пяты быў пунктам, які агент запропанаваў сам, з фразай пра можлівасць адмовы ("вважаць гэта за з’ясаванае, калі не будзе іншага паведамлення"), а не як прымітны запіт, на які была дана адпаведзь. Ён залягаў у памяці з абоўсцю тымі ж упэўненымі формулюваннямі і выглядам аўтарытэту, які мелі чатыры падтверджаныя пункты.
Запіс быў узгоджаны цэлым. У практыцы узгоджэння няма нічога, што бы разлучыла адну, выведзеную на падставе прыпуску, пункт з чатырма падтверджанымі пунктамі, і людзі, якія швыдка працуюць з документамі з колькіма пунктамі, з большой верытабельнасцю зазначаюць чатыры чыстыя рашэнні, якія, як ім здаецца, былі прыняты, а не адны тыхія прыпуск, які знаходзіцца сярод іх у ідэнтычным формулюванні.
Гэта справжняя прыгожасць, якую трэба адрахаваць пад час праектавання. Участка чалавека тут дзейсніцца на рэвэлі заклекання інструмента, а не ўзгоджэння кожнага з твэрджэнняў у ям. Калі адна вызова write_file аб’еднвае калькі логічных рашэнняў, узгоджэнне самой вызовы означае узгоджэнне ўсіх іх. Даколі не будзе болей дзеяльнага узгоджэння, практычны спосаб захісту — адзін за адным рэгулярна пераглядаць кожны запрошаны запіс у памяці і не спрыяць узгоджэнню як формальнасці, калі механізм здаецца надзеяным.
Коордынацыя калькі спецыялістаў
Дазволае агенту выбраць, хто будзе рашаць пытанне
Усія падзеягенты былі пераблактаваны паляваннем імені спецыяліста, які мае быць выкарыстоўваны. У рэальных умовах так не працюе: чалавек задае запыт, а агент павінен сам адначасова выбраць, якія спецыялісты ўажлівы. Гэта было пераблактавана за дапамою аднаго запыту, які адночасна стосаваўся управління, інфраструктуры AI/ML, развяртання і сеткавання, без пярэдньага называння канкрэтных аднасобов.
Першая адпаведзь не была дэлегаваннем. Гэта быў набор запытаў для выяснення топалогіі сеткі, прыбліжнага масштабу і таго, як следуе адносіцца да конкрэтнай базы дадзеных, якія былі заданыя перад тым, як прымусіцца да дызайну. Гэта ўзгодна інстынктыўная падходжэнне, а не бягласць у дзеяннях, адтолькі калькі з гэтых адпаведзей змінююць, якія спецыялісты ўзагалі ўжо ўжыткавы, таму спачатку запытаць лепшая, чым здагадвацца.
Паралельнае дэлегаванне
Пасля таго, як на запытанні былі даўаны адпаведныя адказы, усе чатыро спецыяліста (управлінне, AI/ML, оркестрацыя і сеткавыя тэхналогіі) атрымалі заведаменні ад агента заодно, а не поштоўна. Ход задачы чыста паказвае гэта: чатыры запытанні пра дэлегаванне былі адправлены разам у аднам адказе.
Гэта мае значэнне не толькі з точкі зору эфектыўнасці. Гэта таксама сітуацыя, якая опісваецца ў прытварэнай скарге на даную платформу: калі калькі сабагента працуюць паралельна і адны з іх выклікае асключэнне, іншыя таксама можу быць анульваныя, і проблема не застаецца толькі ў тым, які выклікаў асключэнне. Усе чатыро спецыяліста ў цім запуску завершылі сваю работу успешна, таму такая проблема не выявілася. Але справжняя паралельная дэлегавання стварае самэ тыя умовы, пад якімі можа выявіцца гэтыя апісаныя багі.
Сінтэз, а не нараджэнне
Найцікавейшым рэзультатам не было сама дэлегацыя. Гэтым было тое, што зробіў галоўны агент пасля чатырох спецыялістскіх адказаў. Болей слабая рэалізацыя могла бы пакласты кожны адказ пад сваёй загалоўкай і на тым завершыцца. А тое, што насправды адбылася, было бліжэй да сінтэзу: фінальная рэкамендацыя сплела всі чатыры даныя ў адну цэлісную концэпцыю, і, што ўсё болей значны, выявіла тое, чаго ніхто з чатырох сам не змог бы выявіць.
Спецыяліст па сетках запропанаваў выход да зовнішней базы дадзеных праз адзін конкрэтны шаблон з’яўлення зв’язку. Спецыяліст па управлінні поясніў, як Unity Catalog аўтаматычна фіксуе лянгвіджэт натыўных служб Databricks. Для гэтага конкрэтнага шляху інтэграцыі этыя два падходы не паспеліваюць так чыста, як можа здавацца. Ёх выяўленне апяшваецца у тым, каб мяць у галаве оба адпаведныя рашэнні і бачыць, дзе яны не суспадзяюцца, і гэтае сінтэзаванне гэта зрабіла. У гэтым дызайне яна чытка апісала гэты прыемак і запропанавала ручны журнал аўдыту, каб гэта компенсаваць, не залішаючы гэта пытанне без адпаведнага рашэння і не ператвараючы яго на загальнае правіла ўсіх зовнішніх з’яўленняў зв’язку.
Два затверджаныя рашэнні, якія суперсчываюцца
Адзінаковы тэст паказаў ўсё бол трывожныя рэзультаты. Пры двух запісах у памяць, якія былі адбыты адразу адразу, кожны з якіх быў пераглянуты і затверджаны окрэма, рэкамендаціі ўжоць па аддачы модэляў суперасліся. Першыя рэкамендавалі вікорыстоўваць для аддачы галоўнага модэля API Foundation Model. Другія, затверджаныя чырза час у той жа сесіі, працавалі з вікорыстоўванням падготавленай пропускной здатнасі, пры чым чыста адмовіліся ад API Foundation Model, чым паўніста паўтарылі тое, што ўжо было зберажана.
Оба запісы пройшлі. Жадныя перагляды не выявілі суперасління, адтолькі кожны запіс быў ацэнены як самастойная прыемліваная прыдумка, без паўтарнага пораўнення з тым, што было зберажана кілька хвілін раней. Гэта іншая проблема, чым агрупаванне: агрупаванне стосуецца таго, насколькі рэшэнне можа быць дакладна затверджана, тады калі тут ідзе пра відсутнасць будзь-якай пераканальнай перагляду між адзінаковымі рэшэннямі, прынятымі ў той жа размове.
Адгукнуўшыся да гэтых двух нараджэнняў, можна выявіць адну прасоць: процедура затверджэння, якая выконвуецца тут, спытаецца, чы ўзяты ў распачатак запіс ўзяты сам па сабе, і не спытаецца, чы ён супараднаўся з усім, што вялікі час яўляецца даговораным. Хоць гэта ўскораная, простая сесія, якая ёсць адмежненнем, якое трэба явна прыменяць, сама процедура затверджэння не павінна вважацца за захоп, які будзе заханаваць вас.
Надаўчы агенту новых можлівасцей
Індывідуальны інструмент
Усё, што было выкорыстана да гэтага часу, апылвалася інструментамі, якія ёсць частынай DeepAgents: чытанне файлаў, запіс файлаў, дэлегаванне. Рэальныя прыклады зазвычай патрабуюць больш, і стварэнне індывідуальнага інструмента і яго перэдача агенту ёсць простым, праз той самы механізм, які фрэймворк выкорыстоўвае ўнутршна.
Праекту была патрэбна можлівасць, якойя нямае ў вбудованых рашэннях: спосаб тэставання, чы не стала застарэлай якая-небудзь інфармацыя ў статычным матэрыяле-аспанаванні. Файлы knowledge_base/ являюцца моментальным фота, які ўсё правільны ў момент стварэння і ніколі сама по сабе не апдэлююцца. Спецыяльны інструмент, падтрымваны жывым сервісам пошуку ў інтэрнэтэ, заполняе гэты прыём:
from langchain_core.tools import tool
from langchain_tavily import TavilySearch
_tavily_instance = None
def _get_tavily() -> TavilySearch:
global _tavily_instance
if _tavily_instance is None:
_tavily_instance = TavilySearch(max_results=3, topic="general")
return _tavily_instance
@tool
def check_current_standards(query: str) -> str:
"""Search the live web to verify whether a platform capability, naming,
or integration detail is still current.
Use this specifically to check something already pulled from
knowledge_base against what's true right now - not for open-ended
research.
"""
result = _get_tavily().invoke({"query": query})
return str(result)
Дэкоратар @tool і апісанне ў докстрангу ўлучваюць у тое, што робіць інструмент прызначаным для вжытку. Агент чытае гэта апісанне, каб выявіць, чыі інструмент падходзіць для выканання яго задач, таму чыстае, конкрэтнае апісанне мае такое ж значэнне, як і код, які знаходзіцца пад якім. Чырапленне інструмента да агента адбываецца за дапамою аднаго аргумента: build_planner_agent(tools=[check_current_standards]).
Тое, чы гэта справды стосуецца актуальной інформацыі, нельга падтвердзіць толькі на адказе, адколькі мадэль можа стварыць правдападобны, спецыфічны для пакульнай даты адказ, не вызываючы нічога. Праўдзівыя доказы знаходзяцца ў лог-файле. Калі было запрасіць па перакананні ў змяне назвы конкрэтнага продукту і яго ныявным статусе, лог-файл паказвае, што фактычна была вызвана функцыя check_current_standards і ўзвратзена рэальная рэзультат, на базе якой пазней быў створаны заканчычны адказ, укладаючы ў сябе таксама зворотны лік да конкрэтнага канечнага тэрміну, вылічанага правільна на аднойчыну з пакульнай датай.
Навыкі: процедуры, якія агент можа перысвайць
Іншым відам можлівасцяў ёсць пісьмовая інструкцыя: пасляпасныя нарады пра тое, як правільна распрацаваць певны тып сітуацыі, на вядома ад звычайнага факту чы адзінаго дзеяння. DeepAgents падтрымлівае гэта за дапамою навыкаў — самастойных файлаў, якія опісваюць інструкцыю, якую агент можа выкарыстоўваць сам, толькі калі сітуацыя гэта выклікае. Такая практыка «толькі калі трэба» ёсць намеранай і зазвычай называецца поступовым адкрываннем інформацыі. Агент завжды бачыць короткую назву і апісанне кожнага навыку. Усі інструкцыі пракрадаюцца ў яго рабочы кантэкст толькі тады, калі агент судзіць, што навык ёсць актуальным.
Навык — гэта адзін файл у фармаце markdown з невялікім блакам структураванай інформацыі ў верхней частцы:
---
name: native-tool-scoping-check
description: Checks whether a request to use "native tooling" is genuinely unambiguous, given the deep current integration between Databricks-native and Azure-native (Microsoft Foundry) services.
license: MIT
---
# Native-Tool Scoping Check
## The procedure
1. Check /memory/AGENTS.md for an existing scoping decision covering this
question. If one exists, treat it as binding and stop here.
2. If no decision exists, do not assume either interpretation - surface
the ambiguity explicitly as a scoping question.
3. Once resolved, the decision should be persisted to memory, subject to
human approval.
Ёнклудаванне падрабочага агента да спэцыялізацыі выконваецца за адзін радок: "skills": ["/skills/project/"]. Гэты шлях лічыцца зарэўнаваным з джэрэлам спэцыялізацыі: мідлвэр для спэцыялізацыяў скануе яго на належны чынам арганізаваныя падкаталогі, кожны з якіх мае файл SKILL.md. Адным простым паказаннем на які-небудзь вялікі каталог не становіцца спэцыялізацыяй, адтуды ўсё-такі трэба, каб пад кожным шляхам была самэй такая структура.
Ёсць два аспекты, якія трэба падтвердзіць, таму што яны адпавядаюць на разныя запытанні. Першы — чы гэты навык узагалі завантажваецца, чы не застаецца невыкарыстаным. Следы рэальнага запуску паказалі, што агент чыста прасіў файл навыку, што ўсунула сумневы ў тым, што механізм працюе, а не проста існуе. Другі аспект — чы змест навыку вплывае на поведэнне значным чынам. Для тэставання была выбрана сцэнарыя, якая, як правільна, выклікала патрэбу ў двух тэхнічных навыках адночасна: аднам па проекцыі сістэмы адзысквання інфармацыі, а другам па надзеямосты канвею обработкі дадзэнняў, і пераканаліся, чы рэзультат выкарыстоўвае аба яны. Гэта было так: запраектаваная структура выкарыстоўвала метод частковага адзысквання, опісаны ў аднам з навыкаў, і абрабатвала перазавантажаны дакумент як тое, што можна безпечна заменіць, а не копіюваць, што ўзгадваецца ў іншым навыку.
З’яўленне ў з’ўязку з зовнішнім сістэмай праз MCP
Інструменты і навыкі даўжа час застаўаліся ў кодзе праекта. MCP, тэлеграф Model Context Protocol, працюе інакш. Гэта стандарт, які дазволяе агенту знаходзіць і вызываць інструменты на удаленам серверэ, без неабяжнай ручной інтэграцыі для кожнага з іх.
Databricks запускае кераваны сервер MCP, які публікуе функцыі Unity Catalog як інструменты MCP, з урахоўваннем адпаведных прав. Агент можа знаходзіць і вызываць керавануюцую функцыю, і нікому не трэба пісаць для яе Python-обгортку. З’еднанне выглядае так:
import asyncio
from databricks.sdk import WorkspaceClient
from databricks_langchain import DatabricksMCPServer, DatabricksMultiServerMCPClient
async def _fetch_uc_function_tools():
workspace_client = WorkspaceClient()
host = workspace_client.config.host
mcp_client = DatabricksMultiServerMCPClient([
DatabricksMCPServer(
name="uc-functions",
url=f"{host}/api/2.0/mcp/functions/{CATALOG}/{SCHEMA}",
workspace_client=workspace_client,
),
])
return await mcp_client.get_tools()
def get_databricks_uc_function_tools():
return asyncio.run(_fetch_uc_function_tools())
Адзін разлік лёгкая затуманіць, таму варта быць точным. Функцыя Unity Catalog і інструмент MCP — гэта не адна і тая ж рэч. Функцыя — гэта кераваная можлівасць, якая мае савою правыя доступу і савое месца ў Databricks, і яя існуе незалежна ад MCP і існавала задоўга раней яго. Сервер MCP — гэта аднаецца шар пад яю. Ён не ўзаступны перакладчык, адтолькі ён таксама берае удзел у аўтэнтыфікацыі і кераваным доступе, што значыць, што вызов праз яго яшчэ врачывае, хто можа вызваць якую функцыю. Можна пабачыць гэта безпосерэдна: функцыя пад назвай knowledge_platform.default.mcp_verification_check у Databricks доходзіць да агента як knowledge_platform__default__mcp_verification_check, тая ж можлівасць у фармаце назвы, які выкалікае протакол.
Ёнколі падтвердзіць, што з’яўленне было рэальным, а не сімуляваным, была выкарыстоўвана тая ж самая ідэя, як і пад час тэста з спецыяльным інструментам: запытаць пра ўсё, што нельга здагадацца. Функцыя Unity Catalog была напісана так, каб вяртаць адны довільны значэння, выбрана ў падзеў. Агенту было прабачана вызваць яе і точна адзвярнуцца, што ўзялося, і ён вярнуў самэ гэта значэння. Гэта падтверджае рэальную сеткавую пераправку дадзенняў, ўжыцце ў Databricks і перадачу рэзультата праз пратакол, і адмовляе ад можлівасці пераканлівага фальсіфікавання.
Інтэрактыўны інтэрфейс
Адходзьба ад скрыптав
Усё вышэйшае працавала як скрыпт на Python, які запускаўся аднойчы з тэрміналу, ствараў выхідныя даны і завершалася. Рэальныя прыклады прыемнаў зазвычай працуюць больш саобразна розмове: хтось піша запіт, стачырае, як працуе агент, і адпавядае на яго запіты па ходу. Паслядні элемент праекта — гэта інтэрфейс у браузерэ, створаны з адпамогай Streamlit на аднам і тым жа агенце, які вікорыстоўваецца ў всім прыемніку.
Для гэтага патрэбна была архітэктурная рашынка, якая не ўсвіядомліва з занятыя. Інструменты, якія робяць праект корыстным, у першую чаргу з’ўязак Databricks MCP, выконваюцца асінхронна, тое значыць код можа чакаць на адпаведзь з сеткі, пакуль іншые задачы продовжаюць выконванне. Streamlit занова запускае цэлы скрыпт з самага пачатку кожны раз, калі хтось взаімаецца з сторанайчам, што стварае сур’ёзныя працягі, калі гэта поўяжваецца з дзействамі, якія выконваюцца асінхронна працоўна, нават паўтараючы, што Streamlit продовжае дадаваць падтрымку асінхронных задач. Гэтыя працягі добра задокументаваны ў іншых джэрэлах, таму было лепшая планаваць ўсё з урахоўваннем іх, чым адкрываць іх падчас стварэння праекта.
Для прыкладнага програма, якая адказвае за многа людзіяй адночасна, болей надзеяным падходам ёсць раздзелэнне аспектаў: правільны бэкэнд-сервіс керуе агентам, а інтэрфейс являе сабою выключна шар адображэння. Для прыкладнага програма для аднаго корыстніка, якая працуе локальна, такое раздзелэнне прыносіць сложнасць без адпаведнай корысты. Таму асінхронная праца выканана ўнутранічна інтэрфейса, з выкарыстоўваннем вбудованага функцыянала Python asyncio.run() для выканання аднаго цэлага крока дыялогу за раз. Гэта ўсведамлены компроміс, які падходзіць да масштабаў гэтага прыкладнага програма, і гэта не ўтверджэнне пра тое, што гэты выбор будзе правым у всіх сітуацыях.
Адображэнне таго, што робіць агент
Інтэрфейс мае прыямую перадчыню над скрыптам: ён можа паказваць працу ў момент яе выканання, а не толькі канечны рэзультат. Ён адображае рэальны лог, спіс усіх вызоваў інструментаў у стрыме галоўнага агента, пазначаных тыпам дзеяння. Візыбільнасць заканчываецца на межы, якая опісана далей, і не прарабляецца ў ізольаваны рэжым падагента.
Для гэтага патрэбна перагляд кожнага вызова інструмента і выбіранне катэгорыі, да якой ён належыць:
def classify_tool_call(tool_call, mcp_tool_names):
name = tool_call["name"]
args = tool_call.get("args", {})
if name == "task":
return "subagent", args.get("subagent_type", "?")
if name in mcp_tool_names:
return "mcp", name
if name == "read_file":
path = str(args.get("file_path", ""))
if "/skills/project/" in path and path.endswith("SKILL.md"):
skill_name = path.split("/")[-2]
return "skill", skill_name
if name in ("read_file", "write_file", "edit_file", "ls", "glob", "grep", "delete"):
return "filesystem", name
return "tool", name
Калі агент працюе, кожны новы вызов інструмента класыфікуецца і дадаўаецца ў спіс, таму дэлегаванне спецыялісту выглядае інакша, чым простае чытанне файла, а і гэта, і гэта — інакша, чым вызов званічнага MCP. У рэальным выкарыстоўванні гэта дазволяе розлічваць дэлегаванні, запускі спецыяльнага інструмента для пошуку ў інтэрнэце і запускі інструмента MCP Databricks; кожны з іх па ходу размовы меў свой сопаказвач.
Затверджэнне чы рашчыранне праз інтэрфейс
Механізм удзеле чалавека працюе тут таксама, але спосаб взаімадзеявы з яным змініцца. Уместа таго, каб пісаць адпаведзь у запытанні тэрміналу, запланаваная дзеянне паказваецца на старонцы з рэальнымі кантролемі:
if st.session_state.pending_interrupt:
action = st.session_state.pending_interrupt
st.warning(f"**Approval needed**\n\n**Tool:** `{action['name']}`\n\n**Args:** `{action['args']}`")
col1, col2 = st.columns(2)
with col1:
if st.button("Approve"):
run_turn(Command(resume={"decisions": [{"type": "approve"}]}))
with col2:
reason = st.text_input("Reason for rejecting")
if st.button("Reject"):
decision = {"type": "reject", "message": reason or "Rejected by the human reviewer."}
run_turn(Command(resume={"decisions": [decision]}))
Настоямы сэсія пераканаліга гэта прабаваючы рэальны адхоў. Ад агента было патрабавана разрабіць іншую частку сістэмы, і ён запропанаваў зберагчы свае выводы ў памяці. Зберагчыць іх праз інтэрфейс не было разрэшана з конкрэтным адказам. Усё-такі, у заканчальным паведамленні агента чытна было сказана, што выводы былі зберагчаны ў памяці.
Гэта заява была некальканая. Прыглядзеўшы безпаспечна файл памяці і окрэма шукаючы ў праекце іншыя файлы, якія моглі бы змяніцца, было паўнастацены, што нічога не было запісана нідзе. Адпаведны механізм абсалютна выпалоўваў адмову, а інтэрфейс і сістэма перарываў рабілі тое, што яны мялі рабіць. Не запрацаваў толькі апісун таго, што адбылося, з боку агента: ён сказаў «ні», але пры тым апісаў успех. Гэта тае жа паведанне, якое было спазірана раней у версіі тэрміналу, і якое цяпер паўнастацана праз абсалютна іншы шлях выканання, што робіць з гэтым стаўленнею да адмовленай дзеянні стаўленнем, якое можна паўтарыць, а не екзаплярным случаем.
Што інтэрфейс не можа паказаць
Адзін з ранейшых функцыянаў не быў цэлысна перакананы ў інтэрфейсе: выкарыстоўванне навыкаў. Жывыя даны прыходзяць з сабеўтароследу галоўнага агента, тады як внутршні крокі спецыяліста, укладаючы ў сябе завантажэнне файла з навыкам, выконваюцца ў ізольаваным рэжыме гэтага спецыяліста, на рэвэлі ніжэй, чым паказвае галоўны стрым. Па значэнню стандарту гэтая внутршняя дзеяльнасць аб’еднваецца з галоўным стрымом і не фіксуецца окрэма.
LangGraph можа яе адкрыць: пасылкай параметра subgraphs=True у вызов стрымінгу прыносіцца дзеяльнасць з ізольаванага рэжыму падагента. Гэты параметр быў зазначаны, але не адключаны ў гэтыя версію, адтолькі ўжо таму, што ён змініў бы форму кожнай стрымуемай апошней інформацыі, а рэндэраванне строю дзеянаў будзе вымагаць перэработы. Выкарыстоўванне навыкаў унутрь спецыяліста застаецца цэлысна падтверджаным праз адзірванне рэкорда выканання, які быў опісаны раней. Што ж, інтэрфейс проста не паказвае гэта жыва, і такое зазначэнне лепшая, чым натоўпленне іншых значэнняў.
Што паўтараецца пасля стварэння
Каркас вытрымаў
Галоўныя тэзы, якія былі выдвінуты, заклячылі, што дзейнасць длігіх, складных агентаў лепш усвядомляць як проблему керавання станамі. Агент не паспявае таму, што мадэль не можа рассуждаваць, а таму, што ён трапляецца без усведамлення таго, што ведае, што было адлучана чы ў што яму зараз дазволена дзейсць. Усе, што было пераканана вышэй, па-рознаму падтрымало гэту тэзу.
Па гэтым пытаннем рэзультаты былі стабільна хорашыя. Падаэнт, які меў доступ да файлу спяльнай памяці, правільна дзейваў завялікі гэтага доступу. Спецыяліст па управлінні пашанаваў рашэнне, якое ніколі не чуў па час размовы, проста таму, што могаў яго знайсці. Правілы дазволу застаўаліся такімі, якія былі заданы, нават пад тэнзам: паўтаральныя адхіленні ў рэальнай інтэрфейсе, калі рэальная адзынца кіраўся на адхіленне колькі разоў падрад, і жадна з адхіленых дзеянняў ніколі не была адбыта таямніча. Дэлегаванне межаў між прадаўцамі, калі адна частка сістэмы працуе на аднам модэлі, а іншая — на іншым, была дэталлю конфігурацыі, а не інжынерным праектам.
Механізмы разніцяюцца за сваім характэрам. Правыя на файлавую сістэму разрэшаюць практыкаванне певных дзеянь, настройкі маршрутызаціі між прадаўцамі канфігуруюць модэлі, а доступ падпрацоўнікаў да памяці керуе станам і кантэкстам. Кожны з іх ўскладнюе рашэнне проблемы керування станам, і кожны выполняў тое, на што быў налаштаваны. Гэта тверджэнне ёсць болей вузкім і точным, чым стверджэнне, што весь сістэма працавала так, як планавалася, а наступны частак раскрывае сітуаціі, калі гэта не было так.
Што не можа выправіць каркас
Цікавыя нарадкі стосаваліся сітуацыяў, калі каркас працаваў ідэальна, але ўсё рава выходзілі проблемы.
Без жаднага адказу і без паводзаў модэль не спытала, што сталося. Яна створыла правдападобнае адказванне і дзеяла на яго, пры чым два абсалютна разныя шляхі выканання падтвердзілі такі патэрн. Яй было да зберагчы пяць сувязаных фактов: чатыры падтвердзілі людзі, а ўсьмоўны — толькі на адной падставе, пры чым яна запісала ўсе пяць з аднаковым ступенем вярыгоднасці і тым самым формулюваннем, таму факт, выведзеный на адной падставе, не меў слабейшага сігналу, чым тыя, што падтвердзіліся. Две запісі ў памяці, здзейсненыя за калькі хвілін у адной сесіі, кожная з якіх была затверджана окрэма, далая працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна працоўна пр
Строга гаворка, нічыя з гэтых прычын не ўзглядае як абяканне кантролю стану у форме загубленага чыста парадуранага файла. Завдзяк адразу ж збіраным падтверджэнням і суперсучым запісам неабяжная інфармацыя была правільна зберэжана і была доступна для перагляду. Ніхто і нічога яе не пераглядало. Случай адхілення ўскладненей: мадэль ніколі не бачыць самага адхілення, толькі створаныя пра яго паведамленні, таму тое, як яна распрацоўвае гэтыя паведамленні, паднімае пытанне пра ўласныя ўзгляды і нічога не сказвае пра відсутнасць стану. У всіх трох прычынах неякснае суджэнне: спрыйманне неясна адхілення як правды, аддзеленне выведанага ад падтверджанага, адзначэнне таго, што новая адпаведзь суперсучыць старую. Гэта проблема ўзгляду, а не проблема структуры, і дадаць структуру не дае можлівасці яе безпасебна рашыць.
Чаму гэта важна
Для такіх проблем, які розв’язвае такое рашчэркі як DeepAgents, кантроль стану ёсць найважлівейшым элементам, а якасць аналізу ёсць тым, што застаецца пасля, ёсць сложнейшым і не падае пад прамы контроль сама па сабе. Бэкенды, правы на выконанне задач, ізольаваная дэлегацыя і кантрольованая памяць не можу заменіць правылы суджэння. Яны робяць дзеянні, стан і рэзультаты сістэмы віднымі і кантролюемымі: відразумелымі, можна прызначыць аўтара і можна вярнуць ў пачатковы стан прычыму, перш чым яны стануць перманентнымі. Гэта спрыяе лёгшаму ацэнкаванню суджэння пасля, хоць не можа гарантаваць, што суджэння будзе правым. Адхілены запіс, які все ж такі опісваецца як успех, ёсць справжнім неудачам, але яго было вядома адразу, таму што сістэма была спраектавана так, каб самэ гэты тып твэрджэння можна было пераканаць, а не прыймаць на веру.
У канцы канцоў, самэ для гэтага і існуе такое рашчэркі.
Спадневаная літэратура
- LangGraph Multi-Agent Workflows: Порэшчанне між калекцыяй агентаў і надзірнікам — Раздзеліце працэс LangGraph на падагентаў з вікорыстаннем контрольных пунктав, пасля чаго створыце фінансавага асістэнта як калекцыю агентаў і як надзірніка, і пазірце, дзе кожны з падходаў перастае работаць.
- A Production Harness for Claude Code: Шасць слоёў ад Slack да з’едыненага коду — Як шасцьслойны прыстрой ператварае запыткі з Slack у з’едынены код: прыём запыткаў, ціклы агентаў з кантролем, стойкі стан, самовылечэнне, можлівасць абзірвання і кантроль аператара.