Skip to content

@Tool

Registra uma classe como ferramenta. A lógica fica em execute.

ts
@Tool({
  name: "ler_arquivo",
  description: "Lê o conteúdo de um arquivo do projeto.",
  schema: z.object({ caminho: z.string() }),
})
export class LerArquivoTool {
  async execute(@input() { caminho }: { caminho: string }) {
    return readFile(caminho, "utf8");
  }
}

Opções

CampoTipoO que faz
namestringidentificador que o modelo usa para chamar
descriptionstringlido pelo modelo — é como ele decide quando usar
schemaz.ZodTypevalida os argumentos antes do execute

execute

Os parâmetros são declarados com decorators de injeção — cada um diz o que quer, e a ordem não importa:

ts
async execute(
  @input() args: { caminho: string },   // os argumentos já validados pelo schema
  @context() ctx: AgentContext,          // o contexto da execução
  @state() s: RevisaoState,              // o estado do workflow
): string | ToolOutput | Promise<string | ToolOutput>

Só o @input() é comum; os outros dois são para quando a ferramenta precisa de algo do fluxo.

Um execute sem decorator nenhum recebe os argumentos no primeiro parâmetro — o formato de antes da 0.5.0, mantido por compatibilidade.

ts
type ToolOutput = {
  content: string;        // o texto que volta ao modelo
  isError?: boolean;      // marca como falha (nó de erro no report)
  data?: unknown;         // carga livre, ignorada pelo modelo
};

Devolver uma string equivale a { content, isError: false }.

Injeção no construtor

O construtor recebe o WorkflowRuntime, para disparar outro workflow:

ts
export class DeployTool {
  constructor(private readonly runtime: WorkflowRuntime) {}
}

Tools sem construtor ignoram o argumento.

Erros

Por padrão, um throw no execute derruba a execução. Para virar observação que volta ao modelo:

ts
export const config: ThenaConfig = { toolErrors: "observe" };

Um throw no hook beforeTool cancela a ferramenta e propaga — isso não muda com toolErrors.

A classe precisa mesmo de execute

O decorator exige o método em tempo de compilação; uma classe sem ele não compila. E há uma checagem em runtime para quem não passa pelo tsc, com mensagem que aponta a classe.