Пяць шароў агента-харнеса, з кодам, які не можа працаваць без іх.
Пяць слоёў канструкцыі агента, кожны з якіх мае код, які не можа працаваць без яго: межа выканання, сандбоксаванне, памяць, ціклы верыфікацыі і кантэкстны канал.
Крыніцы: `The Complete Guide to Agent Harnesses (With Code)`
Уявіце сабе команду, якая дадзе адзенту ў настройкі агента адно рэчы: жадныя змяны не можаць быць внесеныя без падтрымкі чалавека. Фраза напісана чытабельна, рэчыця знаходзіцца блізка да верху, і адзента завантажае яе на пачатку кожнай сесіі.
А потым наступае апоўдні, калі адна сесія адбываецца аж адзенаццаць разоў па гэтай рэчыцы і вносіць аж сяродзісці сямдэсят шасць няпрацаваных змян у матэрыял, які мае быць выданы кліенту. Ніякіх памылак не з’яўляецца. Нічога не зупініцца, каб запытаць. Чэрэз два гадзіны хтось працуе над дакументам, выявляючы кожную рэчыцу, якую адзента перапісаў сам, і знаходзіць сорак шасць такіх рэчыцаў у файле, які носіць назву кліента.
Сама інструкцыя была нормальная. Яна толькі знаходзілася не там.
У замену выкорыстоўваецца хук – маленькі скрыпт, які запускаецца прыстроем непразьдзе перш чым выконуецца запыт да інструмента. Ён пераглядае запыт, які чакае на адпаведзь, і можа адмовіць у яе. Агент можа заўсёды жаць здзейсніць змяну, але гэтая змяна ніколі не будзе зафіксавана ў файле. Такі хук інодзе можа даваць некарэктныя рашэнні, зазвычай таму, што правілы сформульаваны занадта строго, і разлік у тым, што можна адкрыць код і паказаць точную умову, якая спрычыніла працяжку. У запытэ простае рэчэ не дае можлівасці паказаць конкрэтную прычыну.
Разлік межаў між правілам, якое вы агласавалі, і правілам, якое вы выкананлі, – гэта прыстрой. Ён распаўляецца на пяць аспектаў:
- Дзеянні, якія можа выконваць агент
- Месцы, да якіх ён можа дасягнуць
- Стан, які застаецца пасля перзапуску
- Адналежнік, які пераглядае яго выходны рэзультат
- Косць таго, што яму паказваецца
Кожны рэгіон атрыбутуецца своім кодам. Існуе набор рабочых дэманстрацый, у якіх кожны слой працюе на вашам лептапе, перш чым можа зламацца ў рэальных умовах. Гэта спрамавана да людзей, які ужо выклалі агента і бачылі, як ён працюе некорэктна.
Што на самай працы дае харнес
Пачнім з чагось настолькі простага, што аж немагчыма гэта сказаць. Галоўны цыкл кодавальнага агента складаецца з шасці ліній:
while agent.turns < max_turns:
call = agent.next_call(observations)
if call is None:
break
result = execute(call)
observations.append(result)
Этыя лініі ўтвараюць агента. З апрацоўкай адзінакоў і павторнымі спробамі колькісць можа дасягнуць апошніх двадцяцяго. Які бы фрэймворк вы не выбралі, ён абгружае гэты цыкл, а цікавы элемент — гэта execute. Гэтая функцыя вяршыць тое, што можа робіць мадэль, што ёй дозволена, што ёй застаецца, хто яе аўдытуе і што ў канцы канцоў опынваецца перад ёю.
Разам гэтыя рашэнні ўтвараюць основу для работы, і багато коментараў стверджуе, што гэта мае большое значэнне, чым выбор самай модэлі. Даныя падтрымліваюць болей обмежанае тлумачэнне, якое, на дзяржбу, ёсць болей практычным.
Харнес выграў заўсёды за рахунак цены. У прадрукаваным аблікаванні з чэрвеня 2026 года было параванаце трох харнесаў (Goose, OpenCode, OpenHands-SDK) на двух мадэлях, выкорыстоўваючы стратыфікованы набор з 50 заданняў з Terminal-Bench Pro — аднойчы жорсткейшай версіі набора агентаў Terminal-Bench. Колькасць токенаў, якія былі выкарыстоўваны на адна заданне, разлічвалася ў разы на 40 межы між харнесамі. Замена на лепшую мадэль зменіла гэты показнік ліша на 1,0–1,3 раза.
Харнес не выграў за рахунак можлівасцей. Разлік у практычнасці выкарыстоўвання харнесаў станавіў ад 0 да 8 балоў, і, з урахоўваннем інтэрвалоў паверыльнасці, усе показнікі, за выключэннем найбольшага разліку, знаходзіліся блізу нуля. Самі автары называюць рэзультаты точнасці опісовымі, вялікі набір заданняў складаў толькі 50.
Простаючы, адна задача для аднаго модэлю з адным коефіцыентам успеху можа коштаць чырвоны раз больш пад аднай сістэмай керавання, чым пад іншай. Усе, што ляжыць пасля, скарматоўвае кошты і зменшае неспакоў, пры чым нічога з гэтага не дадае інтэлекту слабаму модэлю.
Пераклад правіла ў код
Указванне правіла ў запрошэнні сістэмы ўзначае ставку на тое, што модэль яго запамятае, расцёніць як павінна і будзе яго дазваляць, калі кантэкст стане занадта насыценым. Зазвычай модэль выграўвае. Саме гэты коефіцыент успеху і робіць гэта рызыкаваным, таму што люды тады перастаюць пераканваліваць.
Правіла на рэвэлі коду дзейнуюць праз кожны вызов, нават калі модэль відмовіўся ад ўсіх іх.
У цыкле агента ёсць пяць месца, дзе код можа знаходзіцца. Кожны з ніжыяя параграфаў раскрывае яго месца, код, які яго рэалізуе, і адпаведную працэздатнасць, калі гэты слой відсутны. Нікому не патрэбны ўсе пяць адразу. Выберыце той слой, чыя неспрацоўка, як вам здаецца, можа стацься ў вас за гэты тыдзень.
Слой 1: межа выканання
Што агенту разрэшана робіць?
Межа — гэта функцыя, якая знаходзіцца між выборам модэлю і фактычным вызовам інструмента. Пачніце з агента без захавання. У яго інструкціях сказана, што нельга выканаць відмену файлу без пытання, а ў чэрзі чакаюць тры вызовы інструментаў.
SYSTEM_PROMPT = "IMPORTANT: never delete a file without asking the user first."
def execute(call):
if call.name == "delete_file":
FILES.pop(call.args["path"], None)
return f"deleted {call.args['path']}"
Калі ён запускаецца, агент удалівае cache.tmp — безнэпасабельны мусор, а пасля — client-deliverable.md, што апошнія проста як і называецца. Ніякіх запытанняў не было, хоць у інструкцыі з самага пачатку была такая правіла.
Функцыя, размешаная раней за інструментам, рашае гэтыя проблемы:
def boundary(rules):
def wrap(execute):
def guarded(call):
for name, deny_if, reason in rules:
if deny_if(call):
return f"DENIED by {name}: {reason}"
return execute(call)
return guarded
return wrap
NEEDS_APPROVAL = [(
"delete-needs-approval",
lambda c: c.name == "delete_file" and not c.args.get("approved_by_human"),
"deletion requires an explicit human approval flag on the call",
)]
За выкарыстоўвання таго ж агента, скрыпты і запыту нічога не выдаліваецца.
Слой 2: сэндбоксаванне
Да чаго можа дасягнуць агент?
Сэндбокс вялічыць, якія каталогі і хосты можа адчуваць працэс агента. Яго можна стварыць з нуля: пачаць з нічога і даць толькі тое, што неабходна для выканання задачы, за дапамою спісу дазволеных шляхоў, спісу дазволеных хостоў і працэса, які не бачыць нічога іншага.
Пашыроны альтэрнатыўны варыянт — спіс забраныях шляхоў:
DENY = ["secrets/"]
def execute(call):
path = call.args["path"]
if any(path.startswith(d) for d in DENY): # checks the spelling
return "DENIED by deny-list"
real = os.path.normpath(path) # the ../ collapses HERE, after the check
return DISK.get(real, "not found")
З’явіцца яго і агент практыкуе два разы:
read('secrets/api_key') -> DENIED by deny-list
read('work/../secrets/api_key') -> sk-live-DO-NOT-LEAK
Прабавка пераглядала тэкст такім, якім ён быў надрукаваны, тады як пошук файла веліся за месцам, куды паўтараецца той тэкст. Две запыткі, два спосабы напісання, адны файл.
Для выправлення спачатку трэба нормалізаваць шлях, а пасля — парабіцца:
ALLOW_ROOTS = ["work"]
def resolve(path):
real = os.path.normpath(path) # resolve FIRST
if not any(real == r or real.startswith(r + os.sep) for r in ALLOW_ROOTS):
return None
return real
Оба спосабу напісання цяпер ператвараюцца на secrets/api_key, які знаходзяцца пад жаданым корнем, таму оба варыянты адхоўваныя. Хутчэй неабходна дазволіць, чым адмовіць, таму што спіс адмоваў блакуе толькі тыя варыянты напісання, якія уявіў яго автар.
Этыя прыклады — звычныя функцыі Python, таму для ўпрабавкі іх не трэба кантэйнера. У рэальнай рэалізацыі той самы контроль выкананы самым межам процэса: корыстнік або кантэйнер, які не мае права на чытанне па за межамі work/, выкананыя ў той самы парадак.
Слой 1 не можа выканаць гэту задачу. Контроль, які знаходзіцца ўнутрь вашага програмы, бачыць толькі тыя вызывы, якія ён распазнае, тады як каманда шэлу, сіндыкатыў або шлях з .. можа дасягнуць таго ж файлу, не будучы ніякім з гэтых вызываў.
Слой 3: стойкасц памяці
Што застаецца пасля перазначэння кантэксту?
Адзін прыкмет вырабатывае большыя наследкі, чым большасць іншых: прыпынэнне кансэрвацый без жадных раздумаў. Кантэкст запоўняецца, якосьць падупае, і агент начынае не пагадвацца сам з сабой. Багато людзей продовжаюць ведаць такія сесіі. Лепшая пачынаць занова рана, як толькі ўсё важлівае будзе захавана там, дзе перачысці не зможа яго стэрць — будзь то зберажаны код, настройкі, сама платформа або структураваныя нотаткі.
Таму цярпяча выберыце, дзе павінен знаходзіцца кожны элемент стану. Існуе тры варыянты: кансэрвацыя ў рамках сесіі, дзе яна знікае разам з сабой; захаванне на дыску, дзе яна застаецца і можа быць выкарыстоўана пазней; і захаванне ў настройках платформы, дзе яна вплывае на кожную наступную сесію.
Адна функцыя дыстрыбуцыі падтрымлівае ўсе тры варыянты:
CONVERSATION, DISK, HARNESS_CONFIG = [], {}, {}
def remember(kind, key, value):
"""'chat' dies with the session, 'disk' survives it,
'config' shapes every session that follows."""
{"chat": lambda: CONVERSATION.append(value),
"disk": lambda: DISK.__setitem__(key, value),
"config": lambda: HARNESS_CONFIG.__setitem__(key, value)}[kind]()
Функцыя практычна нічага не робіць. Яе ролю складае правіла, які не дозволяюць нічаму зберагчыцца без указвання, у якій з трох прыемных станоў гэта будзе зберагчыцца. Команды рэдка калі прыменяюць гэты выбор явна, што пояснюе, чаму агенты іноды забываюць пра дзеякія рэчы і упертаа памыляюцца ў іншых. У дэманстрацыі спіс размов застаецца порожнім, тады як рашэнні і правілы застаюцца на дыску і ў налаштаваннях.
Слой 4: ціклы пераканання
Хто пераглядае рэзультаты, і што заважае пераглядачу проста выправіць проблемы?
Цікл пераканання означае другі перагляд работы агента, які выпалоўвае той, хто мае права пазначыць проблемы, але не мае права іх выправіць.
Вторая частка — гэта тое, што людзі працяюць пасляе. Нехай падрабітнік-рэвізор напісае код, і ён тыха пацелуе все, што знайдзе. Гэта здаецца каляклівым, але гэта стырае інфармацыю, якую вы хацелі: вы больш не можэце адзеліць правільную работу ад неправільной, якая была пацелена за вашай спінай.
Таму трэба, каб рэвізор меў толькі права на чытанне. Ён стварае крытыку, а дзеянне на адпаведнасць гэй крытыцы — гэта ўжо новы крок з сае власной следам. Раздзелэнне іх захоўвае сігнал, які можна прачытаць.
Другія тактыка — гэта пробны запуск. Для будзь-яга незворачнага дзеяння інструмент прыймае флаг, за замовчаннем опісвае, што б ён зрабіў, і дзеяе толькі тады, калі хтось спецыяльна выключыць гэты флаг. Безнэбяжнае паведанне ёсць за замовчаннем, таму працязка коштуе нічога. У дэманстрацыі інструмент для пацелення анансуе, што перапісае total.py, нічога не пішае, і прычына працязкі застаецца без змян.
Адзін execute выконвае обе правілы:
def execute(call):
if call.name == "review":
snapshot = dict(CODE) # a copy, so the reviewer cannot write
src = snapshot[call.args["path"]]
return f"VERDICT: {'off-by-one' if '+ 1' in src else 'looks good'}"
if call.name == "apply_fix":
if call.args.get("dry_run", True): # on by default, turned off on purpose
return f"DRY RUN: would rewrite {call.args['path']}, nothing written"
CODE[call.args["path"]] = call.args["new"]
return f"wrote {call.args['path']}"
Адміністратар апдэтаў з’являе памылку «off-by-one» і не мае можлівасці яе практычна паскорыць.
Слой 5: канвэйяры кантэксту
Што доходзіць да модэлю, і за шта яго оплачваюць?
Канвэйяр кантэксту апрацоўвае, як інфармацыя праходзіць у «вікна» модэлю і скількі з яе дазволяецца.
Саме тут ідзе грошы. Кожны токен, які праходзіць, оплачваецца ў той момент і зноў у всіх наступных, таму саме тут і выступае чатырохдзесяткратная розніца, а не у Слое 1.
Простая наладка завантажае ўсё: цэлы файл з пытаннем пра адну функцыю, всі рэзультаты пошуку для простай запатэнка і весь історыя. Гэта працюе, але ў двадцаты раз вы зноў плаціце за тое, што ужо было прачытана ў пяцнадцаты-дзевяцнадцаты раз.
Рашэнь — гэта дэлегаванне плюс адсорбаванне. Падрабнік працуе ў адзінам окне, чытае дзесяткі тысяч токэнаў і вяртае адна-две тысячы. Галоўны поток прахоўвае нечысты вынік пошуку і прыме чым толькі адпаведзь.
У кодзе гэта выражаецца ў тым, кой лічык падыходзіць увысь:
def subagent_search(query):
"""Its own window. The main thread never pays for this reading."""
global subagent_tokens
subagent_tokens += sum(len(v.split()) for v in CORPUS.values())
return next(f"{n}: {b.split('ANSWER:')[1].strip()}"
for n, b in CORPUS.items() if "ANSWER:" in b)
def execute(call):
global main_tokens
distilled = subagent_search(call.args["q"])
main_tokens += len(distilled.split()) # the only line that bills you
return distilled
Дэманстрацыя ўмышленна мала і чыстая. Запыт і адпаведны адказ аднаковыя ў обох варыянтах, пры тым галоўны працэс обрабоўвае 9,602 токены ў аднам варыянце і 2 — у іншам.
Гэта таксама раз’яснюе, чаму ланцоўкавыя падагенты выводзяць людзей з парадку. Калі кожны крок чакае на пылейшы, вы атрымваеце ізоляцію кантэксту і абоўсумова жаданага прышвартавання. Прыгожа незалежныя крокі павінны выконвацца паралельна. У працыні, прыйміце, што ізоляцыя — гэта тое, што вы купляўце. Часта гэта прабачае цэну, як толькі вы ведаеце, што пакрывае счыт.
Чаго ўсё ўсё ўсё ня можна сказаць
Доверлівасць грамадскасці да гэтага пытання перасіліла доказы, якія яго падтрымліваюць, таму застэрэжэнні маюць значэнне.
- Нічна з гэтага матэрыялу не была пераглянута экспертамі. Па стан пачатку 2026 года кожны адзін доследжэнне, які расследуе гарнітуру, ўособлівае архіў арXiv без процедуры рэцэнзавання. Найбольш рэтэльны эксперымент опісвае сябе як пачатковая праца, якая находзіцца на этапы перагляду на семінарэ, а найвядомейшая статыя з аналізам выкладвае сябе як позіцыйны доклад без сопственных эксперыментаў. Спрыяйце всему гэтаму, укладаючы ў гэта і гэты тэкст, як матэрыялу без рэцэнзавання, і паўтарыце параболікаванне ў своіх заданнях пры планаванні бюджэтаў на адповідны час.
git clone https://github.com/paoloap-py/agent-harness-guide
cd agent-harness-guide
python3 run_all.py # all five layers, guard off then on, side by side
python3 test_harness.py # asserts every difference above, 10 checks
У дасабле README пяць слоёў паказаныя як чарт аўдыту з адным падзеямым запытаннем: чыі код гарантуе яго адпаведнае выкананне, чыі ж фраза з запросу? Кожны пункт, які нельга пазначыць, паказавшы шлях да файла, — гэта правіло, на якое можна толькі спадзявацца.
Дзе гэта практыкуецца
Розумна правіла, распакаваныя не там, дзе трэба, практычна не маюць значэння. У вышэўказаным сцэнарыі гэта прынесла панздзесят парабянаў, адзінаццаць з яых — за аднія вечары, і дзень, якога ніхто не хочаць. Толькі перамішчанне правіла дапамогла яму стаць эфектывным, пры чым жадна з ягое фраз не была зменена.
Гэта і ёсць сутнасць. Мадэль — гэта тое, што вы купуеце. Усё, што ўсунуто навакол яе, — гэта тое, што вы ствараеце, і самэ гэта напалова вялічыць косцы агента і тое, насколькі часта ён выканае дзеянні, якія вы ніколі не санкціонавалі. Абодва аспекты ўжо ў складзе інжынерыі, але толькі другі з іх вы можэце формаваць самі.
Частаяя запытанні
Што саме ўскладнілае для агента? Усе, што абгортае мадэль: гэта цыкл інструментаў, перакананні перад выконаннем, сандбокс, зберагчыцельнасць между сесіямі, адзінак і лінія апрацоўкі, якая вяршыць, калі самэўтварэнне мае містыць. Цыкл складаецца з шасці рэчэй, а з адзьмяненнем на разлік з бягамі на выключэнні бядаў — з двадцяці, а ўсё інша належыць да ускладнілае.
Чы ўскладнілае важлівей за мадэль? З точкі зоры костоў — так, адзінакі на выкарыстоўванні токэнаў за адна рашаная задача можа разлічыцца аж у 40 разоў. Чы задачы будуць рашаныя — ні. Разлікі ў практычным рэшэнні задач между разнымі ускладнілаемі станавяць ад 0 да 8 балоў, пры чым існуюць інтэрвалы, якія перакрываюць нуль, і автары Terminal-Bench выводзяць, што для канкрэтных рэзультатаў зазвычай важлівей ёсць сама мадэль.
Дзе рэмень кабелів коштае найбольш? У кантэксце. Кожны токен, які паказуецца модэлю ў кожны момент, оплачваецца ў кожны момент. Чырвоныя кабелі ў пяцым слое ёсць дорогім выборам, і гэта пояснюе, чаму перадача пошуку падагенту змінюе суму рахунку, не змінюючы адпаведнай адпаведзі.
Чы правілы дазволу лягаюць у кантэкст безпекі?
Нята. Пераканаленне рэмня кабеліў бачыць толькі тыя вызовы, якія агент фактычна здзейсніў, тады калі команда шэлу, сіндыкатыўны звязак або шлях .. можа дасягнуць таго ж файлу без пераканалення. Рэальныя меры безпекі выклікаеяеся аператыўной сістэмай: запускайце працэс без праваў на ўсё, а потым дадайце тое, што трэба для выканання задачы.
Стварыць рэмень кабеліў самі чы вжыць готавы? Вжыць готавы і застацца з яным. Пераход на іншы стэрае накопленыя знанні ў вашых файлах налашчэння, і кожна правіла, напісаная пасля справжней няудачы, павінна зноў быць здобутая.
Спаднія матэрыялы
- Агенты, які самастаюцься за дапамою навыкаў: паўтарны выкарыстоўванне, выбір, карэкцыя і перакананне — чатырыэтапны падход да стварэння агентаў, якія павышаюць своія навыкі: зберагчык рабочага коду, удосконаленне апісаў, прыметкі ўзглянутых карэкцый і перакананне рэзультата пры перадачы.
- Сістэма для працы з Claude Code: шасць слоёў ад Slack да з’едыненага коду — як шасцьслойная сістэма ператварае запыткі з Slack у з’едынены код: прыемка запыткаў, ціклы агента, стойкі стан, самавылечэнне, можлівасць абзірвання і кантроль аператара.