Sakhanda Wire
NVDA $221.97 +2.54% MSFT $532.95 +0.20% GOOGL $334.76 -1.62% META $697.52 +0.47% AMZN $262.37 -0.10%
← Към новините

Vercel отвори кода на durable-harness за устойчиви на сривове кодиращи агенти

Vercel пусна durable-harness — пакет с отворен код, който поддържа сесиите на кодиращите агенти активни при сривове и изтичане на времето. Vercel durable-harness обвива съществуващи harness-и, включително Pi, OpenCode, Claude Code и Codex, без да ги променя. Всяка сесия се съхранява в устойчив лог. Прекъсването на функция вече не означава загубена работа. За екипите, които преместват агентите от лаптопите в облака, това запълва реална празнина.

Накратко

  • Размер: npm пакет, версия 0.0.x, Apache-2.0. Адаптерите обхващат 5 harness-а: Pi, OpenCode, fx, Claude Code, Codex.
  • Работи на: Vercel Functions плюс Vercel Queues, Node.js 22+ с Postgres или файлове на лаптоп. Claude Code и Codex изискват Vercel Sandbox.
  • Производителност: Няма публикувани бенчмаркове за латентност или пропускателна способност. Всички твърдения за възстановяване са предоставени от Vercel.
  • Най-добро: Завършените заявки към модела и инструментите се прочитат от лога, без повторно изпълнение или двойно таксуване.
  • Най-лошо: Експериментален API на версия 0.0.x. Claude Code и Codex работят само във Vercel Sandbox, дори при самостоятелно хостване.

Какво е durable-harness?

durable-harness е набор от адаптери на Vercel, които съхраняват сесията на harness-а в World на Workflow SDK. World обединява хранилище, опашка и поток в един интерфейс. Пакетът използва същия механизъм, който захранва Workflow SDK на Vercel.

Защо кодиращите агенти губят работа в облака?

Harness-и като Pi и Claude Code са проектирани като дългосрочно работещи локални процеси. Те съхраняват сесията в паметта. Локално работното пространство и историята се намират на един и същ диск, така че възобновяването изисква 1 подкана. В облака виртуална машина с постоянно хранилище не проследява кои заявки са завършили. Екипът на Vercel отбелязва, че при това неуспешен ход или мрежова грешка означава загубена работа.

Как работи durable-harness?

Той записва всяка стъпка от хода в устойчив лог. Преди изпълнението на заявка към модела или инструмент се записва намерение. Когато заявката приключи, се записва резултатът. Всеки ход е подкрепен от съобщение във Vercel Queues. Ако функцията прекъсне, опашката предава хода на нова функция. Тази функция прочита лога и продължава.

След срив логът показва какво е завършило, какво е било в процес на изпълнение и какво никога не е започвало:

  • Завършените заявки се прочитат от лога, така че вече генерираните токени на модела не се таксуват отново.
  • Инструментите с replay: 'safe', като справочни заявки, могат да се изпълнят отново.
  • Инструментите с replay: 'never', като възстановяване на суми, никога не се изпълняват два пъти. Моделът получава информация, че заявката може да е била изпълнена.

Файловете на сесиите на harness-а също се копират в лога. Това обхваща транскрипцията на Claude Code, изпълнението на Codex и хранилището на събитията на OpenCode.

Къде се изпълняват файловете и shell командите?

Командите, избрани от модела, никога не се изпълняват на собствения диск на функцията. Документацията за инструментите посочва 3 опции за работно пространство:

  • virtual() съхранява файловете в лога на сесията, с shell, съвместим с bash, и без мрежа. Поддържа около 500 файла.
  • virtual({ durable: false }) съхранява временните файлове в паметта и ги изчиства при всеки ход.
  • sandbox() предоставя на всяка сесия Vercel Sandbox, с /workspace на Drive.

Типизираните JSON документи, като списък със задачи, също се съхраняват в лога. Всеки от тях е с максимален размер 64 KB.

Стартирай ход</button> <button class="b red" id="kill" disabled>Прекрати функцията</button> <button class="b ghost" id="rst">Нулирай</button> </div> <div class="log" id="lg"><div>Натиснете „Стартирай ход“, след което прекратете функцията, докато CI работи.</div></div> <p class="note">Сценарий от публикацията на Vercel: агент добавя страница с цени, отваря PR и изчаква CI. Илюстративна симулация, а не бенчмарк.</p> </div> <div class="pane" id="p2"> <p class="sub" style="margin-bottom:12px">Изберете инструмент, след което го прекъснете по време на изпълнение.</p> <div class="rules"> <div class="box tool sel" data-r="safe"><h4><code>get_order</code><span class="pill">replay: 'safe'</span></h4><span class="note">Справочна заявка. Безопасно е да бъде повторена след срив.</span></div> <div class="box tool" data-r="never"><h4><code>refund_order</code><span class="pill">replay: 'never'</span></h4><span class="note">Възстановяване на сума. Никога не трябва да се изпълнява два пъти.</span></div> </div> <div class="btns"><button class="b red" id="crash">Прекъсни по време на изпълнение</button></div> <div class="verdict" id="vd">Изберете инструмент и натиснете „Прекъсни по време на изпълнение“.</div> <pre id="code">{ name: 'get_order', replay: 'safe', ... }</pre> </div> <div class="pane" id="p3"> <div class="ws"> <div class="box sel" data-w="0"><h4><code>virtual()</code></h4><span class="note">Файлове в лога на сесията. Shell, съвместим с Bash, без мрежа.</span></div> <div class="box" data-w="1"><h4><code>virtual({durable:false})</code></h4><span class="note">Временни файлове в паметта. Изчистват се при всеки ход.</span></div> <div class="box" data-w="2"><h4><code>sandbox()</code></h4><span class="note">Vercel Sandbox за всяка сесия, <code>/workspace</code> на Drive.</span></div> </div> <div class="box" style="margin-top:14px" id="wsd"></div> </div> <div class="pane" id="p4"> <div class="worlds"> <div class="box world sel" data-g="0"><h4>Vercel</h4><span class="note">Vercel World + проследяване на изпълненията на агента</span></div> <div class="box world" data-g="1"><h4>Лаптоп</h4><span class="note">Локални файлове, нулева конфигурация</span></div> <div class="box world" data-g="2"><h4>Самостоятелно хостване</h4><span class="note">Postgres World, Node.js 22+</span></div> </div> <pre id="wc"></pre> <p class="note" id="wn"></p> </div> <div class="pane" id="p5"> <table> <tr><th>Harness</th><th>Пакет</th><th>Изпълнява се в</th><th>Статус</th></tr> <tr><td>Pi</td><td><code>durable-harness/pi-durable</code></td><td>Вашата функция + виртуално работно пространство или Sandbox</td><td class="y">Поддържа се</td></tr> <tr><td>OpenCode</td><td><code>durable-harness/opencode</code></td><td>Вашата функция + виртуално работно пространство или Sandbox</td><td class="y">Поддържа се</td></tr> <tr><td>fx</td><td><code>libfx</code></td><td>Устойчиво самостоятелно</td><td class="y">Поддържа се</td></tr> <tr><td>Claude Code</td><td><code>durable-harness/claude-code</code></td><td>Само Vercel Sandbox</td><td class="n">Експериментално</td></tr> <tr><td>Codex</td><td><code>durable-harness/codex</code></td><td>Само Vercel Sandbox</td><td class="n">Експериментално</td></tr> </table> <p class="note">Claude Code и Codex са CLI инструменти за един потребител, които съхраняват състоянието си на диска, затова всяка сесия получава собствен Sandbox.</p> </div> <div class="ft"><span>Източник: vercel.com/blog/making-every-harness-durable · документация на Vercel · октомври 2026 г.</span><b>© Marktechpost</b></div> </div> <script> (function(){ var R=document.getElementById('mtp-dh'); function $(s){return R.querySelector(s)}function $$(s){return R.querySelectorAll(s)} function rz(){try{parent.postMessage({mtpEmbedHeight:R.offsetHeight+40,id:'mtp-dh'},'*')}catch(e){}} $$('.tab').forEach(function(t){t.onclick=function(){$$('.tab').forEach(function(x){x.classList.remove('on')});$$('.pane').forEach(function(x){x.classList.remove('on')});t.classList.add('on');$('#'+t.dataset.t).classList.add('on');if(t.dataset.t==='p3')ws(cur);setTimeout(rz,60)}}); var S=[['model','Планирай промяната',1],['read','app/page.tsx',0],['write','app/pricing/page.tsx',0],['run','gh pr create',0],['wait','CI проверките на PR',0],['model','Отговори с резултата',1]]; function draw(id){var o=$(id);o.innerHTML='';S.forEach(function(s){var li=document.createElement('li');li.innerHTML='<span class="k">'+s[0]+'</span>'+s[1];o.appendChild(li)})} var i=0,tm=null,killed=false,ma=0,mb=0; function log(t,c){var l=$('#lg'),d=document.createElement('div');d.className=c||'';d.textContent=t;l.appendChild(d);while(l.children.length>6)l.removeChild(l.firstChild)} function reset(){clearTimeout(tm);i=0;killed=false;ma=mb=0;draw('#sA');draw('#sB');$('#aRe').textContent=0;$('#bRe').textContent=0;$('#aMc').textContent=0;$('#bMc').textContent=0;$('#go').disabled=false;$('#kill').disabled=true;$('#lg').innerHTML='<div>Натиснете „Стартирай ход“, след което прекратете функцията, докато CI работи.</div>'} function li(id,n){return $(id).children[n]} function step(){if(i>=S.length){$('#kill').disabled=true;log('ходът завърши','o');return} ['#sA','#sB'].forEach(function(id){var e=li(id,i);e.className='run'}); log('намерение '+S[i][0]+' '+S[i][1],'i'); tm=setTimeout(function(){['#sA','#sB'].forEach(function(id){li(id,i).className='done'});if(S[i][2]){ma++;mb++;$('#aMc').textContent=ma;$('#bMc').textContent=mb}log('резултат '+S[i][0]+' ok','o');i++;step()},i===4?1800:700)} $('#go').onclick=function(){reset();$('#go').disabled=true;$('#kill').disabled=false;$('#lg').innerHTML='';step()}; $('#rst').onclick=reset; $('#kill').onclick=function(){if(i>=S.length)return;clearTimeout(tm);killed=true;$('#kill').disabled=true;var k=i; li('#sA',k).className='dead';li('#sB',k).className='dead';log('функция 1 прекъсна на стъпка '+(k+1),'x'); setTimeout(function(){log('без устойчивост: ръчно рестартиране, ходът започва отначало','x'); draw('#sA');var re=0,j=0;(function a(){if(j>=S.length){$('#aRe').textContent=re;return}var e=li('#sA',j);e.className='run';setTimeout(function(){e.className=j<k?'rerun':'done';if(j<k){re++;$('#aRe').textContent=re}if(S[j][2]){ma++;$('#aMc').textContent=ma}j++;a()},260)})(); log('с durable-harness: опашката предава хода на функция 2','o'); for(var q=0;q<k;q++)li('#sB',q).className='fromlog'; i=k;(function b(){if(i>=S.length){log('ходът завърши, 0 повторени стъпки','o');return}var e=li('#sB',i);e.className='run';setTimeout(function(){e.className='done';if(S[i][2]){mb++;$('#bMc').textContent=mb}i++;b()},450)})(); },600)}; reset(); var rule='safe'; $$('.tool').forEach(function(t){t.onclick=function(){$$('.tool').forEach(function(x){x.classList.remove('sel')});t.classList.add('sel');rule=t.dataset.r;$('#vd').textContent='Изберете инструмент и натиснете „Прекъсни по време на изпълнение“.';$('#code').textContent=rule==='safe'?"{ name: 'get_order', replay: 'safe', ... }":"{ name: 'refund_order', replay: 'never', ... }"}}); $('#crash').onclick=function(){var v=$('#vd');v.style.opacity=0;setTimeout(function(){v.innerHTML=rule==='safe'?'<b style="color:#50e3c2">Възобновено:</b> прекъснатата справочна заявка може да се изпълни отново. Pi я изпълнява повторно; Claude Code, Codex и OpenCode уведомяват модела, че е безопасно да бъде повторена.':'<b style="color:#f5a623">Никога не изпълнявай отново:</b> моделът получава информация, че възстановяването може да е било или да не е било извършено, така че първо може да провери. Всеки harness изчаква логът да запише заявка \'never\', преди да я стартира.';v.style.transition='opacity .3s';v.style.opacity=1;rz()},150)}; var W=[{t:'Кратки задачи и малки работни пространства',f:['Файловете се съхраняват','В лога на сесията'],m:[['Размер на работното пространство','около 500 файла',55]],x:'Срив по време на изпълнение не оставя нищо след себе си и заявката се изпълнява отново. Цена: процесорно време на функцията плюс лог събития и съхранение.'}, {t:'Временна работа в рамките на един ход',f:['Файловете се съхраняват','Изчистват се при всеки ход'],m:[['Устойчивост','няма между ходовете',8]],x:'Нищо не се записва в лога. Моделът получава информация, че файловете се изчистват. Цена: само процесорно време на функцията.'}, {t:'Реални проекти и дългосрочна работа',f:['Файловете се съхраняват','На Drive, който надживява всеки Sandbox'],m:[['Изолация','1 Sandbox на сесия',100]],x:'Команда, прекъсната от срив, може да е била изпълнена частично и моделът получава информация за това. Цена: използване на Sandbox и Drive плюс стартиране при първата употреба.'}]; var cur=0;function ws(n){cur=n;var w=W[n];$('#wsd').innerHTML='<h4>Най-подходящо за: '+w.t+'</h4><div class="note">'+w.f[0]+': <b style="color:#fff">'+w.f[1]+'</b></div>'+w.m.map(function(m){return '<div class="meter"><i></i></div><div class="ml"><span>'+m[0]+'</span><span>'+m[1]+'</span></div>'}).join('')+'<p class="note">'+w.x+' Типизираните JSON документи също се съхраняват в лога, до 64 KB всеки.</p>';setTimeout(function(){$$('#wsd .meter i').forEach(function(e){e.style.width=w.m[0][2]+'%'});rz()},40)} $$('.ws .box').forEach(function(b){b.onclick=function(){$$('.ws .box').forEach(function(x){x.classList.remove('sel')});b.classList.add('sel');ws(+b.dataset.w)}});ws(0); var G=[["// Във Vercel: @workflow/world-vercel се избира автоматично\nimport { claudeCode } from 'durable-harness/claude-code'\nexport const agent = claudeCode({ model: 'anthropic/claude-sonnet-5.5' })",'Сесиите се появяват в Agent Runs с всяка заявка към модела и инструмента. Възобновените ходове се показват в същото проследяване.'], ["# Локална разработка: @workflow/world-local, без конфигурация\n# сесиите се съхраняват в .workflow-data по подразбиране\nnpm install durable-harness",'Локалният World е подходящ за разработка и за един сървър с постоянно дисково пространство.'], ["# Самостоятелно хостване: 2 променливи преместват всеки агент в Postgres\nWORKFLOW_TARGET_WORLD=\"@workflow/world-postgres\"\nWORKFLOW_POSTGRES_URL=\"postgres://user:password@host:5432/database\"",'Необходими са @workflow/world-postgres 5.0.4+ и Node.js 22+. Това е референтна реализация: няма удостоверяване на маршрутите, няма криптиране и не е оптимизирана за мащабиране.']]; function wd(n){$('#wc').textContent=G[n][0];$('#wn').textContent=G[n][1];rz()} $$('.world').forEach(function(b){b.onclick=function(){$$('.world').forEach(function(x){x.classList.remove('sel')});b.classList.add('sel');wd(+b.dataset.g)}});wd(0); window.addEventListener('load',rz);window.addEventListener('resize',rz);setTimeout(rz,300); })(); </script> </body></html> ">

Къде можете да стартирате durable-harness?

Кодът на агента остава същият във всички Worlds:

  • Vercel: Vercel World, като всяка сесия се проследява в Agent Runs.
  • Локално: файлове на вашата машина, без конфигурация.
  • Самостоятелно хостване: Postgres World, версия 5.0.4 или по-нова, на Node.js 22+. В блога на Vercel също са посочени MongoDB, Redis и Turso.

2 променливи на средата, WORKFLOW_TARGET_WORLD и WORKFLOW_POSTGRES_URL, преместват агента в Postgres.

Как се сравнява durable-harness?

Функцияdurable-harnessTemporal + OpenAI Agents SDKInngest AgentKitCloudflare Agents SDK
Какво представляваАдаптери за устойчивост за съществуващи кодиращи harness-иОбвивка за устойчиво изпълнение на OpenAI Agents SDKTypeScript framework за множество агентиАгенти със състояние върху Durable Objects
Обвива Claude Code / CodexДа, експериментално, само в SandboxНе е оповестеноНе е оповестеноНе е оповестено
Backend за устойчивостWorkflow SDK World (Vercel, локално, Postgres)Temporal сървър или Temporal CloudМеханизъм за оркестрация InngestDurable Objects, Cloudflare Workflows
ЕзикTypeScriptPythonTypeScriptTypeScript
ЛицензApache-2.0MIT (сървър)Apache-2.0MIT
Статус0.0.x, експерименталенGA от 23 март 2026 г.Не е оповестеноНе е оповестено

Основни изводи

  • durable-harness записва всяка заявка към модела и инструментите, след което възобновява прекъснатите ходове в нова функция.
  • Завършените заявки никога не се повтарят, така че токените не се таксуват два пъти.
  • Pi и OpenCode работят във вашата функция; Claude Code и Codex изискват Vercel Sandbox.
  • Самостоятелното хостване работи с 2 променливи на средата и Postgres World.
  • Версията е 0.0.x и експериментална, без публикувани бенчмаркове.

Разгледайте хранилището в GitHub, документацията и съобщението на Vercel. Всички заслуги са за изследователя на този проект. Също така можете да ни последвате в Twitter и не забравяйте да се присъедините към нашия ML SubReddit с над 150 хил. членове и да се абонирате за нашия бюлетин. Чакайте! В Telegram ли сте? Вече можете да се присъедините към нас и в Telegram.

Преведено автоматично от английски. Оригиналната статия е на връзката по-долу.

Първоначално публикувано от MarkTechPost на

Прочетете оригинала в MarkTechPost ↗

Текстът и изображенията са собственост на MarkTechPost и са възпроизведени тук с посочване на авторството и връзка към оригиналната публикация.

← Към новините

Още новини

Всички последни новини