То, что мы экспонируем агенту, — это функции. Сегодня 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, может ошибиться в выборе или в argsTool 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 контракта