Пристрої
Пристрій — це воркер, якого підняли не ми. З'явилося в AGNT2-267.
Усе, що продукт до цього ганяв каналом інструментів, було подом: ми його створювали, ми давали йому перепустку, виписану на одну сесію, і жив він кілька хвилин. Пристрій — інший вид співрозмовника на тому самому каналі: річ, якою хтось володіє, яка стоїть у домі, увімкнена місяцями й вимкнена тиждень, і яка телефонує нам сама.
Чому це взагалі працює
Через перший структурний факт зі сторінки каналу інструментів: воркер телефонує назовні, і ніхто не телефонує всередину. Це писалося про под — і виявилося саме тією властивістю, якої потребує Raspberry Pi за домашнім роутером. До нього не можна достукатися ззовні, і не треба.
Це не нова архітектура. Це наявна, повернута.
Що спільного із сесією — а спільного майже все
Дріт, цілком: субпротокол, обрамлення JSON-RPC, рукостискання MCP, відповідь tools/list, співвіднесення tools/call і коди закриття. Усе це — канал інструментів без змін, і один клас веде його для обох видів співрозмовника. Коду протоколу у слайсі пристрою немає взагалі.
Чого не спільного — і яка за це ціна
Сесія визначається своїми стелями: ttlSeconds, maxExecSeconds, вікно простою, яке читає жнець, сім станів, шість причин відмови, четверо дверей розбирання. Пристрій не має жодної з них, тож це власна таблиця, а не сесія з дев'ятьма обнуленими колонками.
Ціна названа, а не залишена на виявлення:
- Тепер на одному каналі два види співрозмовника. Кожному майбутньому читачеві групи
runtime/доведеться питати «сесія чи пристрій?» там, де раніше була одна відповідь, а тому, хто розбирає сокет, — дивитися у дві таблиці замість однієї. - Чотири механізми до пристрою не застосовуються. Каталог профілів (наскільки великий), жнець дедлайнів (коли помре), четверо дверей розбирання (як прибирається) і шість причин відмови (чому не стартував) — усе це машинерія сесії. Читач, який гадає, що група
runtime/має один життєвий цикл, помилиться.
Дешевший варіант програв із конкретної причини: зробити сесію безстроковою означає перетворити дев'ять її колонок на «null тут означає, що рядок не зовсім сесія», і кожному читачеві — жнецеві, підмітальнику, розбиранню, екрану стану — довелося б вивчити другу форму рядка. Однією необнуленою колонкою менше — і жнець видаляє чиюсь камеру за те, що вона дев'яносто секунд мовчала.
Рядок — він же й обліковий запис
publicId + secretHash, той самий поділ, що в ключа вбудовування: зберігається не робочий ключ.
Відмінність від ключа вбудовування — у тому, що саме називає обліковий запис. Там ключ називає команду, і одна команда може мати їх скільки завгодно. Тут ключ і є особистістю пристрою, один на рядок — бо відкликання має зупиняти один пристрій, і бо канал зобов'язаний знати, який саме пристрій щойно зателефонував.
Ключ висить на команді, а не на агентові, тож видалена команда не може лишити по собі робочий обліковий запис.
Маршрути
GET /teams/:teamId/devices усі пристрої команди
GET /agents/:id/devices ті, до яких цей агент має право звертатися
POST /agents/:id/devices прив'язати
POST /agents/:id/devices/:deviceId/disconnect обірвати живе з'єднання
DELETE /agents/:id/devices/:deviceId відв'язатиДе код
| сам пристрій, його канал, ключ | api/src/slices/runtime/device |
| прив'язка до агента, набір інструментів, темп викликів | api/src/slices/agent/device |
Див. також Використання та Канал інструментів.