Перейти к основному содержимому

Tools and effects

После главы вы сможете спроектировать tool boundary, где модель не вызывает произвольный код, а предлагает typed operation, которую runtime валидирует и авторизует.

Tool call — недоверенный input

Модель может выбрать несуществующее имя, пропустить поле, передать строку вместо числа или повторить старый call. Поэтому выполнение начинается не с handler:

В Helios этот pipeline разделён на prepare → authorize → invoke. Между фазами runtime перечитывает authoritative state. Это важно: interrupt, пришедший пока policy engine думал, должен остановить handler до side effect; результат handler, завершившегося уже после interrupt, наоборот, нельзя потерять — его нужно один раз записать как факт.

Контракт хорошего tool

  • одно ясное назначение;
  • machine-readable input schema;
  • структурированный output;
  • effect class;
  • typed failures;
  • tenant/user identity из trusted runtime context, а не из model arguments;
  • operation ID для записи;
  • postcondition или фактический resource ID.

Плохое имя manage_account скрывает десятки полномочий. get_account, prepare_transfer, confirm_transfer позволяют разнести read, preview и commit.

Anthropic описывает похожий эффект tool design на model performance; это provider observation, а не гарантия для любого model/tool set: Writing effective tools for agents.

Typed errors

ОшибкаЗначение для runtimeСледующий шаг
unknown_toolModel/runtime contract driftНе исполнять; re-plan или fail
invalid_argumentsSchema не пройденаДать компактную ошибку модели
policy_deniedДействие запрещеноНе retry; объяснить/эскалировать
approval_requiredНужен human decisionDurable pause
timeoutOutcome может быть неизвестенReconcile/idempotent retry
retryable_errorВременный сбой до outcomeBounded retry
permanent_errorТе же args не помогутИзменить plan/data
retry_exhaustedBudget исчерпанDegrade/escalate

«Tool failed» стирает recovery semantics. Timeout особенно опасен: внешний effect мог завершиться, хотя ответ потерялся.

Effect classes

Helios использует:

  • read — не меняет domain state;
  • reversible_write — запись с понятным rollback/release;
  • external_write — сообщение, публикация, создание внешнего ресурса;
  • destructive — необратимое удаление/изменение.

Это эвристика. Добавьте sensitivity, amount, destination, environment и legal jurisdiction, если они меняют policy.

Model decision ≠ policy decision

Модель отвечает: «полезно вызвать reserve_funds». Policy engine отвечает: «этому tenant, на эту сумму, в этом run, с этим approval — разрешено или нет».

Если prompt одновременно выбирает действие и авторизует его, prompt injection становится confused deputy: недоверенные данные убеждают систему применить чужие credentials.

Helios policy:

  • read разрешён;
  • reversible/external write требует approval;
  • destructive отключён даже при approved: true.

Commit-time authorization

Проверяйте policy максимально близко к effect. Approval, полученный час назад для 10 SOL, не должен автоматически разрешать изменённый call на 1000 SOL или другого получателя.

Approval event должен включать:

  • точный tool и arguments/preview;
  • identity approver;
  • scope и expiry;
  • решение approve/edit/reject;
  • policy/version, по которой решали.

Учебный runtime реализует три решения, но не хранит реальную identity — это явно не production auth service.

Idempotency

При crash после effect до checkpoint runtime повторит pending call. Без idempotency получится двойная reservation.

idempotency identity = tenant + operation ID
same ID + same arguments → вернуть прежний outcome
same ID + different arguments → conflict

Проверка current state перед записью помогает, но не заменяет atomic uniqueness: два worker могут одновременно увидеть «ещё не выполнено».

Lease/fence runtime защищает только собственный event store. Если stale worker уже отправил запрос во внешний банк или marketplace, downstream также должен дедуплицировать operation ID или проверять fencing/version token. Без такой поддержки остаётся reconciliation и честная at-least-once семантика.

Где должен жить business rule

МестоСильная сторонаСлабость
PromptОбъясняет intent моделиНе security boundary
Tool schemaФорма и локальные constraintsНе знает полный domain state
Policy engineAuthority и cross-cutting rulesНужны свежие inputs
Domain service/DBИнварианты и atomicityНе объясняет модели варианты

Надёжная система использует все четыре, не выбирает одно.

Helios и реальные аналоги

reserve_funds моделирует escrow hold. В neobank аналог — card authorization; в marketplace — reservation stock; в telehealth — booking slot. Во всех случаях convincing text не доказывает effect, а repeated timeout не должен умножать запись.

Лаборатория

npm run test:course:pattern -- "tool|policy|reservation"

Попробуйте добавить external_write tool. Решите, какие fields должны входить в approval preview и idempotency fingerprint.

Стратегии интерфейса

СтратегияВыигрышЦенаКогда плоха
Один универсальный toolБыстрый prototypeОгромная authority, сложные evalsProduction writes
Много узких toolsЯсные effectsTool selection overloadСотни почти одинаковых операций
Search/lazy-loaded toolsМалый contextDiscovery latency и miss5 стабильных tools
Composite domain workflow toolAtomic business operationМеньше свободы моделиOpen-ended investigation

Self-check

  • Кто задаёт tenant identity?
  • Что отличает validation error от policy denial?
  • Какие writes идемпотентны и по какому key?
  • Проверяется ли authorization прямо перед commit?
  • Возвращает ли tool фактический outcome и resource ID?
  • Что произойдёт при timeout после внешней записи?