Pular para o conteúdo
astorlm
Idioma: Português
← Mapa

Nível 13

Humano no loop

O agente faz o trabalho; uma pessoa fica com a palavra final. Ela aprova o que não dá para desfazer, corrige no meio do caminho e responde quando ele está em dúvida.
1/33 Dobras do bandoneón:
  • user
  • assistant
  • tool_result
  • tool_result (erro)
Uma máquina de pegar bichinhos no fliperama. O Oráculo fica na cabine da cartomante, Astor opera os controles e Tina, a pessoa no loop, assiste pelo vidro. Resta uma ficha.

EventBus

O problema

Um agente que roda sem uma pessoa é rápido até o momento em que faz algo que ninguém queria: paga a fatura errada, manda e-mail para todos os clientes, gasta a última ficha no prêmio errado. E um agente que para para perguntar sobre tudo não é mais rápido do que fazer você mesmo.

Esse é o Autopilot Rex: nunca pergunta, nunca espera, nunca atende um chamado. Ele se agarra ao primeiro plano, ignora o que mudou desde então e chuta quando deveria ter perguntado.

A solução

Coloque uma pessoa nos poucos pontos em que o julgamento dela importa, e deixe o agente rodar em todos os outros. São três pontos, e eles se diferenciam por quem quebra o silêncio:

  • Aprovar

    O agente espera

    Antes de uma ferramenta irreversível rodar, um hook mostra à pessoa exatamente o que ela vai fazer e espera um sim ou um não.

    Pagamentos, exclusões, mensagens a clientes, a última ficha: qualquer coisa que não dá para desfazer.

  • Corrigir o rumo

    A pessoa interrompe

    A pessoa coloca uma correção na fila quando quiser. Na próxima chamada de ferramenta, o loop cancela essa chamada e entrega a correção ao modelo no lugar.

    Alguém está olhando e muda de ideia, ou vê o agente indo na direção errada.

  • Escalar

    O agente pergunta

    Uma ferramenta como ask_human que só retorna quando uma pessoa responde. O modelo decide quando usá-la.

    Falta informação, duas opções igualmente boas, pouca confiança. O system prompt diz quando perguntar.

Aprovar e corrigir o rumo vivem no hook beforeToolExecution do nível 6: ele roda antes de toda ferramenta, e pode esperar. Numa aprovação, ele espera a resposta da pessoa; numa correção de rumo, confere se há uma correção na fila. Nos dois casos, o que a pessoa disse volta para o modelo como resultado da ferramenta, então a execução segue com a informação nova em vez de quebrar.

O elenco

O mesmo elenco de sempre, desta vez no fliperama.

A cartomante o modelo
O Oráculo, na cabine. Lê o histórico e decide a próxima chamada. Nunca encosta na máquina.
Os controles as ferramentas
move_claw é de graça e pode ser desfeito. drop_claw gasta a última ficha: não pode.
Tina a pessoa
O balão dela diz quem falou primeiro: ! ela interrompeu, ? perguntaram a ela, YES! ela aprovou.
A tela a aprovação
DROP? YES NO: a garra fica parada enquanto o hook espera. Nada roda até ela decidir.

No painel EventBus, a correção de rumo aparece como um evento user_steering, seguido do resultado da chamada cancelada. Aprovações e respostas não têm evento próprio: são um hook e uma ferramenta que levaram o seu tempo.

O código

Com astorlm: Um hook de aprovação para as ferramentas irreversíveis, embrulhado pelo createSteeringController, que adiciona a fila de correções: chame steer(text) a partir da sua interface e ela chega na próxima chamada de ferramenta. Escalar é uma ferramenta comum que espera pela sua interface.

Do zero: Três checagens na etapa de ferramentas do loop do nível 2: uma correção na fila, uma aprovação para as ferramentas arriscadas e uma ferramenta que espera por uma pessoa.

import { OpenAIProvider, createLocalAgent, createSteeringController, tool } from 'astorlm'
import { z } from 'zod'

// Any OpenAI-compatible endpoint: OpenAI, Ollama, LM Studio, vLLM, a proxy…
const LLM = { baseURL: 'http://localhost:11434/v1', apiKey: 'YOUR_API_KEY' } // local servers usually ignore the key

// Your UI: each of these resolves when the person clicks or types.
declare function approve(what: string): Promise<boolean> // shows YES / NO
declare function answer(question: string): Promise<string> // shows a text box

// 1. ESCALATE: a tool the model calls when it isn't sure. It waits for a person.
const askKid = tool({
  name: 'ask_kid',
  description: 'Ask Tina when you are not sure what she wants. Waits for her answer.',
  schema: z.object({ question: z.string() }),
  execute: async ({ question }) => answer(question),
})

// 2. APPROVE: irreversible tools wait for a yes before they run.
const NEEDS_APPROVAL = new Set(['drop_claw'])
const steering = createSteeringController({
  beforeToolExecution: async ({ toolName, input }) => {
    if (!NEEDS_APPROVAL.has(toolName)) return { authorize: true }
    const ok = await approve(`${toolName}(${JSON.stringify(input)})`) // show the real call
    return ok ? { authorize: true } : { authorize: false, mockResult: 'Tina said no. Ask her what to do.' }
  },
})

const agent = await createLocalAgent({
  provider: new OpenAIProvider({ ...LLM, model: 'your-model' }), // e.g. 'llama3.1', 'gpt-4o-mini'
  systemPrompt: 'You work a claw machine for Tina. If you are not sure which prize she means, ask her before acting.',
  tools: [moveClaw, dropClaw, askKid], // moveClaw, dropClaw: your code
  hooks: steering.hooks, // the steering controller wraps the approval hook
  maxTurns: 20,
})

// 3. STEER: the person can correct the agent at any moment, e.g. from a button.
// The loop cancels the next tool call and hands the model this feedback instead.
onTinaShouts((text) => steering.steer(text)) // your UI: 'No, wait! The penguin!'

const result = await agent.run('Get me the bear!')
console.log(result.content)

O que observar

  • Peça menos, e o pedido vale mais. Aprove só o que é irreversível ou caro. Uma pessoa que clica em YES vinte vezes por hora para de ler, e a aprovação vira formalidade.
  • Mostre a chamada real. “Descer?” não basta. Mostre a ferramenta e os argumentos exatos, o valor, o destinatário, o prêmio, para a pessoa aprovar o que de fato vai rodar.
  • Decida o que acontece quando ninguém responde. Uma pessoa pode ir embora. Defina um timeout e escolha o padrão seguro: geralmente negar, e dizer ao modelo por quê.
  • As correções chegam na próxima chamada de ferramenta. A correção de rumo não consegue parar uma ferramenta no meio nem uma resposta no meio de uma palavra. Se o agente só está escrevendo texto, a correção espera. Para uma parada brusca, aborte a execução.
  • Mantenha um registro. Registre quem aprovou o quê, quando e o que viu. Quando algo dá errado, “foi o agente” nunca é a história toda.