← AI Foundation

Каталог инструментов

ai-foundation · workzone
Прогноз схемы. Дом таблицы tools — в модели данных этого модуля; связь выбора агента (agent_tools) — в Agent Engine. Ниже — концепция, не контракт API.

Инструмент — вызываемая функция, которую платформа даёт модели как tool-schema. Каталог инструментов держит Admin.

Модель зовёт по имени
──▶ даём как tool-schema
Инструмент имя · параметры · тело
──▶ результат в контекст
Ответ модель продолжает
Каталог управляет набором — что включено · видит чат · разрешено агентам Исполнение — общий tool-calling харнесс, не здесь
Инструмент против промпта → Тексты prompt

Разные сущности, их не путать.

Инструмент функция
  • имя · параметры · тело
  • подаётся как структурированная tool-schema
  • модель зовёт по имени → результат в контекст
Промпт текст
  • инструкция, что и как делать
  • направляет поведение, не вызывается

Схема инструмента приходит из структурированного источника, не из прозы админа — контракт вызова надёжен и не ломается правкой текста.

Откуда берётся инструмент — реестр типов → Реестр коннекторов

Каталог открытый; механизм — реестр типов, зеркало реестра коннекторов Harvester: тип объявляет себя классом (имя · tool-schema · вид credential · тело) и саморегистрируется.

тип — класс в коде, саморегистрируется  ──▶  экземпляр — строка в tools (флаги + ключ)

preset v1
Встроенные read-only классы платформы: web_search, fetch_url.
custom v1
Свой класс организации по тому же контракту — pip-пакетом или в дереве, в папке custom/ (свой инструмент).
mcp · openapi v2
Внешний самоописывающийся сервер, без кода.

Провайдер за интерфейсом. web_search — один инструмент для модели (web_search(query)), а провайдер (Tavily · Brave · Serper · Google CSE) выбирает админ на экране, не конфиг-файлом: выбор ложится в несекретную колонку config, ключ — в credential_enc. Модель видит одну стабильную схему; чем её исполнить — дело адаптера. Тот же приём, что у провайдеров ai_models и встроенного эмбеддера.

Секрет инструмента (API-ключ) — не в config (JSONB), а в отдельной колонке credential_enc: шифротекст AES-256-GCM крипто-ядром Auth, наружу — только флаг «задан». Как ключи провайдеров и SMTP. Человекочитаемое имя идёт через t(), в БД — только ключ.

Свой инструмент — кодом → Свой коннектор

Организация добавляет свой инструмент одним классом по контракту: тело — метод call, tool-schema — в манифесте, регистрация декоратором.

# куда положить свой класс — два пути
✦ канонический
  pip-пакет  entry point  achilles.tools
  ядро не трогаешь · апгрейд платформы чист

○ быстрый dev
  в дереве  achilles/ai_foundation/tools/custom/
  своя папка · не мешает встроенным
  1. 1 подкласс · call
  2. 2 манифест · схема
  3. 3 @register_tool
web_search.py
# 3 · discovery подхватит сам
@register_tool
class WebSearchTool(BaseTool):       # контракт: схема + call

    manifest = ToolManifest(             # определяет, что видит модель
        name       = "web_search",       # ключ + имя в tool-schema
        params     = {"query": str},     # аргументы для модели
        access     = ReadOnly,           # read_only · write
        config     = [Provider],         # Tavily · Brave · Serper · CSE
        credential = [ApiKey],           # → credential_enc
    )

    def call(self, args):               # тело инструмента
        return provider.search(args.query)

    def probe(self):                     # кнопка «Протестировать» → status
        return provider.ping()           # active · error
#  любым способом ниже — в дереве или pip-пакетом — класс виден
#   только после пересборки образа и передеплоя контейнера:
#   discovery читает классы на старте процесса, не из Admin
achilles/ai_foundation/tools/ · в дереве
├── base.py        BaseTool — контракт: манифест + call
├── registry.py    discovery: пакет + entry points
├── web_search.py  ┐ встроенные
├── fetch_url.py   ┘ пресеты (read-only)
└── custom/        ← платформа папку не трогает
    └── jira.py    ← свой класс сюда
achilles-jira-tool/ · отдельный pip-пакет
# ядро не трогаем — discovery найдёт через entry point
├── tool.py         ← тот же класс по контракту
└── pyproject.toml  [project.entry-points."achilles.tools"]

Контракт нейтрален: read-only — политика пресетов платформы, а свой класс может писать — под ответственность организации, как custom-коннектор (общий процесс, без песочницы; оператор сам решает, что ставить). Контракт < 1.0 не заморожен — пакет ребилдится под версию платформы.

Появление в каталоге — само

Список на экране — живой реестр типов, не таблица: таблица tools хранит только состояние (флаги + ключ) и связана с типом по name. Поэтому новый класс встаёт в каталог сам — без миграции и правок UI.

Две поверхности — чат и агенты → Tool-calling харнесс

Один каталог питает обе поверхности, но контур у них разный.

Чат
один раунд → ответ
  • KS-поиск + инструменты, включённые админом (chat_enabled)
  • 1..N инструментов параллельно, напр. база знаний + web
Агент
петля ↻ до потолка
  • ядро из 3 KS-инструментов (search · graph · sql, всегда, locked)
  • + выбранные владельцем из allowlist

KS-ядро у агента не снимается. Снятие добавленного инструмента — мягкая деградация: агент продолжает на ядре и в гейт готовности не входит (в отличие от снятия модели, которое агента останавливает).

«Locked» — про конфигурацию, не про безусловность. «Всегда» и «locked» у ядра значат «нельзя выключить вручную ни админу, ни владельцу», а не «присутствует при любом состоянии базы». Есть вторая, производная ось: при пустой базе (is_empty) KS-инструменты не подаются вовсе — искать нечем. Это единый принцип на обе поверхности: и search_knowledge у чата, и ядро у агента отпадают, пока в базе нет данных; решает это общий харнесс, а не отметка админа. Не «снятие» и не деградация конфигом — просто отсутствие данных; наполнится база — ядро вернётся само.

Допуск: две независимые отметки → Экран Инструменты AI

Каталог — лишь реестр типов; допуск инструмента к работе задают две независимые отметки, по одной на поверхность. Обе по умолчанию выключены — инструмент входит в работу только осознанным действием админа; активен он, пока подан хоть одной.

Чат OFF
chat_enabled — инструмент виден чату.
ставит админ
Allowlist агентов OFF
agents_allowed — разрешён к выбору владельцем в редакторе агента.
ставит админ

Включение инструмента и смена его настройки (провайдер, ключ) — это админ-действие: оно ложится в аудит-журнал наравне с прочими изменениями доступа (сами вызовы модели туда не льются — журнал держит значимые события, не каждый запрос). Дефолт OFF и аудит включения — периметр осторожности: внешний выход открывается явно и под наблюдением. Лимит / бюджет вызовов web_searchv2.

Проверка работоспособности — кнопка у админа → Так же у AI-моделей

Ключ задан, провайдер выбран — но рабочий ли он? Админ не должен узнавать о протухшем ключе из жалоб пользователей. У каждого инструмента с внешним выходом — кнопка «Протестировать»: платформа зовёт probe() типа (лёгкий пинг провайдера, не настоящий запрос модели) и сохраняет итог. Зеркало проверки соединения у провайдеров AI-моделей.

active error unchecked
Внешние серверы — MCP v2

Подключение внешних MCP-серверов и инструментов записи — следующая итерация. Зафиксированный дизайн: per-user OAuth (каждый пользователь авторизуется сам), ACL держит сам сервер, доступ read-only через курирование админом. В макетах — серые неактивные заглушки.