100 lines
4.0 KiB
Markdown
100 lines
4.0 KiB
Markdown
---
|
|
name: creating-jasmine-tools
|
|
description: Defines the standard for creating Tools compatible with Jasmine (Captain AI) and the Agents gem. Use when the user needs to create a new Ruby tool class.
|
|
---
|
|
|
|
# Objetivo
|
|
|
|
Padronizar a criação de ferramentas no escopo `Captain::Tools` para garantir compatibilidade com `Agents::Tool`, `RubyLLM` e o sistema de injeção de dependência da Jasmine.
|
|
|
|
# Caminhos Padrão
|
|
|
|
- **Local principal:** `enterprise/lib/captain/tools/`
|
|
- **Alternativo (se service-heavy):** `enterprise/app/services/captain/tools/`
|
|
|
|
# Template Base
|
|
|
|
```ruby
|
|
module Captain
|
|
module Tools
|
|
class NomeDaSuaTool < Captain::Tools::BasePublicTool
|
|
# Definir tool_name se for diferente do nome da classe (Opcional)
|
|
# def name
|
|
# 'nome_da_tool'
|
|
# end
|
|
|
|
def description
|
|
'Descrição curta e objetiva do que a ferramenta faz. Isso é visível para a IA.'
|
|
end
|
|
|
|
# Definição de Parâmetros (DSL da gem Agents)
|
|
param :parametro_um, type: 'string', desc: 'Descrição do parâmetro', required: true
|
|
param :parametro_dois, type: 'integer', desc: 'Descrição do parâmetro opcional', required: false
|
|
|
|
# Método principal de execução
|
|
# tool_context: Objeto de contexto (pode conter estado da conversa)
|
|
# kwargs: Argumentos passados pela IA já normalizados
|
|
def perform(tool_context, **kwargs)
|
|
# 1. Logging Inicial Padronizado
|
|
Rails.logger.info "[#{self.class.name}] Iniciando execução. Params: #{kwargs.inspect}"
|
|
|
|
# 2. Resolução de Dependências (Conversa/Contato)
|
|
# O BasePublicTool já tenta popular @conversation e @user no initialize,
|
|
# mas podemos garantir reload ou fallback aqui.
|
|
ensure_context!(tool_context)
|
|
|
|
return "Erro: Conversa não identificada." unless @conversation
|
|
|
|
# 3. Lógica da Ferramenta
|
|
parametro_um = kwargs[:parametro_um]
|
|
|
|
result = executa_logica(parametro_um)
|
|
|
|
# 4. Retorno
|
|
# Sempre retornar String ou Hash serializável (JSON friendly)
|
|
result
|
|
rescue StandardError => e
|
|
handle_error(e)
|
|
end
|
|
|
|
private
|
|
|
|
def ensure_context!(tool_context)
|
|
# Se @conversation não veio no initialize, tenta extrair do contexto
|
|
if @conversation.nil? && tool_context.present?
|
|
state = resolve_context(tool_context)
|
|
@conversation = find_conversation(state)
|
|
end
|
|
end
|
|
|
|
def executa_logica(dado)
|
|
# Implementação...
|
|
"Sucesso: #{dado}"
|
|
end
|
|
|
|
def handle_error(exception)
|
|
Rails.logger.error "[#{self.class.name}] Erro: #{exception.message}"
|
|
Rails.logger.error exception.backtrace.first(5).join("\n")
|
|
"Ocorreu um erro técnico ao processar sua solicitação: #{exception.message}"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
```
|
|
|
|
# Checklist de Verificação
|
|
|
|
1. **Herança:** A classe herda de `Captain::Tools::BasePublicTool` (para tools públicas) ou `Captain::Tools::BaseTool`?
|
|
2. **Método `perform`:** Está implementando `perform` ao invés de apenas `execute` (para compatibilidade total com `Agents`)?
|
|
3. **Parâmetros:** Os parâmetros estão definidos com `param :nome, type: ...`? Isso ajuda a gerar o esquema JSON automaticamente para a LLM.
|
|
4. **Logging:** Existe log no início (`info`) e no rescue (`error`) com prefixo `[NomeClass]`?
|
|
5. **Contexto:** A ferramenta lida com o fato de `@conversation` poder ser nulo (ex: uso fora do fluxo web)?
|
|
6. **Retorno:** O retorno é texto ou JSON string (algo que a LLM possa ler)?
|
|
|
|
# Boas Práticas
|
|
|
|
- **Snake Case:** Nomes de arquivo em snake_case (ex: `check_availability_tool.rb`).
|
|
- **Nomes Claros:** O método `name` (ou o nome da classe inferido) deve ser claro (ex: `consultar_saldo` é melhor que `acao_banco`).
|
|
- **Idempotência:** Se possível, a ferramenta deve ser segura de rodar múltiplas vezes (ex: checar disponibilidade não altera estado, reservar altera - cuidado).
|
|
- **Tratamento de Erros:** Nunca deixe uma exception explodir para a LLM. Capture `StandardError` e retorne uma mensagem amigável de erro.
|