trustgraph/docs/tech-specs/tool-services.ru.md
Alex Jenkins 8954fa3ad7 Feat: TrustGraph i18n & Documentation Translation Updates (#781)
Native CLI i18n: The TrustGraph CLI has built-in translation support
that dynamically loads language strings. You can test and use
different languages by simply passing the --lang flag (e.g., --lang
es for Spanish, --lang ru for Russian) or by configuring your
environment's LANG variable.

Automated Docs Translations: This PR introduces autonomously
translated Markdown documentation into several target languages,
including Spanish, Swahili, Portuguese, Turkish, Hindi, Hebrew,
Arabic, Simplified Chinese, and Russian.
2026-04-14 12:08:32 +01:00

23 KiB
Raw Blame History

layout title parent
default Сервисы инструментов: Динамически подключаемые инструменты для агентов Russian (Beta)

Сервисы инструментов: Динамически подключаемые инструменты для агентов

Beta Translation: This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.

Статус

Реализовано

Обзор

Эта спецификация определяет механизм динамически подключаемых инструментов для агентов, называемых "сервисами инструментов". В отличие от существующих встроенных типов инструментов (KnowledgeQueryImpl, McpToolImpl и т.д.), сервисы инструментов позволяют добавлять новые инструменты путем:

  1. Развертывания нового сервиса на базе Pulsar
  2. Добавления описания конфигурации, которое сообщает агенту, как его вызывать

Это обеспечивает расширяемость без изменения основной структуры агента.

Терминология

Термин Определение
Встроенный инструмент Существующие типы инструментов с жестко закодированными реализациями в tools.py
Сервис инструмента Сервис Pulsar, который может быть вызван как инструмент для агента, определенный описанием сервиса
Инструмент Настроенный экземпляр, который ссылается на сервис инструмента и предоставляется агенту/LLM

Это двухзвенная модель, аналогичная инструментам MCP: MCP: MCP-сервер определяет интерфейс инструмента → Конфигурация инструмента ссылается на него Сервисы инструментов: Сервис инструмента определяет интерфейс Pulsar → Конфигурация инструмента ссылается на него

Обзор: Существующие инструменты

Реализация встроенного инструмента

Инструменты в настоящее время определены в trustgraph-flow/trustgraph/agent/react/tools.py с типизированными реализациями:

class KnowledgeQueryImpl:
    async def invoke(self, question):
        client = self.context("graph-rag-request")
        return await client.rag(question, self.collection)

Каждый тип инструмента: Имеет жестко заданный сервис Pulsar, к которому он обращается (например, graph-rag-request) Знает точный метод, который нужно вызвать у клиента (например, client.rag()) Имеет типизированные аргументы, определенные в реализации

Регистрация инструментов (service.py:105-214)

Инструменты загружаются из конфигурации с помощью поля type, которое сопоставляется с реализацией:

if impl_id == "knowledge-query":
    impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection"))
elif impl_id == "text-completion":
    impl = TextCompletionImpl
# ... etc

Архитектура

Двухуровневая модель

Уровень 1: Описание сервиса инструмента

Сервис инструмента определяет интерфейс сервиса Pulsar. Он объявляет: Очереди Pulsar для запросов/ответов Параметры конфигурации, которые он требует от инструментов, использующих его

{
  "id": "custom-rag",
  "request-queue": "non-persistent://tg/request/custom-rag",
  "response-queue": "non-persistent://tg/response/custom-rag",
  "config-params": [
    {"name": "collection", "required": true}
  ]
}

Сервис, который не требует параметров конфигурации:

{
  "id": "calculator",
  "request-queue": "non-persistent://tg/request/calc",
  "response-queue": "non-persistent://tg/response/calc",
  "config-params": []
}

Уровень 2: Описание инструмента

Инструмент ссылается на сервис инструмента и предоставляет: Значения параметров конфигурации (соответствующие требованиям сервиса) Метаданные инструмента для агента (название, описание) Определения аргументов для LLM

{
  "type": "tool-service",
  "name": "query-customers",
  "description": "Query the customer knowledge base",
  "service": "custom-rag",
  "collection": "customers",
  "arguments": [
    {
      "name": "question",
      "type": "string",
      "description": "The question to ask about customers"
    }
  ]
}

Несколько инструментов могут ссылаться на один и тот же сервис с разными конфигурациями:

{
  "type": "tool-service",
  "name": "query-products",
  "description": "Query the product knowledge base",
  "service": "custom-rag",
  "collection": "products",
  "arguments": [
    {
      "name": "question",
      "type": "string",
      "description": "The question to ask about products"
    }
  ]
}

Формат запроса

Когда вызывается инструмент, запрос к службе инструмента включает в себя: user: Из запроса агента (многопользовательский режим) config: Значения конфигурации, закодированные в формате JSON, из описания инструмента arguments: Аргументы, закодированные в формате JSON, из LLM

{
  "user": "alice",
  "config": "{\"collection\": \"customers\"}",
  "arguments": "{\"question\": \"What are the top customer complaints?\"}"
}

Сервис инструментов получает это в виде разобранных словарей в методе invoke.

Общая реализация сервиса инструментов

Класс ToolServiceImpl вызывает сервисы инструментов на основе конфигурации:

class ToolServiceImpl:
    def __init__(self, context, request_queue, response_queue, config_values, arguments, processor):
        self.request_queue = request_queue
        self.response_queue = response_queue
        self.config_values = config_values  # e.g., {"collection": "customers"}
        # ...

    async def invoke(self, **arguments):
        client = await self._get_or_create_client()
        response = await client.call(user, self.config_values, arguments)
        if isinstance(response, str):
            return response
        else:
            return json.dumps(response)

Принятые решения по проектированию

Модель конфигурации с двумя уровнями

Сервисы инструментов следуют двухслойной модели, аналогичной инструментам MCP:

  1. Сервис инструмента: Определяет интерфейс сервиса Pulsar (тема, необходимые параметры конфигурации).
  2. Инструмент: Ссылается на сервис инструмента, предоставляет значения конфигурации, определяет аргументы LLM.

Это разделение позволяет: Использовать один сервис инструмента несколькими инструментами с разными конфигурациями. Четко различать интерфейс сервиса и конфигурацию инструмента. Повторное использование определений сервисов.

Отображение запросов: Прямая передача с оболочкой

Запрос к сервису инструмента представляет собой структурированную оболочку, содержащую: user: Передается из запроса агента для поддержки многопользовательской среды. Значения конфигурации: Из описателя инструмента (например, collection). arguments: Аргументы, предоставленные LLM, передаются в виде словаря.

Менеджер агента анализирует ответ LLM в act.arguments в виде словаря (agent_manager.py:117-154). Этот словарь включается в оболочку запроса.

Обработка схем: Без типов

Запросы и ответы используют нетипизированные словари. Отсутствует проверка схемы на уровне агента - сервис инструмента отвечает за проверку своих входных данных. Это обеспечивает максимальную гибкость при определении новых сервисов.

Клиентский интерфейс: Прямые темы Pulsar

Сервисы инструментов используют прямые темы Pulsar без необходимости настройки потоков. Описатель сервиса инструмента указывает полные имена очередей:

{
  "id": "joke-service",
  "request-queue": "non-persistent://tg/request/joke",
  "response-queue": "non-persistent://tg/response/joke",
  "config-params": [...]
}

Это позволяет размещать сервисы в любом пространстве имен.

Обработка ошибок: Стандартная конвенция для ошибок

Ответы сервисов инструментов соответствуют существующей схеме с полем error:

@dataclass
class Error:
    type: str = ""
    message: str = ""

Структура ответа: Успех: error имеет значение None, ответ содержит результат Ошибка: error заполняется значениями type и message

Это соответствует шаблону, используемому во всех существующих схемах сервисов (например, PromptResponse, QueryResponse, AgentResponse).

Корреляция запросов и ответов

Корреляция запросов и ответов осуществляется с использованием id в свойствах сообщения Pulsar:

Запрос включает id в свойствах: properties={"id": id} Ответы включают тот же id: properties={"id": id}

Это соответствует существующему шаблону, используемому во всей кодовой базе (например, agent_service.py, llm_service.py).

Поддержка потоковой передачи

Сервисы инструментов могут возвращать потоковые ответы:

Несколько сообщений ответа с тем же id в свойствах Каждый ответ включает поле end_of_stream: bool Заключительный ответ имеет end_of_stream: True

Это соответствует шаблону, используемому в AgentResponse и других сервисах потоковой передачи.

Обработка ответов: Возврат строки

Все существующие инструменты следуют одному и тому же шаблону: получение аргументов в виде словаря, возврат наблюдения в виде строки.

Инструмент Обработка ответов
KnowledgeQueryImpl Возвращает client.rag() напрямую (строка)
TextCompletionImpl Возвращает client.question() напрямую (строка)
McpToolImpl Возвращает строку, или json.dumps(output), если это не строка
StructuredQueryImpl Форматирует результат в строку
PromptImpl Возвращает client.prompt() напрямую (строка)

Сервисы инструментов следуют тому же контракту: Сервис возвращает строковый ответ (наблюдение) Если ответ не является строкой, он преобразуется с помощью json.dumps() Не требуется конфигурация извлечения в дескрипторе

Это упрощает дескриптор и возлагает ответственность на сервис по возврату соответствующего текстового ответа для агента.

Руководство по настройке

Для добавления нового сервиса инструмента требуются два элемента конфигурации:

1. Конфигурация сервиса инструмента

Хранится под ключом конфигурации tool-service. Определяет очереди Pulsar и доступные параметры конфигурации.

Поле Обязательно Описание
id Да Уникальный идентификатор для сервиса инструмента
request-queue Да Полная тема Pulsar для запросов (например, non-persistent://tg/request/joke)
response-queue Да Полная тема Pulsar для ответов (например, non-persistent://tg/response/joke)
config-params Нет Массив параметров конфигурации, которые принимает сервис

Каждый параметр конфигурации может указывать: name: Имя параметра (обязательно) required: Должен ли параметр предоставляться инструментами (по умолчанию: false)

Пример:

{
  "id": "joke-service",
  "request-queue": "non-persistent://tg/request/joke",
  "response-queue": "non-persistent://tg/response/joke",
  "config-params": [
    {"name": "style", "required": false}
  ]
}

2. Конфигурация инструмента

Хранится под ключом конфигурации tool. Определяет инструмент, которым может пользоваться агент.

Поле Обязательно Описание
type Да Должно быть "tool-service"
name Да Название инструмента, доступное для LLM
description Да Описание того, что делает инструмент (отображается для LLM)
service Да ID сервиса инструмента, который необходимо вызвать
arguments Нет Массив определений аргументов для LLM
(параметры конфигурации) Зависит Любые параметры конфигурации, определенные сервисом

Каждый аргумент может содержать: name: Имя аргумента (обязательно) type: Тип данных, например, "string" (обязательно) description: Описание, отображаемое для LLM (обязательно)

Пример:

{
  "type": "tool-service",
  "name": "tell-joke",
  "description": "Tell a joke on a given topic",
  "service": "joke-service",
  "style": "pun",
  "arguments": [
    {
      "name": "topic",
      "type": "string",
      "description": "The topic for the joke (e.g., programming, animals, food)"
    }
  ]
}

Загрузка конфигурации

Используйте tg-put-config-item для загрузки конфигураций:

# Load tool-service config
tg-put-config-item tool-service/joke-service < joke-service.json

# Load tool config
tg-put-config-item tool/tell-joke < tell-joke.json

Агент-менеджер должен быть перезапущен для применения новых конфигураций.

Детали реализации

Схема

Типы запросов и ответов в trustgraph-base/trustgraph/schema/services/tool_service.py:

@dataclass
class ToolServiceRequest:
    user: str = ""           # User context for multi-tenancy
    config: str = ""         # JSON-encoded config values from tool descriptor
    arguments: str = ""      # JSON-encoded arguments from LLM

@dataclass
class ToolServiceResponse:
    error: Error | None = None
    response: str = ""       # String response (the observation)
    end_of_stream: bool = False

Серверная часть: DynamicToolService

Базовый класс в trustgraph-base/trustgraph/base/dynamic_tool_service.py:

class DynamicToolService(AsyncProcessor):
    """Base class for implementing tool services."""

    def __init__(self, **params):
        topic = params.get("topic", default_topic)
        # Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic}
        # Sets up Consumer and Producer

    async def invoke(self, user, config, arguments):
        """Override this method to implement the tool's logic."""
        raise NotImplementedError()

Клиентская часть: ToolServiceImpl

Реализация в trustgraph-flow/trustgraph/agent/react/tools.py:

class ToolServiceImpl:
    def __init__(self, context, request_queue, response_queue, config_values, arguments, processor):
        # Uses the provided queue paths directly
        # Creates ToolServiceClient on first use

    async def invoke(self, **arguments):
        client = await self._get_or_create_client()
        response = await client.call(user, config_values, arguments)
        return response if isinstance(response, str) else json.dumps(response)

Файлы

Файл Назначение
trustgraph-base/trustgraph/schema/services/tool_service.py Схемы запросов/ответов
trustgraph-base/trustgraph/base/tool_service_client.py Клиент для вызова сервисов
trustgraph-base/trustgraph/base/dynamic_tool_service.py Базовый класс для реализации сервиса
trustgraph-flow/trustgraph/agent/react/tools.py Класс ToolServiceImpl
trustgraph-flow/trustgraph/agent/react/service.py Загрузка конфигурации

Пример: Сервис шуток

Пример сервиса на trustgraph-flow/trustgraph/tool_service/joke/:

class Processor(DynamicToolService):
    async def invoke(self, user, config, arguments):
        style = config.get("style", "pun")
        topic = arguments.get("topic", "")
        joke = pick_joke(topic, style)
        return f"Hey {user}! Here's a {style} for you:\n\n{joke}"

Конфигурация сервиса инструментов:

{
  "id": "joke-service",
  "request-queue": "non-persistent://tg/request/joke",
  "response-queue": "non-persistent://tg/response/joke",
  "config-params": [{"name": "style", "required": false}]
}

Конфигурация инструмента:

{
  "type": "tool-service",
  "name": "tell-joke",
  "description": "Tell a joke on a given topic",
  "service": "joke-service",
  "style": "pun",
  "arguments": [
    {"name": "topic", "type": "string", "description": "The topic for the joke"}
  ]
}

Обратная совместимость

Существующие встроенные типы инструментов продолжают работать без изменений. tool-service - это новый тип инструмента, который существует наряду с существующими типами (knowledge-query, mcp-tool и т.д.).

Будущие соображения

Сервисы с автоматическим оповещением

В будущем можно будет реализовать функцию, позволяющую сервисам публиковать свои собственные описания:

Сервисы публикуют информацию при запуске в определенной теме tool-descriptors. Агент подписывается и динамически регистрирует инструменты. Это обеспечивает возможность подключения и использования без изменения конфигурации.

Это выходит за рамки первоначальной реализации.

Ссылки

Текущая реализация инструментов: trustgraph-flow/trustgraph/agent/react/tools.py Регистрация инструментов: trustgraph-flow/trustgraph/agent/react/service.py:105-214 Схемы агента: trustgraph-base/trustgraph/schema/services/agent.py