Écrire un outil personnalisé sous forme de module WebAssembly
Ce guide montre comment donner à l'agent un outil qui s'exécute comme module WebAssembly à l'intérieur de mm, dans un bac à sable : le module ne voit aucun fichier, aucune variable d'environnement et aucun réseau, sauf les dossiers du projet que vous lui ouvrez. Utilisez-le à la place d'un outil commande quand l'outil ne doit pas avoir vos droits — il lit un dossier, ou calcule quelque chose à partir de ses seuls arguments. Il suppose que TinyGo est installé et que vous avez un fichier d'agent YAML.
Étapes
-
Écrivez l'outil comme un programme Go ordinaire. Il lit les arguments de l'appel en un seul objet JSON sur stdin, et ce qu'il écrit sur stdout ou stderr est ce que le modèle reçoit ; sortir avec un code non nul marque l'appel comme échoué :
// tools-src/search_notes/main.go package main import ( "encoding/json" "fmt" "os" "path" "strings" ) func main() { var in struct { Word string `json:"word"` } if err := json.NewDecoder(os.Stdin).Decode(&in); err != nil { fmt.Fprintln(os.Stderr, "bad input:", err) os.Exit(2) } entries, _ := os.ReadDir("notes") for _, e := range entries { data, _ := os.ReadFile(path.Join("notes", e.Name())) for i, line := range strings.Split(string(data), "\n") { if strings.Contains(strings.ToLower(line), strings.ToLower(in.Word)) { fmt.Printf("%s:%d: %s\n", e.Name(), i+1, line) } } } } -
Compilez-le en module WASI :
tinygo build -o tools/search_notes.wasm -target=wasip1 -no-debug ./tools-src/search_notes -
Déclarez-le dans le fichier d'agent avec
wasm:à la place decommand:, et ouvrez les dossiers dont il a besoin —read:en lecture seule,write:en lecture-écriture :tools: - name: search_notes description: Find the lines of the notes that mention a word. parameters: word: { type: string, description: "One word, e.g. wazero" } wasm: ./tools/search_notes.wasm read: [notes]Le chemin du module est relatif au fichier d'agent ; les dossiers sont relatifs au répertoire de travail, et le module les ouvre sous le même nom (
notes/…). -
Demandez-le avec vos propres mots, depuis le répertoire du projet :
mm -p "Which notes mention TinyGo?"Le terminal affiche le module et le JSON qu'il a reçu, puis sa sortie :
🧰 search_notes: search_notes.wasm {"word":"TinyGo"} │ tinygo.md:1: # TinyGo │ wazero.md:4: It runs WASI modules, such as the ones TinyGo builds with -target=wasip1.
Variantes
- Un outil qui écrit.
write: [out]lui permet de créer et de modifier des fichiers dansout/seulement. Un dossier qu'il peut seulement lire va dansread:; un dossier absent des deux listes n'existe pas pour lui. - Un calcul pur. Omettez
readetwrite: le module ne voit alors aucun fichier. - Les chemins dans le module. Nettoyez-les avant d'ouvrir : la couche WASI de TinyGo refuse
./notes/a.mdet..—path.Join("notes", name)donnenotes/a.md. Un nom comme../agent.yamldevient alorsagent.yaml, qui n'est pas monté : le bac à sable le tient à l'écart. - Paramètres typés, valeurs par défaut. Le JSON contient chaque valeur dans son type déclaré (
"top": 5,"exact": true), ledefaultd'un paramètre optionnel que l'appel a omis, et aucune clé pour un paramètre optionnel sans valeur par défaut. - Un calcul long. Ajoutez
timeout: 2m; au-delà, le module est arrêté. Sans lui,bashTimeouts'applique. - Demander avant chaque appel.
yolo: falsedemande pour un outil wasm comme pour un outil commande. - Un autre langage. Tout module commande WASI preview 1 devrait s'exécuter de la même façon ; seuls des modules TinyGo ont été essayés.
Voir aussi
- Un exemple complet avec quatre modules, un dossier en lecture et un dossier en écriture :
demos/wasm-tools/ - Chaque clé et chaque erreur : référence de la configuration et outils déclarés
- Ce que le bac à sable permet et ce qu'il coûte : Outils déclarés
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
|