Пошаговые инструкции advanced 25 мин

Как подключить инструменты к ИИ-агенту: tool calling без хаоса

Пошаговая инструкция по tool calling для ИИ-агента: tool registry, JSON Schema, backend executor, validation, policy gate, idempotency, approval, audit log и evals.

AI-агенты tool calling audit log Инструкция function calling JSON Schema human approval backend validation

Что получится в результате

Соберем безопасный контур tool calling для ИИ-агента. Модель будет не выполнять действия напрямую, а предлагать tool call в строгом формате. Backend проверит JSON schema, права пользователя, политику инструмента, лимиты, idempotency, риск действия и только потом выполнит tool или отправит действие на approval.

В результате будет рабочий MVP:

  1. инструменты описаны в `tool_registry`;
  2. версии схем хранятся в `tool_schema_versions`;
  3. права на tools лежат в `tool_policy`;
  4. входные аргументы проверяются в `tool_argument_checks`;
  5. каждый запрос модели сохраняется в `model_call_log`;
  6. предложенные tool calls пишутся в `tool_call_candidates`;
  7. backend-решение пишется в `policy_gate_log`;
  8. выполнение tools идет через `tool_execution_queue`;
  9. результаты tools сохраняются в `tool_result_log`;
  10. retries пишутся в `tool_retry_log`;
  11. идемпотентность контролируется через `idempotency_keys`;
  12. опасные действия идут через `approval_queue`;
  13. все внешние API calls пишутся в `external_api_log`;
  14. ошибки tools пишутся в `error_log`;
  15. стоимость и задержка пишутся в `cost_log` и `latency_log`;
  16. тесты tools лежат в `tool_eval_cases`;
  17. результаты тестов пишутся в `tool_eval_runs`;
  18. все решения фиксируются в `audit_log`.

Первая версия должна подключить 2-3 простых инструмента: read-only поиск, создание черновика задачи и действие с approval. Этого достаточно, чтобы проверить всю архитектуру без риска.

Что понадобится

Минимальный набор:

  1. один ИИ-агент;
  2. модель с поддержкой tool calling или structured output;
  3. backend, который исполняет tools;
  4. база для реестра tools, логов и очередей;
  5. JSON Schema для каждого инструмента;
  6. список ролей пользователей;
  7. policy gate перед выполнением tools;
  8. approval для опасных действий;
  9. тестовый API или sandbox;
  10. 20-40 тестовых сценариев.

Для первого запуска возьмите три инструмента: `search_knowledge_base`, `create_task_draft`, `send_email`. Первые два можно разрешить в ограниченном режиме, а `send_email` сразу сделать `approval_required`.

Шаг 1. Выберите один сценарий MVP

Не подключайте все API компании сразу.

Хорошие первые сценарии:

  1. поиск ответа в базе знаний;
  2. чтение карточки CRM;
  3. создание черновика задачи;
  4. создание черновика письма;
  5. проверка статуса заказа;
  6. расчет стоимости доставки;
  7. поиск файла;
  8. создание заявки на согласование;
  9. обновление безопасного служебного поля;
  10. отправка уведомления внутри команды.

Для этой инструкции берем сценарий: агент отвечает клиенту, ищет информацию в базе знаний, при необходимости создает черновик задачи менеджеру и готовит письмо, но не отправляет его без approval.

Проверка: первый MVP не имеет tool, который удаляет данные или отправляет деньги.

Шаг 2. Разделите tools по риску

Создайте классы риска до написания кода.

Классы:

  1. `read_only` - только чтение данных;
  2. `draft_only` - создание черновика без внешнего эффекта;
  3. `write_internal` - изменение внутренней системы;
  4. `send_message` - отправка сообщения человеку;
  5. `external_write` - действие во внешнем сервисе;
  6. `payment` - деньги, возвраты, счета;
  7. `delete` - удаление данных;
  8. `permission_change` - права доступа и публичные ссылки.

Правило для MVP:

  1. `read_only` можно выполнять после проверки доступа;
  2. `draft_only` можно выполнять после schema validation;
  3. `write_internal` только через approval;
  4. `send_message`, `payment`, `delete`, `permission_change` не выполнять напрямую.

Проверка: у каждого tool есть риск до того, как он появился в prompt.

Шаг 3. Создайте `tool_registry`

`tool_registry` - реестр всех инструментов.

Колонки:

id
tool_name
display_name
description
tool_type
risk_level
side_effect_type
owner
is_active
created_at
updated_at

Стартовые инструменты:

search_knowledge_base | Поиск по базе знаний | retrieval | low | read_only
read_customer_profile | Чтение клиента | api | medium | read_only
create_task_draft | Черновик задачи | api | medium | draft_only
send_email | Отправка письма | api | high | send_message
update_crm_field | Обновление CRM | api | high | write_internal

Проверка: tool не может использоваться агентом, если его нет в `tool_registry` или `is_active = false`.

Шаг 4. Версионируйте схемы tools

Создайте `tool_schema_versions`.

Колонки:

id
tool_name
schema_version
input_schema_json
output_schema_json
status
created_at

Пример `search_knowledge_base`:

{
  "type": "object",
  "additionalProperties": false,
  "required": ["query", "top_k"],
  "properties": {
    "query": {"type": "string", "minLength": 3, "maxLength": 500},
    "top_k": {"type": "integer", "minimum": 1, "maximum": 10},
    "filters": {"type": "object"}
  }
}

Проверка: изменение схемы создает новую версию, а не ломает старые traces.

Шаг 5. Опишите `tool_policy`

`tool_policy` решает, кто и когда может вызвать tool.

Колонки:

id
tool_name
role
condition_json
allow_call
requires_approval
max_calls_per_run
max_payload_size
is_active

Пример:

search_knowledge_base | any | {} | yes | no | 10 | 20kb
read_customer_profile | support | {"same_account":true} | yes | no | 5 | 20kb
create_task_draft | support | {} | yes | no | 3 | 50kb
send_email | support | {"recipient_verified":true} | yes | yes | 1 | 50kb
delete_customer | any | {} | no | yes | 0 | 0

Проверка: модель может предложить `delete_customer`, но backend всегда вернет block.

Шаг 6. Сделайте backend executor

Модель не должна сама ходить в API. Она возвращает намерение вызвать tool, а backend исполняет.

Компоненты:

  1. `tool_call_parser` - извлекает tool name и arguments;
  2. `schema_validator` - проверяет JSON Schema;
  3. `policy_gate` - проверяет права и риск;
  4. `executor` - вызывает реальный код;
  5. `result_normalizer` - приводит результат к схеме;
  6. `audit_logger` - пишет решения;
  7. `retry_manager` - управляет повторами;
  8. `approval_manager` - отправляет опасное действие на согласование.

Проверка: даже если модель "уверена", без backend executor tool не выполняется.

Шаг 7. Логируйте model calls

Создайте `model_call_log`.

Колонки:

id
run_id
provider
model_id
prompt_version
input_tokens
output_tokens
status
latency_ms
created_at

Логируйте:

  1. модель;
  2. prompt version;
  3. входные и выходные токены;
  4. latency;
  5. finish reason;
  6. был ли tool call;
  7. ошибку, если модель не ответила.

Проверка: можно понять, какая модель предложила неправильный tool.

Шаг 8. Сохраняйте tool call candidates

Создайте `tool_call_candidates`.

Колонки:

id
run_id
model_call_id
tool_name
arguments_json
arguments_hash
confidence
status
created_at

Статусы:

  1. `proposed`;
  2. `schema_failed`;
  3. `blocked_by_policy`;
  4. `waiting_approval`;
  5. `queued`;
  6. `executed`;
  7. `failed`;

Проверка: предложенный model tool call сохраняется до выполнения, чтобы его можно было расследовать.

Шаг 9. Валидируйте аргументы

Создайте `tool_argument_checks`.

Колонки:

id
run_id
candidate_id
tool_name
schema_version
is_valid
errors_json
normalized_arguments_json
created_at

Проверяйте:

  1. обязательные поля;
  2. типы данных;
  3. enum values;
  4. минимумы и максимумы;
  5. формат email;
  6. формат даты;
  7. размер payload;
  8. отсутствие лишних полей;
  9. принадлежность resource_id пользователю;
  10. отсутствие prompt injection в строковых аргументах.

Проверка: arguments с лишним полем `send_now=true` не проходят validation, если поле не описано в schema.

Шаг 10. Добавьте policy gate

Создайте `policy_gate_log`.

Колонки:

id
run_id
candidate_id
tool_name
user_id
role
policy_result
matched_policy_id
requires_approval
block_reason
created_at

Policy gate проверяет:

  1. tool активен;
  2. роль пользователя разрешена;
  3. user имеет доступ к ресурсу;
  4. лимит вызовов не превышен;
  5. risk level допустим;
  6. side effect разрешен;
  7. approval нужен или нет;
  8. cost limit не превышен;
  9. idempotency key есть для write-действий;
  10. tool не запрещен в текущем workflow.

Проверка: backend блокирует tool до executor, если правило не прошло.

Шаг 11. Настройте idempotency

Идемпотентность нужна, чтобы retry не создал две задачи или два письма.

Создайте `idempotency_keys`.

Колонки:

id
idempotency_key
run_id
tool_name
arguments_hash
status
result_ref
created_at
expires_at

Правила:

  1. для write-действий idempotency key обязателен;
  2. key строится из run_id, tool_name и normalized arguments hash;
  3. повтор с тем же key возвращает старый результат;
  4. key имеет TTL;
  5. разные arguments не должны использовать один key.

Проверка: повторный retry `create_task_draft` не создает дубль.

Шаг 12. Выполняйте tools через очередь

Создайте `tool_execution_queue`.

Колонки:

id
run_id
candidate_id
tool_name
payload_json
idempotency_key
status
attempts
run_after
created_at
started_at
finished_at

Статусы:

  1. `queued`;
  2. `running`;
  3. `completed`;
  4. `failed`;
  5. `retry_scheduled`;
  6. `cancelled`;
  7. `waiting_approval`;

Проверка: внешний API вызывается worker, а не напрямую из ответа модели.

Шаг 13. Сохраняйте результаты tools

Создайте `tool_result_log`.

Колонки:

id
run_id
execution_id
tool_name
status
result_json
result_summary
external_id
created_at

Результат должен быть нормализован:

{
  "ok": true,
  "resource_type": "task",
  "resource_id": "TASK-123",
  "summary": "Создан черновик задачи для менеджера"
}

Проверка: модель получает не сырой API response, а очищенный и безопасный результат.

Шаг 14. Настройте retries

Создайте `tool_retry_log`.

Колонки:

id
run_id
execution_id
tool_name
attempt
retry_reason
next_run_at
created_at

Retry разрешен для:

  1. timeout;
  2. rate limit;
  3. transient API error;
  4. network error;
  5. temporary unavailable.

Retry запрещен для:

  1. schema validation fail;
  2. policy block;
  3. access denied;
  4. approval rejected;
  5. insufficient funds;
  6. invalid resource id;
  7. dangerous action.

Проверка: policy block не повторяется автоматически.

Шаг 15. Добавьте approval для опасных действий

Создайте `approval_queue`.

Колонки:

id
run_id
candidate_id
tool_name
requested_action
risk_level
payload_summary
requested_by
approver
status
approved_at
rejected_reason

Через approval идут:

  1. отправка email клиенту;
  2. изменение CRM;
  3. платеж;
  4. возврат;
  5. удаление данных;
  6. публикация ссылки;
  7. изменение прав;
  8. экспорт PII;
  9. массовое обновление;
  10. внешний webhook с side effect.

Проверка: `send_email` создает approval и не попадает в `tool_execution_queue` до approve.

Шаг 16. Логируйте внешние API

Создайте `external_api_log`.

Колонки:

id
run_id
tool_name
provider
endpoint
method
request_hash
response_status
response_hash
latency_ms
created_at

Не пишите в обычные логи токены, raw PII и секреты. Храните hash и summary.

Проверка: по внешнему id можно связать tool execution и запрос к API.

Шаг 17. Обрабатывайте ошибки tools

Создайте `error_log`.

Колонки:

id
run_id
tool_name
component
error_code
error_message
retryable
attempt
created_at

Типовые ошибки:

  1. invalid arguments;
  2. policy denied;
  3. approval rejected;
  4. access denied;
  5. API timeout;
  6. rate limit;
  7. duplicate idempotency key conflict;
  8. resource not found;
  9. provider error;
  10. result schema invalid.

Проверка: пользователь получает понятное сообщение, а не "tool failed".

Шаг 18. Считайте latency и стоимость

Создайте `latency_log`.

Колонки:

id
run_id
component
operation
latency_ms
created_at

Создайте `cost_log`.

Колонки:

id
run_id
cost_type
provider
amount
currency
created_at

Считайте:

  1. latency модели;
  2. latency tool;
  3. latency очереди;
  4. стоимость model call;
  5. стоимость внешнего API;
  6. стоимость retries;
  7. стоимость failed runs;
  8. стоимость approval задержки.

Проверка: понятно, что дороже и медленнее: модель или tool.

Шаг 19. Верните результат tool обратно модели

После tool execution модель должна получить безопасный результат.

Правила:

  1. вернуть только нужные поля;
  2. убрать секреты;
  3. маскировать PII;
  4. добавить статус;
  5. добавить external_id при необходимости;
  6. добавить warning, если результат неполный;
  7. не отдавать raw stack trace;
  8. не отдавать внутренние tokens.

Пример:

{
  "tool": "create_task_draft",
  "status": "completed",
  "result": {
    "task_id": "TASK-123",
    "state": "draft",
    "url": "https://crm.example/tasks/TASK-123"
  }
}

Проверка: модель формирует ответ пользователю по безопасному tool result, а не по сырому API payload.

Шаг 20. Настройте audit log

Создайте `audit_log`.

Колонки:

id
run_id
user_id
event_type
tool_name
decision
summary
created_at

Фиксируйте:

  1. tool предложен моделью;
  2. schema validation passed или failed;
  3. policy gate result;
  4. approval request;
  5. approval result;
  6. tool queued;
  7. tool executed;
  8. tool failed;
  9. retry scheduled;
  10. result returned to model.

Проверка: по одному tool call можно восстановить весь путь от предложения модели до результата.

Шаг 21. Напишите системное правило для модели

Системное правило должно объяснять модели, что tools не являются прямыми действиями.

Шаблон:

Ты можешь предлагать tool calls только из списка доступных tools.
Ты не выполняешь действия сам.
Backend проверяет schema, права, policy и approval.
Если нужного tool нет, скажи, что действие недоступно.
Если данных недостаточно, запроси недостающие поля.
Для опасных действий всегда выставляй requires_approval=true.
Не пытайся обойти policy через другой tool.

Проверка: модель не выдумывает tools и не обещает, что действие уже выполнено, если оно только в approval.

Шаг 22. Сделайте tool prompt коротким

В описание tool включайте только то, что помогает выбрать tool.

Для каждого tool укажите:

  1. когда использовать;
  2. когда не использовать;
  3. обязательные поля;
  4. ограничения;
  5. риск;
  6. что вернется;
  7. нужен ли approval.

Не кладите в tool description секреты, API paths, внутренние токены и длинные инструкции.

Проверка: model prompt содержит tool schema, но не раскрывает backend credentials.

Шаг 23. Добавьте тесты tool calling

Создайте `tool_eval_cases`.

Колонки:

id
case_name
input_json
expected_tool
expected_arguments_json
forbidden_tools_json
expected_policy_result
risk_level
is_active

Добавьте тесты:

  1. обычный поиск в базе знаний;
  2. создание черновика задачи;
  3. нехватка обязательного поля;
  4. попытка отправить email без approval;
  5. prompt injection с просьбой удалить данные;
  6. access denied;
  7. invalid resource id;
  8. retryable API error;
  9. non-retryable policy block;
  10. duplicate idempotency key.

Проверка: тест проверяет не только текст ответа, но и tool name, arguments и policy result.

Шаг 24. Запускайте tool eval runs

Создайте `tool_eval_runs`.

Колонки:

id
eval_case_id
agent_version
model_id
actual_tool
actual_arguments_json
policy_result
passed
failure_reason
created_at

Запускайте evals:

  1. перед добавлением tool;
  2. перед изменением schema;
  3. перед заменой модели;
  4. перед изменением prompt;
  5. после инцидента;
  6. по расписанию.

Проверка: если новая модель начала вызывать запрещенный tool, релиз блокируется.

Шаг 25. Проверьте end-to-end сценарий

Сценарий:

  1. пользователь просит помочь с заявкой;
  2. модель предлагает `search_knowledge_base`;
  3. backend валидирует arguments;
  4. policy gate разрешает read-only tool;
  5. worker выполняет поиск;
  6. результат возвращается модели;
  7. модель предлагает `create_task_draft`;
  8. backend проверяет schema и policy;
  9. worker создает черновик;
  10. модель предлагает `send_email`;
  11. policy gate отправляет действие в approval;
  12. письмо не отправляется до approve;
  13. все события есть в `audit_log`.

Проверка: в production не произошло ни одного write-действия без backend approval.

Шаг 26. Минимальный результат для запуска

MVP tool calling готов, если выполнены условия:

  1. есть `tool_registry`;
  2. у каждого tool есть JSON Schema;
  3. схемы версионируются;
  4. есть `tool_policy`;
  5. модель только предлагает tool call;
  6. backend валидирует arguments;
  7. backend проверяет policy gate;
  8. write-действия требуют approval;
  9. есть idempotency для write tools;
  10. execution идет через очередь;
  11. retries ограничены;
  12. tool result нормализован;
  13. все события есть в `audit_log`;
  14. есть `tool_eval_cases`;
  15. есть мониторинг latency, cost и errors.

Проверка результата: отключите tool в `tool_registry` и убедитесь, что модель не может выполнить его через старый prompt или повторный запрос.

Что нельзя автоматизировать в первой версии

В первой версии не автоматизируйте:

  1. удаление данных;
  2. платежи и возвраты;
  3. изменение прав доступа;
  4. отправку внешних сообщений без approval;
  5. массовое обновление CRM;
  6. публикацию ссылок;
  7. экспорт PII;
  8. создание новых tools моделью;
  9. изменение tool schema моделью;
  10. выполнение tool без backend validation;
  11. retry policy block;
  12. хранение API keys в prompt;
  13. передачу raw API response модели;
  14. работу без idempotency для write actions;
  15. production-запуск без audit log.

Сначала подключите read-only и draft-only tools. Write-tools добавляйте только после evals, approval и мониторинга.

Частые вопросы

Tool calling и function calling - это одно и то же?

В практике почти да: модель возвращает имя функции или инструмента и JSON-аргументы. Важно не название, а архитектура: модель предлагает вызов, backend проверяет и только потом выполняет действие.

Можно ли доверять аргументам, которые вернула модель?

Нет. Аргументы всегда нужно валидировать через JSON Schema, проверять типы, лимиты, доступ к ресурсам, risk level и policy. Модель может ошибиться или попасть под prompt injection.

Почему tools нельзя выполнять прямо из ответа модели?

Потому что это обход безопасности. Между моделью и реальным API должен быть backend executor: schema validation, policy gate, idempotency, approval, retries, logs и audit trail.

Какие tools подключать первыми?

Начните с read-only: поиск по базе знаний, чтение статуса, получение карточки. Потом draft-only: создать черновик задачи или письма. Write-tools подключайте после approval и evals.

Что делать, если модель вызывает не тот tool?

Сохраните run в `tool_eval_cases`, уточните tool descriptions, schema и routing, проверьте model choice. Если ошибка dangerous, добавьте policy block и regression test.

Дальше по теме

Похожие материалы