Усе — це плагін: дизайн Cordis у основі DeepSeek Harness
Як DeepSeek Harness створює середовище виконання агента з плагінів, використовуючи ідеї Cordis такі як зворотні ефекти, реактивні залежності та замінюваний цикл агента.
Джерела: DeepSeek Quietly Built a Different Kind of AI Agent Framework
Звичайний підхід та його обмеження
Більшість фреймворків для агентів починаються з однакових елементів: моделі мови, кількох інструментів, збереженої розмови та циклу, який обробляє все це. Наведений нижче скетч демонструє їхню структуру.
User asks something
↓
LLM thinks
↓
LLM calls a tool
↓
Tool returns data
↓
LLM continues
↓
Final answer
За визначенням це вже вважається агентом. Проблеми починаються, коли система росте. Накопичуються вимоги: кілька постачальників моделей, інструменти браузера, виконання через шель, сервери MCP, процеси схвалення, пам’ять, телеметрія, автентифікація, різні інтерфейси користувача, фонові агенти, користувацькі запити, дозволи та гаряче завантаження. Незабаром кожна частина залежить від усіх інших. Зміна постачальника моделей впливає на цикл агента, видалення плагіну залишає слухачі подій, а перезавантаження інструменту може пошкодити агентів, які працюють у цей момент. Плагіни також залежать від сервісів, які можуть з’явитися чи зникнути під час роботи.
DeepSeek Harness підходить до цього зовсім інакше. Його основна ідея звучить майже занадто просто: усе є плагіном, включаючи ті компоненти, які більшість фреймворків вважають ядром.
Під усім цим лежить фреймворк під назвою Cordis, який виник на основі дослідницької статті під назвою „A Programming Paradigm for Spatiotemporal Composability“. Ця стаття є цікавою, оскільки проект — це не просто ще одна схема для організації модулів JavaScript. Він ставить більш глибоке інженерне питання: як компоненти можуть об’єднуватися, відходити, замінювати один одного та змінювати залежності в працюючій програмі, не призводячи до хаосу під час її виконання?
Що таке харнес
DeepSeek Harness, скорочено dsh, — це харнес агентів з відкритим кодом, розроблений DeepSeek. Харнес — це інфраструктура, яка оточує модель. Незалежно від того, чи це модель DeepSeek, Claude, GPT, Gemini чи локальна, харнес піклується про все, що з нею пов’язано.
┌───────────────┐
│ LLM │
└───────┬───────┘
│
┌──────────▼──────────┐
│ Agent Harness │
│ │
│ Prompt construction │
│ Tool execution │
│ Session history │
│ Permissions │
│ Streaming │
│ Agent lifecycle │
│ Model adapters │
└─────────────────────┘
Ця різниця має велике значення. Зазвичай увага зосереджується на тому, наскільки розумним є модель, проте створення таких інструментів, як Claude Code, Codex, Cursor чи довгостроковий автономний агент, показує, що час їхньої роботи має таке ж важливе значення. DeepSeek Harness керує цим часом роботи за допомогою набору динамічно складених плагінів, а не як одного монолітного додатку, і це рішення безпосередньо успадковане від Cordis.
Загадка залежностей
Уявіть собі створення кодувального агента з трьох плагінів.
GitPlugin
TerminalPlugin
CodingAgent
Для роботи з кодуванням потрібні Git та Terminal. На початку найпростіший спосіб — це завантажити їх по черзі.
load Git
load Terminal
load CodingAgent
Це просто, і більшість фреймворків для вставки залежностей справляються з цим добре. Складніше запитання полягає у тому, що станеться, якщо плагін Git зникне під час роботи програми. Його могли оновити, змінитися його налаштування, користувач міг його вимкнути, або може з’явитися інша реалізація. У такому разі система виконання мусить зупинити все, що залежить від цього сервісу.
CodingAgent
↓ -------->depends on
GitPlugin
Якщо Git зникає, агент для кодування не повинен продовжувати вести себе так, ніби він існує. А якщо пізніше з’явиться інший постачальник Git, можливо, агент має знову почати працювати. Тут приховані дві окремі проблеми, які у статті Cordis називаються темпоральною та просторовою композитністю.
Темпоральна композитність: чисте виходження
Припустимо, плагін завантажується та реєструє слухач подій.
events.on("message", handler)
Пізніше плагін вивантажується, і виникає питання: що стається з об’єктом-прослуховувачем? Якщо ніщо не припиняє його роботу, плагін формально зникає, але частина його продовжує функціонувати. До того ж плагін міг запустити таймери, відкрити з’єднання до бази даних, зареєструвати команди, змінити спільний стан, додати інструменти, приєднати обробники подій та запустити фонові процеси. Вивантаження означає зворотну дію щодо кожного з цих кроків.
Це є тимчасовою композитністю: компонент, який приєднується до системи, повинен залишити її здатною повністю скасувати все, що він зробив. Cordis розглядає такі зміни як ефекти, які можна скасувати.
Ефекти без жаргону
Ефект — це просто те, що робить ваш код, змінюючи зовнішній світ чи стан під час виконання. Візьмемо, наприклад, реєстрацію інструменту.
toolRegistry.add("search", searchTool)
Перед дзвінком реєстр виглядає так.
tools = {}
Після цього воно утримує новий інструмент.
tools = {
search: searchTool
}
Операція просування вперед — це додавання.
add(searchTool)
Проте Cordis прагне чогось більшого. Вона хоче, щоб операція мала свою власну зворотну дію. Концептуально ефект поєднує дію з її скасуванням.
Effect:
do: add search tool
undo: remove search tool
Без математичної нотації ця ідея формулюється наступним чином.
state --effect--> new state
new state --inverse--> original state
Цей зворотний процес є ключовим елементом, і Cordis називає всю цю структуру зворотним ефектом.
Кожна зміна вимагає наступного виправлення
Cordis реалізує це за допомогою подібної до наступної схеми, де функція застосовує зміну та повертає функцію, яка її скасовує.
ctx.effect(() => {
registerSomething()
return () => {
unregisterSomething()
}
})
Час виконання застосовує ефект, зберігає функцію очищення та викликає її пізніше, коли плагін припиняє свою роботу.
apply effect
↓
store cleanup function
↓
plugin runs
↓
plugin unloads
↓
run cleanup
Коли плагін містить кілька ефектів, вони застосовуються у певному порядку.
effect A
effect B
effect C
Потім процес очищення відбувається у зворотному порядку, як розпаковується стек.
undo C
undo B
undo A
Чому зворотно? Розгляньмо плагін, який починається ось так.
1. open database
2. start service using database
3. start agent using service
Завершення роботи у тому самому порядку буде небезпечним, оскільки база даних закриватиметься, поки інші програми все ще нею користуються.
close database
stop service
stop agent
Безпечний порядок — це протилежне.
stop agent
stop service
close database
Це останній, хто увійшов, — перший, хто вийде.
Last In
First Out
Cordis вбудовує цю поведінку у механізм керування життєвим циклом компонентів.
Лише зворотне очищення недостатнє
Тут стаття стає цікавішою. Припустимо, плагін A змінює спільне значення, потім плагін B змінює те саме значення, а після цього A намагається відновити початкове значення. Це може стерти зміни, внесені B.
Initial: x = 10
Plugin A: x = 20
Plugin B: x = 30
Plugin A unloads: restore x = 10
B все ще активний, проте його стан зник. Тож зворотні ефекти є безпечними лише за певних припущень про незалежність, які у статті формалізуються як незалежність ефектів. У неформальному сенсі два ефекти є незалежними, коли застосування чи зворотний процес одного не скасовує значення іншого. Реєстрація різних інструментів зазвичай відповідає цим умовам, оскільки вони впливають на різні області.
Plugin A registers tool "search"
Plugin B registers tool "calculator"
Заміна тієї самої конфігурації, ймовірно, не допоможе.
Plugin A replaces configuration X
Plugin B also replaces configuration X
Це розрізнення знову з’являється пізніше, коли йдеться про систему контексту Cordis.
Просторова композитність: розуміння потреб плагіна
Часова композитність стосується можливості безпечного видалення компонента. Просторова композитність стосується того, чи розуміє система, від чого залежить компонент. Уявіть собі цей плагін.
CodingAgent
Для цього потрібні три речі.
LLM
ToolRegistry
SessionStore
Традиційний код може звертатися до глобальних змінних.
global.llm
global.tools
global.sessions
У такому випадку архітектура не має реальних знань про залежності. Cordis робить їх очевидними. Концептуально плагін оголошує, що він інжектує.
inject: [
"llm",
"tools",
"sessions"
]
Тепер середовище виконання може бачити вимоги плагіну у вигляді дерева.
CodingAgent
├── requires LLM
├── requires ToolRegistry
└── requires SessionStore
Це дозволяє системі реагувати на зміни в цих сервісах.
Реактивні залежності
Це, можливо, найкраща ідея в Cordis. Припустимо, компоненту потрібен LLM.
LLM
Спочатку його немає.
LLM unavailable
Тож компонент не може стати активним. Пізніше завантажується плагін-постачальник, який надає один такий компонент.
OpenAI Plugin loads
↓
provides LLM
↓
dependency becomes satisfied
↓
component activates
Якщо цього постачальника видалити, його функціонал також зникне.
OpenAI Plugin unloads
↓
LLM disappears
↓
dependency becomes unsatisfied
↓
dependent component unloads
Коли завантажується інший постачальник, функціональність повертається.
DeepSeek Plugin
↓
provides LLM
↓
component becomes active again
Залежності тому не перевіряються один раз під час запуску. Вони є реактивними, саме тому у статті йдеться про реактивні коекфекти.
Ефекти проти коекфектів
Ця термінологія здається складною, але розрізнення просте. Ефект описує те, що змінює компонент, поширюючись від плагіну до середовища.
Plugin → Environment
Прикладами є ці дії.
register tool
open database
subscribe to event
start timer
Коефект описує те, що компонент потребує від свого середовища, протікаючи у зворотному напрямку.
Environment → Plugin
Типовими прикладами є ці потреби.
need an LLM
need a logger
need session storage
need a tool registry
Поєднавши їх, вимоги будуть надходити лише в одному напрямку.
requirements
Environment ───────────────────> Plugin
поки ефекти повертаються назад.
Environment <─────────────────── Plugin
effects
Це основна ідея Cordis. Компонент вказує, що йому потрібно, що він надає та які зворотні ефекти він створює.
I NEED these services.
I PROVIDE these services.
I PERFORM these reversible effects.
Потім середовище виконання координує життєвий цикл.
Звідки походить термін „просторово-часовий“
Тепер назва статті має сенс. Просторова композитність стосується взаємозв’язків між компонентами.
A depends on B
B provides X
C depends on X
Темпоральна композитність стосується того, як компоненти рухаються в часі.
load
activate
replace
deactivate
unload
reload
Разом вони утворюють всю філософію.
Spatiotemporal composability = dependency-aware composition + reversible lifecycle changes
Об’єкт контексту
DeepSeek Harness не передає десятки сервісів вручну через конструктори. Плагіни взаємодіють через спільний контекст, який зазвичай має таку назву.
ctx
Концептуально він відображає основні сервіси.
ctx
├── llm
├── tools
├── sessions
├── agents
├── agentLoop
├── logger
└── ...
Проте ctx — це більше, ніж просто об’єкт JavaScript, наповнений глобальними змінними. За його допомогою плагіни знаходять свої залежності, надають послуги, реєструють ефекти, прослуховують події, ізолюють ресурси, перехоплюють доступ до послуг та координують цикли життя, саме тому Cordis представляє контекст як єдину абстракцію.
DeepSeek Harness відкриває доступ до своїх основних підсистем через цей спільний контекст.ctx.sessions
ctx.systemPrompt
ctx.tools
ctx.agents
ctx.agentLoop
ctx.llm
ctx.sessions
ctx.systemPrompt
ctx.tools
ctx.agents
ctx.agentLoop
ctx.llm
Зверніть увагу на щось незвичайне: навіть цикл агентів — це просто сервіс.
ctx.agentLoop
Отже, цей цикл можна замінити, адже це не священний код фреймворку. Це веде до основного принципу проектування: не існує привілейованого ядра, яке кожна функція мусить підтримувати.
Чому важливий цикл у форматі плагіну
Більшість фреймворків агентів містять центральний цикл, схожий на цей.
while not finished:
response = model(history)
if response.tool_call:
result = execute_tool(response.tool_call)
history.append(result)
else:
return response
Потім кожна розширена функція починає її змінювати. Схвалення перед виконанням команд? Поправка цього циклу. Відстеження? Поправка цього циклу. Повторні спроби, делегування між кількома агентами, інший бекенд для інференсу? Поправка цього циклу. Зрештою вона перетворюється на хаб, до якого підключаються інструменти, моделі та пам’ять.
Agent Loop
/ | \
/ | \
tools models memory
/ | \
approvals retries tracing
Цей цикл стає „богом“ додатку. DeepSeek Harness уникає цього, дозволяючи циклу брати участь у тій самій архітектурі плагінів, що й усі інші компоненти.
Структура одного етапу роботи агента
Під спудом взаємодія проходить через етапи, приблизно такі.
turn/start
↓
claim incoming user input
↓
assemble prompt + available tools
↓
agent/pre-step
↓
step/start
↓
record user message
↓
reconstruct conversation history
↓
send model request
↓
stream assistant response
↓
tool call?
│
├── yes → execute tool
│ record result
│ continue another step
│
└── no → finish
↓
step/end
↓
turn/end
Важливо те, що кожен етап розкриває події та межі сервісів, надаючи плагінам можливість брати участь без необхідності переписування всього середовища виконання.
Події у форматі «водоспаду» як проміжне середовище
Cordis підтримує кілька режимів виконання подій. Один з зручних режимів — «водоспад», який функціонує як проміжне середовище. Уявіть собі запит, який проходить через пайплайн.
request
↓
Plugin A
↓
Plugin B
↓
Plugin C
↓
LLM
Плагін B може обгорнути виконання обробником, який отримує наступний крок.
async function handler(next) {
console.log("before")
const result = await next()
console.log("after")
return result
}
Виконання відбувається ієрархічно, причому кожен плагін діє до та після внутрішнього виклику.
Plugin A before
Plugin B before
Plugin C before
LLM
Plugin C after
Plugin B after
Plugin A after
Це стосується дозволів, перепису запитів, телеметрії, кешування, маршрутизації моделей, перевірок безпеки та вставки контексту — жоден з цих елементів не потребує прямого вбудовування у адаптер моделі.
Модель знаходиться за межами можливостей
Цей інструмент також абстрагує LLM, тому агенту не потрібно розуміти кожен SDK постачальника; він взаємодіє з однією службою.
Agent
↓
ctx.llm
↓
Model Adapter
↓
Provider API
Один з постачальників може реалізувати це для API DeepSeek.
DeepSeek API
Інший стаття присвятована OpenAI.
OpenAI
Третій розділ присвятований Anthropic.
Anthropic
Решта архітектури агента також стосується тієї самої можливості LLM. У документації Harness це іноді називають «швом можливостей», який складається з визначення сервісу та постачальника цього сервісу.
Service Definition
↓
Service Provider
↓
Consumer
Для ШІ цей ланцюг простягається від інтерфейсу до певного постачальника.
LLM interface
↓
OpenAI provider
↓
Agent loop
Отже, додавання постачальника моделей не обов’язково означає переписування движка виконання. Ви просто надаєте іншу реалізацію тієї самої функціональності.
Сесії, засновані на подіях
Розмови не зберігаються системою як один великий змінний масив, який є джерелом істини. Натомість сесії зберігаються у вигляді потоку подій, до якого можна лише додавати нові елементи.
turn/start
user/message
assistant/chunk
assistant/chunk
assistant/message
tool/call
tool/result
assistant/message
turn/end
Історію моделі можна відновити на основі цих подій, тому журнал сеансу є джерелом істини.
Session log = source of truth
Це замінює поширену альтернативу.
Mutable chat history = source of truth
Чому агенти отримують перевагу від event sourcing
Агенти стали настільки складними, що зберігання простого списку повідомлень часто буває недостатнім.
[
{"role": "user", "content": "..."},
{"role": "assistant", "content": "..."}
]
Дебагування може вимагати знання того, який інструмент був використаний та який активовано, яка модель написала відповідь, який системний запит було застосовано, де почалася заявка, де закінчився крок міркувань, яка конфігурація була активною, чи намагання здійснити виклик було повторено та який потоковий результат надійшов у відповідь. Система фіксує структуровані події сесії, щоб можна було відтворити все, що могла бачити модель. Один із принципів її проектування полягає у тому, що все, що видиме для моделі, має бути доступне у журналі подій. Замість того, щоб здогадуватися, чому агент діяв певним чином, можна відтворити саму заявку, яка лежить у основі цих дій.
Волокна та стани життєвого циклу
Cordis представляє запущені компоненти за допомогою волокон. Це не має нічого спільного з волокнами операційної системи. Волокно Cordis — це екземпляр компонента під час виконання, який проходить через такі стани.
PENDING
↓
LOADING
↓
ACTIVE
↓
UNLOADING
↓
DISPOSED
Існують також стани збою. Що ще важливіше, волокно фіксує кілька фактів про себе.
what dependencies I need
what providers currently satisfy them
what effects I have created
what cleanup functions belong to me
Коли змінюються залежності, фібра може оновити свій життєвий цикл.
Чому важлива ідентичність постачальника
Припустимо, компонент залежить від сервісу бази даних.
database
Наразі його постачає один постачальник.
DatabaseProvider A
Під час гарячого перезавантаження воно замінюється іншим.
DatabaseProvider B
Навіть коли обидва повертають еквівалентні об’єкти JavaScript, Cordis може розрізняти ідентичності постачальників. Причина в тому, що значення залежності — це не просто наявність певного значення.
"value exists"
Це також може означати, що значення походить від іншої інстанції компонента.
"this value came from a different component instance"
Отже, заміна постачальника може спонукати залежності до правильного перезавантаження, що допомагає уникнути великої кількості помилок через застарілі посилання.
Звільнення ресурсів у порядку залежностей
Розгляньмо ланцюжок, у якому один плагін забезпечує доступ до бази даних.
Plugin A provides database
Другий плагін залежить від бази даних, а третій — від другого.
Plugin B depends on databasePlugin C depends on Plugin B
Ланцюг залежностей виглядає ось так.
A
↓
B
↓
C
Тепер перший елемент видалено. Наївний двигун виконання може негайно закрити базу даних, хоча два інші елементи все ще можуть виконуватися. Замість цього Cordis координує граф залежностей. Починається процес завантаження даних.
A begins unloading
Потім залежні об’єкти очищуються по черзі, перш ніж оригінал завершить своє очищення.
↓ mark A unavailableB notices dependency disappeared↓ B unloadsC notices B disappeared↓ C unloadsthenA completes cleanup
Порядок має величезне значення, адже це запобігає тому, щоб залежні елементи використовували те, що вже наполовину зруйноване.
Ізоляція: одна назва, окремі світи
Один глобальний простір імен для сервісів може стати обмежуючим фактором. Уявіть двох агентів, яким потрібні різні бази даних.
Agent A → Database A
Agent B → Database B
Обидва все ще прослять про те саме.
database
Cordis підтримує ізоляцію, тому вирішення проблем з послугами відбувається у парному режимі.
service name + isolation realm
і не лише за ім’ям.
service name
Концептуально кожна сфера перетворює однакову назву на свій власний екземпляр.
Realm A: database → DB_A
Realm B: database → DB_B
Така сама логічна залежність може розв’язуватися по-різному залежно від контексту, що допомагає у багатокористувацьких системах, з кількома агентами, у середовищах тестування, для плагінів у ізольованих средах та окремих робочих просторах.
Перехоплення
Cordis також може формувати доступ до послуг за допомогою метаданих. Уявіть реєстр інструментів, де адміністративний агент може бачити ці інструменти.
shell
browser
filesystem
deploy
тоді як обмежений агент бачить менший набір.
browser
filesystem-readonly
Замість створення окремого реєстру доступ можна перехоплювати залежно від контексту.
ctx + metadata
↓
service resolution
↓
modified view of capability
Це сильний патерн для систем політик.
Безпечніша заміна гарячих модулів
Гаряче завантаження здається простим.
file changed
↓
reload module
Під час роботи плагіну ситуація ускладнюється. Що робити, якщо новий модуль містить помилку, і що станеться зі старою працездатною версією? Завантажувач Cordis підтримує функцію перезавантаження, яка діє як транзакція.
working plugin
↓
code changes
↓
attempt new import
↓
success?
┌───────┴───────┐
yes no
↓ ↓
replace rollback
plugin old module
Це природно поєднується з зворотними ефектами. Плагін із чітким життєвим циклом, набором залежностей та процедурою очищення значно менш небезпечний для заміни.
Приклад з реального світу
Cordis був створений не лише для DeepSeek Harness. У статті розглядається Koishi — фреймворк чат-ботів відкритого коду, побудований на ньому, із спільнотним екосистемою, яка, за словами авторів, налічує тисячі плагінів. Справжня екосистема робить динамічне складання набагато переконливішим, ніж десять ручно створених модулів. Проте автори залишаються обережними та не стверджують, що контрольовані тестування показали значне покращення продуктивності чи ефективності. Потрібні додаткові оцінки.
Не все можна скасувати
Тут теорія зустрічається з реальністю. Деякі ефекти під час виконання справді є зворотними, як-от відкриття та закриття файлу.
open file
→ close file
Інші також добре утворюють пари.
allocate memory
→ free memorystart worker
→ terminate workerregister event listener
→ unregister listener
Є ще варіант — надіслати електронний лист.
send email
Яким буде його обернений елемент?
unsend email?
Зазвичай це неможливо, і те саме стосується групи інших дій.
send HTTP request
transfer money
publish message
delete external data
Коли щось впливає на зовнішній світ, справжнього зворотного процесу може не існувати. Найкращим доступним варіантом є компенсація.
payment → refund
message → follow-up correction
database mutation → compensating transaction
Компенсація — це не те саме, що математичне зворотне перетворення. У статті прямо визнається ця межа, і Cordis найкраще підходить для ефектів, які час виконання може справді контролювати та відновлювати.
Cordis довіряє вашому очищенню
Припустимо, що плагін запускає сервер у межах певного ефекту та повертає функцію для очищення.
ctx.effect(() => {
startServer()
return () => {
// supposedly cleanup
}
}))
Cordis не має способу довести, що процедура очищення справді зворотно змінює стан програми. Формальна модель передбачає, що зворотний процес має повернути середовище до його попереднього стану, але реалізація залежить від програміста, який має написати коректний функціонал для очищення. Тому поєднання певного ефекту з процедурою очищення є своєрідною дисципліною.
effect + cleanup
Це не автоматична формальна верифікація, і це важлива різниця.
Чому це підходить для штучних інтелектуальних агентів
Традиційні додатки залишаються досить стабільними після запуску. Агенти рухаються в протилежному напрямку. Майбутні системи агентів можуть постійно виконувати подібні операції.
install tool
remove tool
change model
spawn agent
kill agent
load skill
reload code
switch permissions
connect service
disconnect service
modify environment
Уявіть агента, який вирішує, що йому потрібна підтримка GitHub, завантажує відповідну функціональність, а потім видаляє її, коли вона більше не потрібна, або замінює несправну реалізацію. Такій системі потрібні набагато сильніші семантики складання під час виконання, ніж може запропонувати звичайний інжектор залежностей. Без них агент, який працює протягом тривалого часу, може накопичувати залишки.
orphan listeners
stale tools
dangling processes
broken dependencies
zombie services
duplicated handlers
Cordis намагається зробити композицію під час виконання концепцією першого класу в програмному забезпеченні.
Чому дизайн здається елегантним
Оскільки Cordis відповідає за композицію, DeepSeek Harness може моделювати майже все таким самим способом.
Model provider → plugin
Tool → plugin
Agent loop → plugin
Session store → plugin
UI → plugin
Telemetry → plugin
Approval system → plugin
Sandbox → plugin
Credential store → plugin
Нові функції не стають окремими випадками всередині фреймворку. Вони стають ще одними учасниками одної системи композицій.
Профілі та пакети
Якщо все є плагіном, ніхто не хоче щоразу вручну складати п’ятдесят з них. Тому інструментарій додає складання на вищому рівні. Профіль описує конфігурацію системи з іменем, а пакет розподіляє групи плагінів разом із їхньою конфігурацією. Основний пакет може виглядати ось так.
Base Bundle
├── model adapters
├── tools
├── sessions
├── sandbox
├── approvals
├── credentials
├── settings
└── telemetry
Ще один пакет може додати веб-додаток.
Web Application
Інший варіант може створити агента без голови.
Headless Agent
Архітектура залишається модульною, не ускладнюючи щоденного використання.
П’ять ідей, які варто запам’ятати
Якщо все інше зникне, саме ці п’ять моментів варто пам’ятати.
На першому місці — зворотні ефекти: будь-які зміни, які вносить компонент, мають мати спосіб їх скасування.
change + inverse
Другий тип — це реактивні коекфекти. Компоненти оголошують, що їм потрібно, а система під час виконання реагує, коли з’являються, зникають або змінюються залежності.
dependency available → activate
dependency gone → deactivate
Третім є контекст. Ефекти, залежності та доступ до сервісів існують у межах одного єдиного контексту виконання.
ctx
Четвертим є динамічний калькул компонентів, який описує компонент через те, що він потребує, що надає та що змінює, надаючи часу виконання достатню структуру для аналізу завантаження та звільнення ресурсів.
Dependencies + Provisions + Effects
П’ята — це просторово-часова композитність, яка поєднує просторові та часові аспекти.
spatial:
who depends on whom?
+
temporal:
how can components safely enter and leave?
Якщо формулювати коротко, це зворотна зміна плюс реактивна залежність.
Чому це важливо не лише для одного проекту
Більшість сучасних фреймворків агентів все ще передбачають досить статичний додаток: запуск програми, завантаження інструментів, завантаження моделі, виконання агента, зупинка. Автономні агенти прагнуть до середовищ виконання, які можуть змінювати себе під час своєї роботи. Уявіть собі агента, який може виконувати послідовність дій, схожу на цю.
discover a capability
install it
use it
upgrade it
replace it
remove it
continue running
У цей момент керування життєвим циклом плагінів перестає бути приємною архітектурною функцією та стає основною інфраструктурою. Саме це робить проект цікавим. Модель — не найбільш інноваційна частина; інноваційною є система виконання, яка її оточує.
Глибший урок
Архітектура програмного забезпечення зазвичай стосується композиції в певний момент часу: ви об’єднуєте елементи та запускаєте програму.
A + B + C
Cordis ставить ще складніші запитання.
What if A disappears?
What if B is replaced?
What if C suddenly gains a dependency?
What if another implementation of A appears?
What if all of this happens while the system is running?
Це повністю змінює сутність проблеми. Компоненти перестають бути статичними блоками та починають діяти як живі учасники: вони приходять, створюють зв’язки, змінюють своє оточення, залежать від інших та зрештою йдуть.
Висновок
DeepSeek Harness може здаватися просто ще однією рамкою для агентів, і його привабливість полягає не в тому, що він може викликати LLM чи запускати інструменти, що роблять багато інших рамок. Справжня ідея полягає у тому, що сама система складання є архітектурою. Кожна функціональність — це компонент, кожна залежність є чітко визначеною, кожен контрольований ефект знає, як себе очистити, компоненти реагують на зміни у залежностях, а навіть цикл агента може бути замінений — він не є недоторканним кодом рамки. Керівничим принципом є перетворення кожної функціональності на компонент, чітке визначення кожної залежності та забезпечення того, щоб кожен ефект мав власний механізм скасування.
У звичайних додатках це є зручною архітектурою плагінів. У довготривалих, самомодифікуючихся штучних інтелектуальних агентах це може мати набагато більше значення. Якщо агенти зрештою змінюють свій власний середовище виконання, програмному забезпеченню знадобиться принципово правильний метод змін, який не пошкоджуватиме поступово середовище, в якому воно працює. Саме цю проблему прагне вирішити DeepSeek Harness та дослідження Cordis, що лежать в її основі.
Пов’язана література
- DS-STAR: пояснення, штучний інтелектуальний агент Google та причини успіху його системи керування — детальний огляд агента DS-STAR від Google: його сім модулів, цикл звітності DS-STAR+, опубліковані запити, результати тестування та наявні обмеження.