Галоўная / Артыкулы

Файлавая сістэма агента — гэта рашэнне: бэкэнды Deep Agents

Бэкэнды LangChain Deep Agents вызначаюць, якія файлы перажывуць сесію: пяць убудаваных, маршрутызацыя CompositeBackend, пастка прастор імёнаў у шматкарыстальніцкіх сховішчах і пясочніцы.

Выдавец: REACTAPP.TOP9 хв чытання2174 слоў

Крыніцы: LangChain Deep Agents: Your Agent’s Filesystem Is a Decision. Most People Make It by Accident. IV

Найбольшая абярацыйная баг-агент не выклікае збоў. Яна тыха забывае вчорашні дзень, апавярнюе памяць іншага чалавека або запісвае ценную інфармацыю ў прастор, які вы ніколі не хацелі втраціць. У Deep Agents ад LangChain местам, дзе вырашаюцься такі наследкі, являецца бэкенд, і мета тут — перастаць ставіцца да файловай сістэмы як да чагось чародзяйскага і намеравана вырашыць, што застоіцца, што знікне і хто можа гэта бачыць.

Кожны агент Deep Agents атрымле файловую сістэму, але тое, дзе саме яна будзе знаходзіцца, залежыць ад вас: у памяці, на дыску, у стойкай сістэме зберагчыцтва, якая распрастраńваецца па ніткам, або ў сумесці. Неправы выбор прыводзіць да таго, што агент тыха забывае все, што было між кансэрваціямі.

Баг, які стоіць за знікненням запіскаў

Сказаўмо, вы створылі агента з увімкнутымі інструментамі файловай сістэмы і побачылі, як ён зберагае нотаткі ў /memories/findings.md падчас чату. Пазней ён чытае іх знову ў той самы размове. Усё гаразд, таму вы выпускаеце продукт. Наступнага дня вяртаецца вядомы корыстувач, згадвае ўсё тое, пра што, як сумніваецца, агент мяў ведаць ўчора, але агент нічога не ведае. Нотаткі зніклі. Ніякіх адзінакоў, ніякіх запісаў у журнале. Агент проста пачаў занова і не сказаў пра гэта.

Ніхто няўмышлена не стварае такой баг. Ён вынікае з стандартнага налаштавання: файлы агента зберагаюцца у прасторэ для працы, прызначаным для конкрэтнай размовы, які заканчываецца разам з нею. Калі не прыміць рашэння пра тое, дзе будуць зберагвацца файлы, фрэймворк рашае за вас. Для тэмпарарыяў такое падходзіць, але для памяці — гэта неправільны выбар.

Правыя на адзейнаўчыцтва, памяць, «піскулярныя коробкі» і працэс развяртання — усё гэта залежыць ад гэтага адзінаго выбору. Калі бэкенд правы, усё іншае стае на свае месца, а калі ён неправы, давайся ў пошук зніклых дакументаў цэлыя полудзенні.

Файловая сістэма ўявная, а бэкенд — тое месца, дзе яна знаходзіцца

Агент завжды бачыць звычайную файловую сістэму з звычайнымі шляхамі. Бэкенд вяршыць тое, з чаго складаецца гэтая файловая сістэма, і вы можэце зменіць бэкенды без змены спосабу працы агента.

Прадстаўлены шасць інструментаў для работы з файловай сістэмай: ls, read_file, write_file, edit_file, glob і grep. Для модэлю яны выглядаюць як простая файловая сістэма. Ён запішае /workspace/plan.md, пазней прачытае яго і будзе шукаты ў /repo, як будзь у яго дыск, і нічога з гэтага не змяніцца незалежна ад таго, які бэкенд знаходзіцца пад спадом.

Бэкэнд — гэта рэалізацыя, якая стоіць за гэтым абстракцыям. Ён адпавядае на запыткі, пра якія агент ніколі не думае. Калі мадэль запішае /workspace/plan.md, куды падаюць байты? У памяць Python, якая знікае, калі працэс завершаецца? На рэальны дыск? У базу дадзеных, якая застаецца пра кожную розмову, якая будзе у корыстніка? Кожны адпаведны адпаведае на адны бэкэнд.

Выбор здзейсніваецца праз перэдачу бэкэнда функцыі create_deep_agent(model=..., backend=...). Якшо нічога не перэдаць, будзе застаўцца стандартны варыянт, што і адказвае на знікненне зместу вышэй.

Адна прадактыка, каб ваш код падходзіў да актуальных версій: дайце агенту готовую інстанцыю, напрыклад StateBackend(). Старэйшыя прыклады выкарыстоўвалі обгортку lambda rt:, якая зараз ўжо не падтрымваная і непатрэбная.

Пяць бэкэндаў, распараджаных па тым, што застаецца

Просты спосаб разлічэння пяці вбудованых рэшэнняў — па трымусловасці, а не па внутрашняй структуры: як давго застаецца файл, запісаны праз кожна з іх?

StateBackend ўжо ёсць стандартным варыянтом і выступае як тэматычны прастор для працы. Файлы зберагаюцца ў стане агента і застаюцца актуальнымі працэсах адноўы розмовы (аднай тэме), але не дзеляцца между тэмамі. Гэта сваерадку агента, ідэальная для проміжных дзеянняў, якія чытаюцца знову за два крокі пазней і знікаюць пасля завершэння розмовы. Гэта правільны стандартны варыянт, а таксама самэе тое рэшэння, якое вызывае парадокс з знікненням зместу, калі яго плутаюць з памяцюючым механізамам.

StoreBackend — гэта стойкае зберагачча дадзейна між адзінамі потакамі. Файлы зберагаюцца ў сховішчы LangGraph і застаюцца актуальнымі праз усі размовы, што якраз і патрабуеяцца для давялега запам’ятавання. Але ёсць значны недзея: трэба ясна паведаміць, чыяя дадзеныя ён зберагае. Пра гэта пасля.

FilesystemBackend і LocalShellBackend выкарыстоўваюць рэальны дыск апарату-хоста. Яны чытаюць і запісваюць рэальныя файлы ў каталог, які вы выбералі, а LocalShellBackend таксама дае агенту інструмент execute, які выкананяе каманды шэлла прымусова на вашам апараце без жадных механізмаў захавання. Яны падходзяць для локальнага асістэнта-праектавальніка, які вы развіваеце на сваём столе, але ў іншых сцэнарыях ўскладнююць сітуацыю, таму ў даследжэннях працоўна паведамляецца пра абавязковую абераганне ўжыцця іх у дыяктууючых агентах. Безконтрольны доступ да апарату-хоста разам з дынамічнымі данымі з вводу корыстніка — гэта прычына, якая можа спрычыніць інцыдэнты з безпекай.

ContextHubBackend — гэта натыўная, стойкая апцыя Лангсміт. Файлы знаходзяцца ў рэпазітарыі LangSmith Hub і зберагаюцца як коміты, таму вы атрымліваеце стойкасць паўтарных запускаў, а таксама летак кожнай змены ў файлавай сістэме, не трэбаячы ствараць сабстыянтны склад для зберагання. Гэта практычна, калі вы вялікі ў экасістэме Лангсміт і хочаце стойкасць без налажвання базы дадзенаў.

Якшча рассматраць іх разам, варыянты знаходзяцца на адной осі: нічога не застаецца, розмова застаецца, усё застаецца, або усё застаецца з історыяй. Выберыце тое, калі трэба вашай функцыі.

CompositeBackend: разныя шляхі, разныя трыманні

Ідэя, якая робіць бэкенды эфектывнымі, заключаецца у тым, што рэдкая раз вы хочацее адну політыку зберагчыцтва для всіх файлавых сістэм. Рабочыя файлы должны быць дашчывымі, шырокімі і можна быць знешчытанымі, тады калі памяць — стойкай. Гэта два разныя бэкенды, а CompositeBackend дазваляе аб’еднаныя іх у адной файлавой сістэме за дапамою маршрутацыі па прымку пацыі.

Заставьце яго выкорыстоўваць аднаго стандартнага бэкенда для большасці пацыяў і табліцу маршрутацыі, якая перакідае выбраныя прымкі. Звычны распад — усё зберагаецца у тымчасовым рэжыме, а стойкое зберагчыцтва знаходзіцца за /memories/:

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    backend=CompositeBackend(  # ①
        default=StateBackend(),  # ②
        routes={  # ③
            "/memories/": StoreBackend(namespace=lambda _rt: ("memories",)),  # ④
        },
    ),
    store=InMemoryStore(),  # passed to create_deep_agent, not to the backend  ⑤
)

Перагляд пунктаваных пазначэнняў у гэтым спісе:

  1. CompositeBackend прадстаўляе агенту адну файлавую сістэму і перадае кожную операцыю пад-бэкенду, чыя маршрутная схема падходзіць да шляху.
  2. default прымеўа тое, калі ніякі маршрут не прызначаны. У гэтым прыкладзе гэтым ёст StateBackend, які працюе ў межах адпаведнага потока.
  3. routes супакоюе прымесы шляхоў з бэкендамі. Калі два прымесы падходзяць, пераважае дыявоўшы, таму /memories/projects/ перамагае /memories/.
  4. Запісы пад /memories/ падаюць у стойкі StoreBackend, чыя функцыя namespace вяртае тупл, які ідэнтыфікуе власніка і вызначае межы дадзэнняў.
  5. Об’ект store з LangGraph перадаецца функцыі create_deep_agent, а не бэкенду — гэта тонкасць паўтарання, якую люды не зразумеваюць з першага разу.

Эфект такі: все, што запісваецца пад /memories/, апошылваецца у стойкі сховішча і застаецца паўнамо цілым праз разныя размовы, тады як усё іншае — будзь то план у /workspace, тымчасовы файл чы выкарыстоўваны кэш — апошылваецца у стандартны StateBackend і знікае, калі заканчываецца тэкст. Агент нічога пра гэта не ведае і яму не важна. Ён проста запісвае шляхі.

Стратэгія файловай сістэмы для рэальнага агента

Возьмімо агента для тыпавага карэнту коду, напрыклад, з назвай buggy-shop. Калі ён працуе з рэпазітарыем, файлы рэпазітарыя ўважаюцца станом працы. Ооні завантажваюцца, правераны і тэстуюцца, і няма прычын, чаму яны мялі бы прасочыцца ў наступную размову. Тое, што агент вывучае па дорозе, — гэта адна спраба, і самэ гэта ён павінен памятаць па наступнай запытцы: ненадзеяныя тэсты ў аднам модулі, фікстчары, якія выкарыстоўваюцца кількомі тэстовымі комплектамі, або баг з пагінацыяй, які быў знайдзены раней.

Такім чынам buggy-shop выкарыстоўвае вышэўказаную складную структуру. Рэпазітарый знаходзіцца пад стандартным StateBackend як тэматычная памяць, а скарыстаныя нотаткі зберагаюцца пад пададрасам /memories/ у стацыонарным StoreBackend. Цэўнае агента з чыстаю адпаведздзю на пытанне, што должна застацца пасля завершэння кантакту. Разлікаванне тымчасовага стану працы і стойкіх знанняяў — гэта ключовы падход, а маршрутызацыя па пададрасах — спосаб яе рэалізацыі.

Дзе выконваецца код і дзе знаходзяцца файлы

Дапытлі, усё гэта стосуецца файлоў, і багато агентаў ніколі не патрабуюць больш. Але агент, чыя задача — падтвердзіць выправленне за дапамогою pytest, патрабуе шэл, таму што выкананне каманд не ёсць операцыяй файлавой сістэмы. Бэкенд у фармаце піску даўае гэта: па-першае, ён адкрывае доступ да файлавай сістэмы, а па-другое — надае інструмент execute для выканання каманд, усё гэта відбываецца ў ізольаваным кантэйнерэ, тады агент не можа зашкодзіць хосту.

Агенты можна падзяліць у сандбокс двума спосабамі. Адзін з іх — падаць агента ў сандбокс, дзе ён працуе з яго файлавой сістэмай. Гэта дазволяе локальную розработку застацца бліжэй да рэальнай супрацоўкі, але вымагае, каб вашы ключы API знаходзіліся ў сандбоксе. Іншы спосаб — спрыяець сандбоксу як інструменту: агент застаецца на вашам серверэ і выклікае сандбокс толькі для запуску коду. Кранты застаюцца занятымі званацьцем, сандбокс можна празрыць, а калі ён зламаецца, стан агента застаецца безпечным. Deep Agents падтрымлівае аба варыянты, і гэта явна адрозненасць ад інструментаў, якія дазваляюць толькі першы варыянт.

Памятайце, што выкананне коду і зберагчыце файлоў — гэта два разныя пытанні. Файлавая сістэма адпавядае за аднае, а сандбокс — за другое, і багатыя агенты патрабуюць абоўдвух.

Канфігурацыя, якую нельга праігнораваць

Калі StoreBackend адказвае больш за аднаго карыстальніка, патрабуецца фабрыкант прастора імен. Калі яго няма, не будзе краху, але будзе вытэк. Бэкенду неабходна інфармацыя пра тое, чыя файлы ён зберагае, і гэта інфармацыя отрымваецца з прастора імен — маленькай функцыі, якая прыме час выканання і вяртае тупл, у якім указваецца власнік. Размежаванне па пользоватэлях дазволяе кожнаму чалавеку маты адзінокыя месцы зберохвату:

from deepagents.backends import StoreBackend
backend = StoreBackend(
    namespace=lambda rt: (rt.server_info.user.identity,),
)

Не выклікайце прастора імен і застаўцы старых значэннях дыялогаў ад асістэнта, тады кожны выкарыстоўчык таго ж агента будзе дзеліць адзін і той самы запас хранення і зможа чытаць прыватную памяць іншых.

Гэты баг праходзіць усі тэсты на вашай сабе машыне, калі ўсё ж такі вы ўсё едыны выкарыстоўчык. Ён стае проблемай прыватнасці тады, калі заходзіць другі чалавек. Вважайце стварэнне прастора імен обав’язковым для усяго, кроме локальных прыборків для аднаго выкарыстоўчыка. У дасягледах напісана, што гэта стане обав’язковым, таму запішыце гэта зараз і прыхіліце міграцыю да пазнейшага часу.

У стандартным заднім кінцем таксама ёсць менша прыемка. StateBackend фіксуе цэлы стан агента на кожны крок, і самэ гэта дазваляе чыстаўа адноваць размову. Але за гэта вялікія файлы, якія зберагаюцца ў стане, павтараючыся, серыялізуюцца на кожны крок, таму вялікія артэфакты таямніча спадважваюць працэздатнасць і прыемку. Рашэннем являецца той самы комплексны патэрн: выкладзіце вялікія або дыявернія элементы у хранілніку, а StateBackend застаўце для маленькіх, транзыентных дадзеных.

Спіс задач на сёньдзе

  • З’ясавайце, які задній кінець вікорыстоўвае ваш агент. Без аргумента backend= для create_deep_agent вы вікорыстоўваеце StateBackend, і агент забывае все між размовамі. Пераканайцеся, што гэта самэ тое, чаго вы хацелі.
  • Аджуставайце, што павінна застацца пасля заканчэння размовы. Разлучаеце файлы, якія ўжо працуюць, і давялівыя знанні. Усё, што знаходзіцца ў столуце давялівых дадзеных, павінна быць у StoreBackend.
  • Іспользуйце шаблон компазітных структураў. Створыце CompositeBackend, які за замовчаннем вяртаецца да StateBackend, а адправляе запыты на пададчык /memories/ да StoreBackend. Самы элемент store падае на функцію create_deep_agent, а не на бэкэнд.
  • Да кожнага багатадзіячнага StoreBackend даўце фабрыку прастора імен. Прыўяжыце яе да ідэнтыфікатора карыстальніка і зрабіце гэта яшчэ перад тым, як другі чалавек заўйдзе.
  • Аўдытуйце вялікія файлы ў стане. Калі агент запісвае вялікія даны, адправіце іх за межы StateBackend, каб іх не перэсерыялізавалі на кожны крок.
  • Бэкэнд стае часткай адлічэння

    Якшае ставіцеся да бэкэнда як да варыянта, і тады вы вялікім чынам ухіліліся ад проблемы, калі трэба есці пасля полудня, з самага пачатку. Вы можэце опісаць пяць вбудованых рашэнняў па трываласці іх жыцця, надсылаць разныя шляхі да разной трываласці жыцця за дапамою CompositeBackend, і вы знаеце, што мнагадзінны хранэнне не можа існаваць без фабрыкі іменавання прастора. Агент, спраектаваны такім чынам, мае план для сваіх файлоў: тымчасавы прастор для рабочага рэпазітарыю, а стойкая памяць — для таго, што ён збірае.

    Тое, што агент можа выконваць трывалая збероҞка дадзеных у сабе, павінна прымусіць вас заспакоўвацца, і гэта ўсё правільна. Агент, які можа запісваць файлы, можа запісаць неправільны файл, адмахнуць правільны або запусціць каманду, якой вы ніколі не хацелі. Файловая сістэма — гэта як наданне яму рук. Далей прыходзіць «ліжачка», тыя самыя дэкларатыўныя правыя на адчыненне, якія обмежваюць, якія файлы ён можа чытаць, і падтрымка чалавека, якая прымусвае яго спачатку запытаць разрэшэння. «Ліжачка» дапамагае толькі тады, калі вы ўжо намеравана выбралі месца размешчэння файлаў.