Skip to content

Run e RunHandle

ts
const app = Thena.create(MeuWorkflow, config); // não é async
const exec = app.run({ prompt: "oi" });
const resultado = await exec;
await app.dispose();

Thena.create(ClasseDoWorkflow, config?)

Devolve um WorkflowApp. Não é async — montar o app não espera nada.

ts
Thena.create<T = string, D extends RunData = RunData>(
  ClasseDoWorkflow, config?: ThenaConfig
): WorkflowApp<T, D>

T é o tipo da saída da execução; D tipa o run({ data }) e o context<D>().data.

bootstrapWorkflow é a forma async depreciada

Continua funcionando para não quebrar código da 0.6. Use o Thena.create.

WorkflowApp

MembroO que faz
run(options)inicia uma execução, devolve um RunHandle de forma síncrona
use(plugin)acopla um plugin. Dê await, e chame antes do run
dispose()aborta as execuções em voo, espera elas soltarem, encerra os plugins

Chamadas concorrentes ao run são seguras: cada uma abre o próprio RunContext.

WorkflowRunOptions

ts
await app.run({
  prompt: "Revise src/",
  state: { memory: ["userId: 123"] },
  data: { contaId: "acme" },
  budget: { maxChatCalls: 20 },
  signal: AbortSignal.timeout(30_000),
  observe: true,
  report: false,
  log: "verbose",
});
OpçãoTipoObservações
promptstringa primeira mensagem user da execução. Não é o prompt do agente, que é o markdown de sistema dele
statePartial<State>de onde a execução parte: history, tasks, memory. O handle.state devolve o próximo
dataDo seu canal — nunca vai ao modelo nem ao report
budgetRunBudgetsem ele, nada é medido
signalAbortSignalcombina com o abort() do handle; o primeiro a disparar vence
observebooleanforça a observação ligada
reportboolean | ReportOptionssobrescreve o ThenaConfig nesta execução
logLogConfigsobrescreve o ThenaConfig nesta execução

RunHandle

É PromiseLike, então await devolve o resultado. Sem await, você tem a execução.

MembroTipoObservações
runIdstringsíncrono, antes do primeiro turno
resultPromise<T>Promise comum — compõe com Promise.all
signalAbortSignalo seu combinado com o abort() deste handle
abort(reason?)voida reason chega no catch de quem chamou
onEvent(cb)() => voiddevolve como cancelar a assinatura
eventStreamAsyncIterable<ExecutionEvent>dá backpressure
onToken(cb)() => voiddevolve como cancelar a assinatura
textStreamAsyncIterable<string>
then / catch / finallydevolvem Promises comuns — encadear descarta o handle

Quem assina atrasado recebe o que já passou antes dos itens novos, num buffer de até 500 eventos.

Nada é emitido a menos que a execução seja observada

A observação liga com report, log, um plugin com onEvent, ou um observe: true explícito. Senão a execução segue o caminho de custo zero — sem árvore, sem eventos, sem streaming — e você recebe um aviso único no console.

Veja Streaming.

RunBudget

ts
budget: {
  maxDurationMs: 60_000,
  maxChatCalls: 20,
  maxToolCalls: 50,
  maxTokens: 100_000,
  maxCostUsd: 0.5,
  mode: "stop",
  onExceeded: (info) => console.warn(info.reason),
}
ChaveObservações
maxDurationMstempo de parede da execução inteira
maxChatCallschamadas ao modelo
maxToolCallsexecuções de tool
maxTokensprompt + completion, só o que o provider reporta
maxCostUsdexige costPer1kTokens no provider
mode"stop" (default) encerra graciosamente; "throw" lança BudgetExceededError
onExceededchamado uma única vez, quando o orçamento estoura
ts
interface BudgetUsage {
  chatCalls: number;
  toolCalls: number;
  tokens: number;
  costUsd: number;
  elapsedMs: number;
}

Leia no meio da execução com ctx.usage() ou ctx.budget.

O teto é uma barreira, não um corte no meio da frase

A parada é checada entre unidades de trabalho, e uma chamada ao modelo só é contabilizada depois de responder. A execução pode gastar mais uma chamada além do limite — e mais uma por nível de aninhamento quando uma tool dispara um sub-workflow. É um limite superior conhecido e constante.

Uma execução aninhada conta no orçamento do pai. Passe um budget explícito ao runtime.run() para dar a ela um teto próprio; corta quem estourar primeiro.

Relacionado