Aller au contenu
English

Créer votre propre boucle d’agent

Utilisez le harness intégré d’Outpost avec un fournisseur de modèle, des outils et des limites explicites.

Choisissez le harness intégré si vous voulez contrôler vous-même l’API du modèle, les outils et les règles d’exécution de l’agent. La boucle s’exécute dans votre processus Node.js, tandis que ses outils agissent dans la sandbox de la tâche.

Agent CLIHarness intégré
Où tourne la boucleDans la sandbox, comme processus de la CLIDans votre processus Node.js
OutilsCeux de la CLIUniquement ceux passés à tools
Accès au modèleConnexion de compte ou clé d’APIUne clé d’API sur un fournisseur de modèle
Image de la sandboxContient la CLI, ou l’installe au démarrageAucune CLI d’agent à installer
ContrôleRéglages de la CLIPermissions, hooks et limites par appel, et sous-agents
Remontée de la consommationDépend de la CLIAprès chaque réponse du modèle

Choisir un agent compare toutes les capacités.

createHarness() configure la boucle ; createAgent() l’associe à un modèle. L’agent passe ensuite à dispatch() comme n’importe quel autre.

import { createAnthropicModelProvider } from "@elie-laloum/outpost";

export const modelProvider = createAnthropicModelProvider({
  apiKey: process.env.ANTHROPIC_API_KEY ?? "",
});
import {
  createAgent,
  createHarness,
  createHarnessFileTools,
  createHarnessSearchTools,
} from "@elie-laloum/outpost";
import { modelProvider } from "./review-model.ts";

export const reviewer = createAgent({
  model: { name: "claude-sonnet-5-5", maxOutputTokens: 16_000 },
  harness: createHarness({
    modelProvider: modelProvider,
    instructions: "Inspect the repository and answer with evidence.",
    tools: [createHarnessFileTools(), createHarnessSearchTools()],
  }),
});
import { reportValue } from "./reporter.ts";
import { dispatch } from "@elie-laloum/outpost";
import { repository, sandboxProvider } from "./outpost.config.ts";
import { reviewer } from "./review-agent.ts";

export const result = await dispatch({
  repository,
  sandboxProvider,
  agent: reviewer,
  brief: { text: "List the exported functions that no test calls." },
});
reportValue(result.text);
// Example output: No test calls parseDate() or formatDate().
reportValue(result.usage);
// Example output: { input: 1200, cached: 0, output: 320 }

Définissez ANTHROPIC_API_KEY, puis lancez node harness-review.ts. result.text contient la réponse finale du modèle. Ces outils ne font que lire des fichiers : l’agent ne peut pas modifier le dépôt.

Glissez pour vous déplacer · Ctrl + molette pour zoomer
100 %
  • Ouvrir le tourUne fois par brief, passe ou réparation.
    1. Construire le prompt systèmeRésoudre instructions et le catalogue de compétences. hôte
    2. Démarrer les serveurs MCPLes mcpServers déclarés démarrent et ajoutent leurs outils. sandbox
    (Étapes)
    • → Exécuter une étape : puis
  • Exécuter une étapeRépétée jusqu’à ce que le modèle réponde sans appel d’outil.
    1. Interroger le modèleEnvoyer l’historique, le prompt système et la liste des outils. hôte
    2. Contrôler les appelsValider chaque entrée contre son schéma, puis appliquer les permissions et les hooks before-tool. hôte
    3. Exécuter les outilsLes appels consécutifs en lecture seule tournent en parallèle, les autres un par un. sandbox
    4. Renvoyer les résultatsRésultats et erreurs d’outils rejoignent l’historique pour l’étape suivante. hôte
    (Étapes)
    • → Terminer : puis
  • TerminerLe modèle répond.
    1. Rendre la réponseLe texte final devient result.text, sauf si un hook stop ou une nouvelle instruction envoyée pendant l’exécution relance le modèle. hôte
    (Étapes)

Outpost vérifie les limites avant chaque étape et après chaque réponse du modèle. La première atteinte termine le tour par une OutpostError.

limits borne la boucle ; toolExecution règle l’exécution des appels d’outils.

import {
  createAnthropicModelProvider,
  createHarness,
  createHarnessShellTools,
} from "@elie-laloum/outpost";

const harness = createHarness({
  modelProvider: createAnthropicModelProvider({
    apiKey: process.env.ANTHROPIC_API_KEY ?? "",
  }),
  tools: [createHarnessShellTools()],
  limits: { maxSteps: 30, maxToolCalls: 60, usage: { output: 20_000 } },
  toolExecution: { deadlineMs: 60_000, onError: "fail" },
});

Référence API : HarnessLimits et HarnessToolExecution.

Avec onError par défaut, un appel en échec ou expiré revient au modèle comme résultat d’erreur, et la boucle continue. usage compte les sous-agents et les résumés de contexte, et exige un fournisseur de modèle qui remonte une consommation complète.

deadlineMs et idleMs de dispatch() bornent aussi chaque tour du harness : sa durée totale et le silence entre deux événements de la boucle. Un appel d’outil en cours suspend le délai d’inactivité ; toolExecution.deadlineMs le borne à la place. Voir Limites et annulation.

Référence API : AgentObservation.

Suivez les appels d’outils et les requêtes au modèle pendant l’exécution du harness. Cet exemple active l’observation détaillée pour que la fonction de rappel puisse examiner la requête complète au modèle.

import { createAnthropicModelProvider } from "@elie-laloum/outpost";

export const observedModel = createAnthropicModelProvider({
  apiKey: process.env.ANTHROPIC_API_KEY ?? "",
});
import {
  createAgent,
  createHarness,
  createHarnessFileTools,
} from "@elie-laloum/outpost";
import { observedModel } from "./observed-model.ts";

export const agent = createAgent({
  model: { name: "claude-sonnet-5-5", maxOutputTokens: 16_000 },
  harness: createHarness({
    modelProvider: observedModel,
    tools: [createHarnessFileTools()],
  }),
});
import { reportValue } from "./reporter.ts";
import { dispatch, createObservationHub } from "@elie-laloum/outpost";
import { repository, sandboxProvider } from "./outpost.config.ts";
import { agent } from "./observed-agent.ts";

await dispatch({
  repository,
  sandboxProvider,
  agent,
  brief: { text: "Explain how the build is configured." },
  observation: createObservationHub({ verbose: true }),
  observe(event) {
    if (event.kind === "tool") reportValue(event.name, event.input);
    // Example output: read_file { path: "README.md" }
    if (event.kind === "model-request") console.dir(event.request);
  },
});

tool-output diffuse la sortie des commandes, rattachée à son appel par callId. Les contenus complets de model-request et model-response n’existent qu’avec un hub d’observation détaillé. Ils contiennent toute la conversation, et le journal normal les écarte.

  • L’accès au modèle exige une clé d’API, ou un serveur local sans clé. Les connexions de compte des CLI ne s’appliquent pas.
  • Le code des outils s’exécute dans votre processus, avec vos droits. Seul ce qu’il fait via context.sandbox s’exécute dans la sandbox.
  • Les requêtes au modèle partent de votre processus : les restrictions réseau de la sandbox ne s’y appliquent pas.

API : createHarness · HarnessOptions · HarnessLimits · HarnessToolExecution · createAgent · createObservationHub.

Ajoutez une déclaration routing facultative pour choisir parmi les modèles du provider de ce harness après compaction et avant les hooks du modèle. Outils et hooks voient le modèle sélectionné tandis que la sandbox et l’historique restent disponibles. Consultez le routage de modèles pour la validation des candidats, l’état, le repli et l’usage.