Aller au contenu
astorlm
Langue: Français
← Carte

Niveau 13

L'humain dans la boucle

L'agent fait le travail ; une personne garde le dernier mot. Elle approuve ce qui ne peut pas être défait, le corrige en cours de route, et répond quand il hésite.
1/33 Plis du bandonéon :
  • user
  • assistant
  • tool_result
  • tool_result (erreur)
Une machine à pince dans une salle d'arcade. L'Oracle est dans la cabine de la voyante, Astor manie les commandes, et Tina, la personne dans la boucle, regarde à travers la vitre. Il reste une pièce.

EventBus

Le problème

Un agent qui tourne sans personne est rapide, jusqu'au moment où il fait quelque chose que personne ne voulait : payer la mauvaise facture, envoyer un e-mail à tous les clients, dépenser la dernière pièce pour le mauvais lot. Et un agent qui s'arrête pour tout demander n'est pas plus rapide que de le faire vous-même.

C'est Autopilot Rex : il ne demande jamais, n'attend jamais, ne prend jamais d'appel. Il s'accroche à son premier plan, ignore ce qui a changé depuis et devine là où il aurait dû demander.

La solution

Placez une personne aux quelques endroits où son jugement compte, et laissez l'agent tourner partout ailleurs. Il y a trois de ces endroits, et ils diffèrent par qui rompt le silence :

  • Approuver

    L'agent attend

    Avant qu'un outil irréversible ne s'exécute, un hook montre à la personne exactement ce qu'il va faire et attend un oui ou un non.

    Paiements, suppressions, messages aux clients, la dernière pièce : tout ce qu'on ne peut pas reprendre.

  • Réorienter

    La personne interrompt

    La personne met une correction en file quand elle veut. Au prochain appel d'outil, la boucle annule cet appel et donne la correction au modèle à la place.

    Quelqu'un regarde et change d'avis, ou voit l'agent partir dans la mauvaise direction.

  • Faire remonter

    L'agent demande

    Un outil comme ask_human qui ne rend pas la main tant qu'une personne n'a pas répondu. Le modèle décide quand l'utiliser.

    Une information manque, deux options se valent, peu de confiance. Le system prompt dit quand demander.

Approuver et réorienter vivent tous deux dans le hook beforeToolExecution du niveau 6 : il s'exécute avant chaque outil, et il peut attendre. Pour une approbation, il attend la réponse de la personne ; pour une réorientation, il vérifie si une correction est en file. Dans les deux cas, ce qu'a dit la personne revient au modèle comme résultat de l'outil, donc l'exécution continue avec la nouvelle information au lieu de planter.

Les personnages

Les mêmes personnages que d'habitude, cette fois dans une salle d'arcade.

La voyante le modèle
L'Oracle, dans sa cabine. Il lit l'historique et décide de l'appel suivant. Il ne touche jamais la machine.
Les commandes les outils
move_claw est gratuit et peut être annulé. drop_claw dépense la dernière pièce : lui, non.
Tina la personne
Sa bulle dit qui a parlé en premier : ! elle a interrompu, ? on lui a demandé, YES! elle a approuvé.
L'écran l'approbation
DROP? YES NO : la pince reste immobile pendant que le hook attend. Rien ne s'exécute tant qu'elle n'a pas décidé.

Dans le panneau EventBus, la réorientation apparaît comme un événement user_steering, suivi du résultat de l'appel annulé. Les approbations et les réponses n'ont pas d'événement à elles : ce sont un hook et un outil qui ont pris leur temps.

Le code

Avec astorlm : Un hook d'approbation pour les outils irréversibles, enveloppé par createSteeringController, qui ajoute la file de corrections : appelez steer(text) depuis votre interface, et elle arrive au prochain appel d'outil. Faire remonter, c'est un outil ordinaire qui attend votre interface.

À partir de zéro : Trois vérifications dans l'étape outils de la boucle du niveau 2 : une correction en file, une approbation pour les outils risqués, et un outil qui attend une personne.

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)

Points de vigilance

  • Demandez moins, et ça compte plus. N'approuvez que l'irréversible ou le coûteux. Une personne qui clique sur YES vingt fois par heure arrête de lire, et l'approbation devient une formalité.
  • Montrez le vrai appel. « Descendre ? » ne suffit pas. Montrez l'outil et ses arguments exacts, le montant, le destinataire, le lot, pour que la personne approuve ce qui va réellement s'exécuter.
  • Décidez de ce qui se passe quand personne ne répond. Une personne peut s'éloigner. Fixez un timeout, et choisissez la valeur par défaut sûre : en général refuser, et dire au modèle pourquoi.
  • Les corrections arrivent au prochain appel d'outil. La réorientation ne peut pas arrêter un outil en pleine exécution ni une réponse au milieu d'un mot. Si l'agent ne fait qu'écrire du texte, la correction attend. Pour un arrêt net, interrompez l'exécution.
  • Gardez une trace. Journalisez qui a approuvé quoi, quand, et ce qu'il a vu. Quand quelque chose tourne mal, « c'est l'agent qui l'a fait » n'est jamais toute l'histoire.