То, что мы экспонируем агенту, — это функции. Сегодня LLM их диспетчирует (выбирает по семантике description, передаёт args через JSON-схему), потому что underlying inference ещё не детерминирована. Когда станет — те же функции остаются, просто вызываются напрямую из pipeline-кода. Тело то же, интерфейс тот же, dispatcher меняется: LLM-dispatch → deterministic-dispatch.
Это третья ось рядом с двумя другими страницами про tooling агента:
- tool-calling — как делать tool calls (industry-standard pattern, провайдеры, parallel calls)
- code-mode-pattern — code execution как альтернативный pattern (LLM пишет код вместо дискретных invocations)
- Эта страница — когда LLM в pipeline вообще нужен и как pipeline эволюционирует по мере того, как underlying-операции становятся решёнными
Конкретный callsite в нашей системе
Прямой пример — diagnostician с тремя tools (lookup_biomarker, lookup_domain, submit_diagnostic_plan). Сегодня LLM нужна из-за остаточного fuzziness:
- Tier 1 — fuzzy-match имени биомаркера ↔ запись в biomarker-graph (Креатинин ↔ «креатинин крови» ↔ Creatinine ↔ …)
- Tier 2 — domain-классификация когда биомаркер не нашёлся (LLM читает
scope-описания доменов)
Когда появится LOINC-классификатор (biomarker-graph-key-loinc) — оба tier’а уйдут на детерминистический lookup, агентский цикл свернётся, останутся простые function calls в pipeline-коде. Tier 3 (model_knowledge — биомаркер в графе отсутствует совсем) — единственное место где LLM реально незаменим.
То есть три tools — это API будущего pipeline’а, который мы сейчас вынуждены диспетчить через LLM. Дизайн-decision’ы (как разбить, какие args, что возвращать) переживут смену dispatcher’а.
Design — тот же craft, другой consumer
Когда программист пишет API для другого программиста — он думает: где границы между функциями, какие типы параметров, что возвращается, как ошибки распространяются. То же самое, когда пишем tool для агента. Краcт одинаковый — разбиение задачи на slot’ы, типизация, naming, cohesion. Меняется consumer:
| Consumer | Поведение | Что это меняет |
|---|---|---|
| Код | Детерминистический — точно следует написанному | Inputs предсказуемые; ошибки — bug в коде |
| Агент | Стохастический — выбирает по семантике description, может ошибиться в выборе или в args | Tool description = часть контракта (не docstring); failure modes — partial / wrong-tool / arg-misinterpretation наряду с обычными bug’ами |
Практическое следствие: при дизайне tool’а нельзя «забыть про description» и положиться на типы. У детерминированного consumer’а типы — primary контракт; у стохастического — description несёт сигнал не меньше типов. Field order в schema тоже значимо (structured-output-field-order-cot).
Спектр scope’а — от tool до библиотеки
Tool-calling — не единственный режим экспонирования возможностей агенту. Шире — спектр того, какую поверхность мы даём LLM:
| Режим | Поверхность | Масштаб |
|---|---|---|
| Tool calling (tool-calling) | 3-20 typed tools со схемой | Узкий набор ручек |
| Code execution (code-mode-pattern) | Typed bindings + sandbox; LLM пишет код | API-поверхность целой библиотеки |
Code execution — предельный случай той же идеи: вместо нескольких ручек агент получает полноценную библиотеку с typed API, в которой filter/map/reduce/dataframe-style операции — естественные function calls. Дизайн-craft тот же — что cohesive, какие границы, какие типы. Что меняется — scope; и появляется выбор: проектируем библиотеку сами (custom bindings для domain’а) или используем готовую (Python stdlib, pandas, FHIR client SDK).
Этот scope-выбор ортогонален migration-оси (tool → function): даже когда underlying станет детерминированным, библиотека-как-поверхность останется библиотекой; LLM-dispatch внутри неё свернётся, но bindings и их дизайн — то же мышление, что и для small-set tools.
Открытые вопросы
- Какие наши сегодняшние tools — конкретные кандидаты на migration в обычный function call? Tier 1/2 Диагноста зафиксированы; остальные 4 production-агента (mastra) — не аудитили под этим углом.
- Где tool description реально несёт signal, а где он избыточный? «Description как часть контракта» — гипотеза, не измеряли вклад description’а в quality / iteration count.
- Когда переходить с tool-calling на code execution? code-mode-pattern оставляет открытым — у нас пока ни один agent не упёрся в потолок tool-calling настолько, чтобы оправдать сложность sandbox-инфраструктуры.
Связано
- tool-calling — industry-standard pattern: как именно делать tool calls (провайдеры, parallel, gotchas)
- code-mode-pattern — code execution как предельный scope; «целая библиотека вместо нескольких ручек»
- diagnostician — конкретный callsite с tools, которые мигрируют в function call при появлении LOINC-классификатора
- biomarker-graph-key-loinc — миграция Tier 1/2 lookup’а на deterministic dispatch
- structured-output-field-order-cot — field order в schema = part of stochastic-consumer контракта