Skip to content

Sub-agente isolado

Às vezes uma subtarefa é ruidosa: dez voltas de tentativa e erro para chegar a uma resposta de uma linha. Se isso acontece no mesmo histórico, o agente principal carrega todo o ruído — e com modelo pequeno, isso degrada as decisões dele.

A saída é rodar a subtarefa num workflow próprio, disparado por uma tool:

agente pai  (histórico enxuto)
 └─ tool ──▶ workflow isolado  (estado próprio)
              ├─ 10 voltas de tentativa e erro
              └─ devolve UMA string ao pai

Como se escreve

O construtor da tool recebe o WorkflowRuntime injetado:

ts
import { Tool, WorkflowRuntime } from "@thenajs/core";
import { z } from "zod";
import { DeployWorkflow } from "../workflows/deploy.workflow.js";

@Tool({
  name: "deploy",
  description: "Executa o processo de deploy e devolve o resultado.",
  schema: z.object({ repositorio: z.string() }),
})
export class DeployTool {
  constructor(private readonly runtime: WorkflowRuntime) {}

  async execute(@input() args: { repositorio: string }) {
    return this.runtime.run(DeployWorkflow, {
      input: { message: `Faça o deploy de ${input.repositorio}` },
      memory: { ambiente: "staging" },   // contexto explícito para o filho
    });
  }
}

O filho começa com estado novo: só recebe o que você passou em input e memory.

Isso é bom — o ruído dele não polui o pai — e tem um custo: ele começa sem saber o que foi pedido. Se precisar repassar algo da conversa do pai, peça o contexto:

ts
import { Tool, WorkflowRuntime, input, context } from "@thenajs/core";

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

  async execute(
    @input() { repositorio }: { repositorio: string },
    @context() ctx: AgentContext,
  ) {
    const pedido = ctx.state.history.find((m) => m.role === "user")?.content;

    return this.runtime.run(DeployWorkflow, {
      input: { message: `Faça o deploy de ${repositorio}` },
      memory: { pedidoOriginal: pedido },
    });
  }
}

É o caso de uso central do @context(): você escolhe o que atravessa o isolamento, em vez de tudo ou nada.

Step ou tool? O guia de decisão

É a escolha arquitetural central de um workflow, e as duas formas parecem equivalentes até a primeira vez que a diferença morde.

sub-agente como stepsub-agente como tool
Históricocompartilhado com o paipróprio, isolado
A saída viramensagem assistantobservação de ferramenta
Quem decide se rodavocê, na ordem dos stepso modelo, chamando a tool
Custo de contexto no paitodos os turnos do filhouma string
Use quandoé uma conversa só e o pai precisa ver o caminhoa subtarefa é ruidosa, ou só o resultado importa

A visibilidade não se perde

O report aninha a execução do filho dentro do nó da tool:

workflow WorkflowPai
  agent AgentePai
    chat
      tool deploy
        workflow DeployWorkflow      ← o filho aparece aqui
          agent DeployAgent
            chat

Você abriu mão do contexto compartilhado, não da observabilidade.

O orçamento não atravessa

Cada run tem contador próprio. Um budget no pai não soma o consumo dos filhos. Se o subworkflow é caro, passe um budget no runtime.run dele também.