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.
17 KiB
| layout | title | parent |
|---|---|---|
| default | Serviços de Ferramentas: Ferramentas de Agente Dinamicamente Plugáveis | Portuguese (Beta) |
Serviços de Ferramentas: Ferramentas de Agente Dinamicamente Plugáveis
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.
Status
Implementado
Visão Geral
Esta especificação define um mecanismo para ferramentas de agente dinamicamente plugáveis, chamadas "serviços de ferramentas". Ao contrário dos tipos de ferramentas integradas existentes (KnowledgeQueryImpl, McpToolImpl, etc.), os serviços de ferramentas permitem que novas ferramentas sejam introduzidas por:
- Implantando um novo serviço baseado em Pulsar
- Adicionando um descritor de configuração que informa ao agente como invocá-lo
Isso permite a extensibilidade sem modificar o framework de resposta do agente principal.
Terminologia
| Termo | Definição |
|---|---|
| Ferramenta Integrada | Tipos de ferramentas existentes com implementações codificadas em tools.py |
| Serviço de Ferramenta | Um serviço Pulsar que pode ser invocado como uma ferramenta de agente, definido por um descritor de serviço |
| Ferramenta | Uma instância configurada que referencia um serviço de ferramenta, exposta ao agente/LLM |
Este é um modelo de duas camadas, análogo às ferramentas MCP: MCP: O servidor MCP define a interface da ferramenta → A configuração da ferramenta a referencia Serviços de Ferramenta: O serviço de ferramenta define a interface Pulsar → A configuração da ferramenta a referencia
Contexto: Ferramentas Existentes
Implementação de Ferramenta Integrada
As ferramentas são atualmente definidas em trustgraph-flow/trustgraph/agent/react/tools.py com implementações tipadas:
class KnowledgeQueryImpl:
async def invoke(self, question):
client = self.context("graph-rag-request")
return await client.rag(question, self.collection)
Cada tipo de ferramenta:
Possui um serviço Pulsar pré-definido que ele chama (por exemplo, graph-rag-request)
Conhece o método exato a ser chamado no cliente (por exemplo, client.rag())
Possui argumentos tipados definidos na implementação
Registro de Ferramentas (service.py:105-214)
As ferramentas são carregadas da configuração com um campo type que mapeia para uma implementação:
if impl_id == "knowledge-query":
impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection"))
elif impl_id == "text-completion":
impl = TextCompletionImpl
# ... etc
Arquitetura
Modelo de Duas Camadas
Camada 1: Descritor do Serviço de Ferramenta
Um serviço de ferramenta define uma interface de serviço Pulsar. Ele declara: As filas Pulsar para solicitação/resposta Os parâmetros de configuração que ele requer das ferramentas que o utilizam
{
"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}
]
}
Um serviço de ferramenta que não requer parâmetros de configuração:
{
"id": "calculator",
"request-queue": "non-persistent://tg/request/calc",
"response-queue": "non-persistent://tg/response/calc",
"config-params": []
}
Nível 2: Descritor de Ferramenta
Uma ferramenta referencia um serviço de ferramenta e fornece: Valores de parâmetros de configuração (que satisfazem os requisitos do serviço) Metadados da ferramenta para o agente (nome, descrição) Definições de argumentos para o 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"
}
]
}
Múltiplas ferramentas podem referenciar o mesmo serviço com diferentes configurações:
{
"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"
}
]
}
Formato da Requisição
Quando uma ferramenta é invocada, a requisição ao serviço da ferramenta inclui:
user: Do pedido do agente (multi-tenência)
config: Valores de configuração codificados em JSON, provenientes da descrição da ferramenta
arguments: Argumentos codificados em JSON, provenientes do LLM
{
"user": "alice",
"config": "{\"collection\": \"customers\"}",
"arguments": "{\"question\": \"What are the top customer complaints?\"}"
}
O serviço de ferramenta recebe estes como dicionários analisados no método invoke.
Implementação Genérica do Serviço de Ferramenta
Uma classe ToolServiceImpl invoca serviços de ferramenta com base na configuração:
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)
Decisões de Design
Modelo de Configuração de Duas Camadas
Os serviços de ferramentas seguem um modelo de duas camadas semelhante às ferramentas MCP:
- Serviço de Ferramenta: Define a interface do serviço Pulsar (tópico, parâmetros de configuração necessários)
- Ferramenta: Referencia um serviço de ferramenta, fornece valores de configuração, define argumentos do LLM
Essa separação permite: Que um único serviço de ferramenta seja usado por várias ferramentas com diferentes configurações Uma distinção clara entre a interface do serviço e a configuração da ferramenta A reutilização das definições de serviço
Mapeamento de Solicitações: Transmissão com Envelope
A solicitação a um serviço de ferramenta é um envelope estruturado contendo:
user: Propagado do pedido do agente para multi-inquilinato
Valores de configuração: Do descritor da ferramenta (por exemplo, collection)
arguments: Argumentos fornecidos pelo LLM, transmitidos como um dicionário
O gerenciador de agente analisa a resposta do LLM em act.arguments como um dicionário (agent_manager.py:117-154). Este dicionário é incluído no envelope da solicitação.
Tratamento de Esquemas: Não Tipados
As solicitações e respostas usam dicionários não tipados. Não há validação de esquema no nível do agente - o serviço de ferramenta é responsável por validar suas entradas. Isso fornece o máximo de flexibilidade para definir novos serviços.
Interface do Cliente: Tópicos Pulsar Diretos
Os serviços de ferramentas usam tópicos Pulsar diretos, sem a necessidade de configuração de fluxo. O descritor do serviço de ferramenta especifica os nomes completos das filas:
{
"id": "joke-service",
"request-queue": "non-persistent://tg/request/joke",
"response-queue": "non-persistent://tg/response/joke",
"config-params": [...]
}
Isso permite que os serviços sejam hospedados em qualquer namespace.
Tratamento de Erros: Convenção de Erro Padrão
As respostas do serviço de ferramenta seguem a convenção de esquema existente com um campo error:
@dataclass
class Error:
type: str = ""
message: str = ""
Estrutura da resposta:
Sucesso: error é None, a resposta contém o resultado
Erro: error é preenchido com type e message
Isso corresponde ao padrão usado em todo o serviço existente (por exemplo, PromptResponse, QueryResponse, AgentResponse).
Correlação de Requisições/Respostas
As requisições e respostas são correlacionadas usando um id nas propriedades da mensagem Pulsar:
A requisição inclui id nas propriedades: properties={"id": id}
A(s) resposta(s) incluem o mesmo id: properties={"id": id}
Isso segue o padrão existente usado em todo o código-fonte (por exemplo, agent_service.py, llm_service.py).
Suporte a Streaming
Os serviços de ferramenta podem retornar respostas em streaming:
Múltiplas mensagens de resposta com o mesmo id nas propriedades
Cada resposta inclui o campo end_of_stream: bool
A resposta final tem end_of_stream: True
Isso corresponde ao padrão usado em AgentResponse e outros serviços de streaming.
Tratamento da Resposta: Retorno de String
Todas as ferramentas existentes seguem o mesmo padrão: receber argumentos como um dicionário, retornar a observação como uma string.
| Ferramenta | Tratamento da Resposta |
|---|---|
KnowledgeQueryImpl |
Retorna client.rag() diretamente (string) |
TextCompletionImpl |
Retorna client.question() diretamente (string) |
McpToolImpl |
Retorna uma string, ou json.dumps(output) se não for uma string |
StructuredQueryImpl |
Formata o resultado para uma string |
PromptImpl |
Retorna client.prompt() diretamente (string) |
Os serviços de ferramenta seguem o mesmo contrato:
O serviço retorna uma resposta em string (a observação)
Se a resposta não for uma string, ela é convertida via json.dumps()
Nenhuma configuração de extração é necessária no descritor
Isso mantém o descritor simples e coloca a responsabilidade de retornar uma resposta de texto apropriada para o agente no serviço.
Guia de Configuração
Para adicionar um novo serviço de ferramenta, são necessários dois itens de configuração:
1. Configuração do Serviço de Ferramenta
Armazenado sob a chave de configuração tool-service. Define as filas Pulsar e os parâmetros de configuração disponíveis.
| Campo | Obrigatório | Descrição |
|---|---|---|
id |
Sim | Identificador único para o serviço de ferramenta |
request-queue |
Sim | Tópico Pulsar completo para requisições (por exemplo, non-persistent://tg/request/joke) |
response-queue |
Sim | Tópico Pulsar completo para respostas (por exemplo, non-persistent://tg/response/joke) |
config-params |
Não | Array de parâmetros de configuração que o serviço aceita |
Cada parâmetro de configuração pode especificar:
name: Nome do parâmetro (obrigatório)
required: Se o parâmetro deve ser fornecido pelas ferramentas (padrão: falso)
Exemplo:
{
"id": "joke-service",
"request-queue": "non-persistent://tg/request/joke",
"response-queue": "non-persistent://tg/response/joke",
"config-params": [
{"name": "style", "required": false}
]
}
2. Configuração da Ferramenta
Armazenado sob a chave de configuração tool. Define uma ferramenta que o agente pode usar.
| Campo | Obrigatório | Descrição |
|---|---|---|
type |
Sim | Deve ser "tool-service" |
name |
Sim | Nome da ferramenta exposto para o LLM |
description |
Sim | Descrição do que a ferramenta faz (mostrada para o LLM) |
service |
Sim | ID do serviço de ferramenta a ser invocado |
arguments |
Não | Array de definições de argumentos para o LLM |
| (parâmetros de configuração) | Varia | Quaisquer parâmetros de configuração definidos pelo serviço |
Cada argumento pode especificar:
name: Nome do argumento (obrigatório)
type: Tipo de dados, por exemplo, "string" (obrigatório)
description: Descrição mostrada para o LLM (obrigatório)
Exemplo:
{
"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)"
}
]
}
Carregando a Configuração
Use tg-put-config-item para carregar as configurações:
# 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
O agente-gerenciador deve ser reiniciado para aplicar novas configurações.
Detalhes da Implementação
Esquema
Tipos de requisição e resposta em 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
Servidor: DynamicToolService
Classe base em 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()
Cliente: ToolServiceImpl
Implementação em 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)
Arquivos
| Arquivo | Propósito |
|---|---|
trustgraph-base/trustgraph/schema/services/tool_service.py |
Esquemas de requisição/resposta |
trustgraph-base/trustgraph/base/tool_service_client.py |
Cliente para invocar serviços |
trustgraph-base/trustgraph/base/dynamic_tool_service.py |
Classe base para implementação de serviço |
trustgraph-flow/trustgraph/agent/react/tools.py |
Classe ToolServiceImpl |
trustgraph-flow/trustgraph/agent/react/service.py |
Carregamento de configuração |
Exemplo: Serviço de Piadas
Um exemplo de serviço em 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}"
Configuração do serviço de ferramenta:
{
"id": "joke-service",
"request-queue": "non-persistent://tg/request/joke",
"response-queue": "non-persistent://tg/response/joke",
"config-params": [{"name": "style", "required": false}]
}
Configuração da ferramenta:
{
"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"}
]
}
Compatibilidade com versões anteriores
Os tipos de ferramentas integradas existentes continuam a funcionar sem alterações.
tool-service é um novo tipo de ferramenta, juntamente com os tipos existentes (knowledge-query, mcp-tool, etc.).
Considerações futuras
Serviços de autoanúncio
Uma melhoria futura poderia permitir que os serviços publicassem seus próprios descritores:
Os serviços publicam em um tópico tool-descriptors conhecido na inicialização.
O agente se inscreve e registra dinamicamente as ferramentas.
Permite um verdadeiro sistema de plug-and-play sem alterações de configuração.
Isso está fora do escopo da implementação inicial.
Referências
Implementação atual da ferramenta: trustgraph-flow/trustgraph/agent/react/tools.py
Registro de ferramentas: trustgraph-flow/trustgraph/agent/react/service.py:105-214
Esquemas do agente: trustgraph-base/trustgraph/schema/services/agent.py