# Utilisation efficace des outils agent

Découvrez les contrats, utilisez les lectures compactes, prévisualisez la planification atomique et vérifiez préparation et usage.

Utilisez les outils BernOps pour découvrir les contrats exacts, sélectionner les enregistrements utiles, planifier par lots et vérifier le résultat sans recharger de longues descriptions ni deviner les champs de mutation. L'efficacité ne supprime ni les permissions projet, ni la propriété d'une réclamation, ni l'approbation humaine, ni les contrôles de concurrence.

**Compatibilité des versions et du déploiement**

Ce guide décrit les changements de `feat/agent-tool-efficiency` ; il n'annonce ni leur déploiement en production ni leur disponibilité dans chaque client installé. Consultez `bernops app --help` et les descriptions d'opérations du backend déployé. Les anciens hôtes peuvent ne pas exposer les nouvelles opérations et les anciens backends peuvent les refuser. Conservez les appels pris en charge au lieu de deviner les paramètres, de mettre à niveau ou de vous authentifier automatiquement. La distribution de la CLI reste privée.


## Choisir le transport

| Interface | Authentification et usage | Réponses compactes |
| --- | --- | --- |
| `bernops_app` dans une session BernOps personnelle | L'hôte déduit le projet et l'acteur ; utilisez les outils de tableau, wiki et roadmap autorisés pour cette session. | Les opérations compatibles acceptent `query.response_view: "compact-v1"`. |
| `bernops app` pour un agent externe | Une clé API projet provisionnée séparément avec les scopes requis, pas les identifiants OAuth utilisateur ou fournisseur. | Réponses REST directes ; ne fournissez pas `response_view`. |
| Recherche/lecture des docs publiques | Sans connexion, clé, fournisseur ou composant agent installé. | Lecture de sections publiques, pas accès aux données privées du projet. |

Pour les appels CLI app, utilisez la variable d'environnement approuvée `BERNOPS_API_KEY` ou `--api-key-stdin` ; ne mettez jamais une clé dans les arguments de commande ou la documentation. Les commandes app ciblent le cloud par défaut. N'utilisez `--target local` que pour un environnement local explicitement voulu. Consultez [Clés API et scopes](/fr/docs/api-keys-scopes).

## Découvrir les opérations exactes avant de les appeler

Avec les outils gérés compatibles, décrivez l'opération utile au lieu de parcourir les sources ou de tester des mutations devinées :

```json
{"operation":"operation.describe","params":{},"query":{"operation":"roadmap-planning.bulk-replace"}}
```

Un agent externe peut lire le même contrat déployé via la CLI :

```bash
bernops --json app operation describe --project "$PROJECT_ID" \
  --query operation=roadmap-planning.bulk-replace
```

L'équivalent REST authentifié est `GET /api/projects/{projectId}/app-control/operations?operation=roadmap-planning.bulk-replace`. L'accès au projet est requis. La découverte ne demande pas de scope de domaine supplémentaire, mais l'exécution de l'opération décrite exige toujours les scopes et permissions annoncés.

Pour lister les noms, omettez `query.operation`. L'index renvoie 20 noms par défaut, au maximum 50 par page. Tant que `has_more` vaut vrai, passez le `next_cursor` reçu dans `query.after`. Décrivez ensuite un nom sélectionné séparément ; ne combinez pas `operation` et pagination de l'index.

Lisez `params`, `query_keys`, `body_allowed`, `body_fields`, `body_required`, `semantics`, `permissions`, `concurrency`, `pagination` et `compact_view_supported`. En particulier :

- `params` est obligatoire, même vide `{}`. Les UUID et paramètres numériques de chemin sont des chaînes. Ne fournissez pas de substitution d'identité projet/acteur.
- `body_allowed: false` signifie omettre `body`, pas fournir null ou un objet vide. Lisez aussi les règles conditionnelles : un jalon exige soit une date ponctuelle, soit les deux bornes d'une période.
- `query` contient des scalaires non vides ou des tableaux de scalaires, pas des objets imbriqués. Les curseurs roadmap sont des chaînes JSON encodées ; ceux des statuts du tableau sont des chaînes `sort_key:UUID`.
- Les exemples contiennent des identifiants et préconditions synthétiques. Remplacez-les par des enregistrements actuels ; la découverte n'accorde ni bail, ni approbation, ni droits administrateur ou d'exécution. Les opérations binaires sont hors de ce catalogue JSON.

La révision des docs publiques peut différer du backend actif. Utilisez la description déployée pour les champs pris en charge ; une correspondance partielle de recherche ne prouve pas qu'une opération exacte existe.

## Utiliser les lectures compactes pour sélectionner, pas implémenter

Un dispatcher personnel compatible accepte cette lecture ciblée du tableau :

```json
{"operation":"work-item.list","params":{},"query":{"status":"todo","limit":14,"response_view":"compact-v1"}}
```

Vérifiez `compact_view_supported` dans la découverte avant d'ajouter l'option. Les familles compatibles comprennent les sélections et reçus ordinaires de tableau/libellés, les réclamations, les snapshots/candidats roadmap et reçus ordinaires de planification, ainsi que les résumés des listes de pages wiki. Omettez l'option, ou utilisez `"full"` sur une opération compatible, pour conserver la réponse complète existante.

Les réponses compactes omettent les descriptions de ressources avec `description_omitted: true` et le doublon `event.post_state` avec `post_state_omitted: true`. Elles conservent identifiants, noms, dates, révisions, ETags de ressources, identifiants de bail, identités de mutation/événement, résultats, indicateurs de rejeu, `event.changes`, avertissements et indicateurs de pagination/complétude des dépendances. Une omission ne signifie ni description vide ni retour de toutes les dépendances. Les limites de taille existantes s'appliquent avant projection : filtrez, réduisez les limites et paginez plutôt que de compter sur le mode compact pour sauver une réponse trop volumineuse.

Les lectures canoniques `work-item.get`, `work-item.get-by-number`, `work-item.events`, le contenu/historique wiki et les opérations d'approbation à fort impact restent uniquement complètes. Ne leur envoyez pas `response_view`. Lisez toujours l'élément complet et ses critères d'acceptation avant de réclamer ou implémenter ; lisez le contenu wiki complet actuel avant modification.

**Le mode compact est une option de l'outil géré**

N'ajoutez pas `response_view` aux listes REST directes ou `bernops app`. Si un ancien backend refuse l'option sur une lecture, utilisez la lecture complète prise en charge. Ne rejouez jamais une mutation au résultat incertain simplement pour changer son format de réponse.


## Séparer ETags de ressources, curseurs et baux

Une ressource compacte peut renvoyer un `etag` comme `"7"`. Passez exactement ce jeton entre guillemets dans `if_match`, sans ajouter une couche de guillemets. Un curseur de snapshot ou d'événement n'est pas l'ETag d'une ressource.

Pour une mutation d'élément par CLI/REST externe, suivez `concurrency.etag_read_operation` et `etag_response_header` : lisez le `work-item.get` canonique et utilisez son en-tête de réponse `ETag`. Le détail REST direct est l'élément lui-même ; un reçu de commande peut l'envelopper dans `item`. Les collections par défaut et reçus de mutation ordinaires ne garantissent pas d'en-têtes ETag.

Les jetons de tête wiki sont propres à la page, par exemple `"wiki-page:<page UUID>:rev:7"`, et non `"7"`. Une liste compacte `wiki-page.list` peut les fournir, mais les révisions historiques ne sont pas des préconditions d'écriture de la tête actuelle. Libellés, réclamations et pièces jointes n'ont pas leur propre jeton de révision de ressource.

Les réclamations exigent leur jeton de bail privé et leur génération reçus, pas un ETag. Les mutations de bail prennent `generation` comme entier JSON même si les réponses l'encodent en chaîne décimale. `ttl_seconds` est un entier JSON entre 60 et 3600. `claim.next` sélectionne **et réclame** le travail : c'est une mutation, pas un raccourci de consultation.

Pour un résultat de transport ambigu, conservez la clé d'idempotence logique, l'UUID de mutation, le corps et les préconditions. Une nouvelle invocation CLI génère un nouvel UUID sauf si vous conservez explicitement `--mutation-id`. Les refus 403, 409, 412 ou 428 demandent inspection et réconciliation, pas des tentatives aveugles ou des ETags rafraîchis sous la même écriture logique. Une proposition délibérément révisée est une nouvelle mutation logique.

## Prévisualiser et appliquer une planification atomique par lot

Utilisez `roadmap-planning.bulk-replace` pour remplacer la planification de **1 à 50 éléments uniques** d'un projet. Son corps contient exactement `dry_run` et `items`. Chaque entrée doit fournir l'ID de l'élément, son `if_match` actuel entre guillemets et **les quatre** champs de planification pouvant être null. Null efface un champ ; l'omettre ne le préserve pas. C'est un remplacement complet, pas un patch.

Remplacez les identifiants fictifs et l'ETag illustratif ci-dessous par les valeurs actuelles avant de demander une prévisualisation :

```json
{
  "operation": "roadmap-planning.bulk-replace",
  "params": {},
  "body": {
    "dry_run": true,
    "items": [{
      "work_item_id": "<existing item UUID>",
      "if_match": "\"7\"",
      "roadmap_id": "<existing roadmap UUID>",
      "roadmap_goal_id": null,
      "planned_start_on": "2026-11-02",
      "planned_end_on": "2026-11-03"
    }]
  }
}
```

Les dates sont des paires inclusives `YYYY-MM-DD`, toutes deux null ou valides avec début antérieur ou égal à la fin. Sans roadmap, les autres champs doivent tous être null. Un objectif sélectionné doit appartenir à cette roadmap ; les dates ne doivent pas obligatoirement tenir dans sa fenêtre. Toute réclamation active bloque le lot, même détenue par l'appelant. Aucun contournement par bail n'existe. Les dates finales des dépendances impliquant les éléments réellement modifiés doivent placer la fin du prédécesseur strictement avant le début du successeur.

La prévisualisation exécute la validation dans une transaction annulée. Elle n'enregistre ni révision, ni événement, ni entrée d'idempotence et ne réserve rien ; elle renvoie `expected_revision` / `expected_etag` et les valeurs proposées, pas des révisions validées simulées. L'application utilise `dry_run: false`, une autre clé d'idempotence logique et revalide tous les éléments. Un élément invalide annule tout le lot. Les reçus de lot sont déjà compacts ; **n'envoyez pas `response_view`**.

La CLI externe accepte les mêmes fichiers de corps. Provisionnez séparément le scope `work_items:write` requis. Générez et conservez un UUID/une clé distincts pour la prévisualisation et l'application ; les variables suivantes doivent déjà contenir ces valeurs :

```bash
bernops --json app roadmap-planning bulk-replace --project "$PROJECT_ID" \
  --json-file plan-preview.json \
  --idempotency-key "$PREVIEW_KEY" --mutation-id "$PREVIEW_MUTATION_ID"

bernops --json app roadmap-planning bulk-replace --project "$PROJECT_ID" \
  --json-file plan-apply.json \
  --idempotency-key "$APPLY_KEY" --mutation-id "$APPLY_MUTATION_ID"
```

`plan-preview.json` contient seulement le corps ci-dessus ; `plan-apply.json` contient les remplacements examinés avec `dry_run: false`. Conservez exactement le fichier, la clé et l'UUID d'application pour réconcilier un résultat ambigu. Le rejeu exact renvoie le reçu historique original sans réappliquer ; relisez un snapshot pour l'état actuel.

Une séquence efficace est **snapshot/candidats → prévisualisation → application → snapshot de vérification**. Cela représente quatre appels du domaine de planification seulement si les enregistrements tiennent dans les lectures et si les préconditions actuelles sont déjà disponibles. Comptez séparément découverte, pages supplémentaires et lectures canoniques d'ETag/détail. Ce n'est ni une promesse de quatre appels totaux à froid, ni de factures fournisseur réduites, ni une autorisation d'implémenter le travail sélectionné.

## Vérifier la préparation, pas seulement les liens

Sur les déploiements compatibles, `roadmap.snapshot` inclut le résumé faisant autorité `readiness` en mode complet et compact. Il couvre tout le travail lié non archivé, pas seulement les pages chargées ou les barres localement visibles. Lisez ensemble la fenêtre effective, le travail planifié/non planifié, le travail inachevé et les avertissements de dépendance. L'historique terminé sans dates ne doit pas être traité comme une livraison future à dater.

Si une timeline n'a aucune barre, vérifiez le résumé serveur, les dates, la fenêtre du snapshot, l'historique terminé, les filtres/groupes repliés locaux et la pagination. `outside_window_count` signifie travail daté hors fenêtre, pas dates absentes. Un compte de barres visibles/chargées n'est pas un total serveur.

Pour du travail inachevé lié mais sans dates, `zero_visible_work`, `zero_window_work`, `unscheduled_work` et `propose_dates_or_confirm_intentional_unscheduling` distinguent un simple rattachement d'un plan de livraison daté. Proposez des dates à examiner ou expliquez explicitement l'absence volontaire de planification ; ne déclarez pas un plan daté terminé uniquement parce que les éléments sont liés.

Les reçus de lot incluent le résumé de préparation une fois par ancienne/nouvelle roadmap concernée après l'ensemble du lot. `readiness_state` distingue `proposed_final_batch` et `committed_final_batch` ; un rejeu est historique. Après une mutation ordinaire de planification, ou si l'état actuel compte, relisez le snapshot. Les avertissements n'attribuent pas de dates, ne déplacent pas les successeurs et n'accordent aucun droit d'exécution ou de mutation.

## Interpréter l'attribution sans inventer la facturation

Sur les déploiements compatibles, la boîte d'usage d'une session montre l'attribution par requête/tour/outil, le parent et les enfants délégués, les données absentes et les lacunes de collecte. Actualiser repart de la première page, la navigation suivante remplace la page et l'export JSON contient **uniquement la page validée courante**, pas un total de session.

- Les compteurs modèle d'entrée/sortie/cache/contexte restent distincts ; des catégories fournisseur peuvent se recouper. N'additionnez pas toutes les catégories affichées.
- Le coût de catalogue SDK est une estimation, pas une facture fournisseur. L'estimation des tokens de texte d'outil utilise `ceil(octets UTF-8 / 4)` : une approximation du texte nouvellement introduit, pas du retraitement de l'historique ni des tokens modèle facturés.
- Un usage absent reste indisponible, pas nul. L'absence de ligne ou une lacune de collecte ne prouve pas l'absence de coût. Les totaux agrégés existants ne sont pas augmentés par l'ajout des lignes d'attribution.
- Le collecteur stocke des identités bornées, compteurs et catégories fermées d'outil/opération, pas les prompts, arguments, textes d'outil, chemins de fichier, identifiants secrets ou payloads fournisseur bruts. L'usage délégué est distinct du résultat Task du parent.

L'endpoint privé `GET /api/agent-sessions/{sessionId}/usage-attribution` exige le créateur de session et l'accès actuel au projet. Il est paginé avec au maximum 100 lignes par page et utilise `Cache-Control: no-store` ; ce n'est ni un fichier des docs publiques ni un endpoint de découverte par clé projet.

## Un parcours efficace en pratique

1. Recherchez les docs publiques, puis récupérez l'ID de section réel dans la même langue. La révision publique est une référence, pas une preuve de prise en charge déployée.
2. Découvrez seulement les contrats utiles à la tâche. Utilisez des lectures ciblées autorisées et suivez chaque page/curseur pertinent.
3. Utilisez les sélections/snapshots compacts gérés si disponibles ; lisez le détail canonique avant de réclamer, implémenter ou modifier du contenu.
4. Conservez ETags de ressources, baux privés et identités d'idempotence. Prévisualisez uniquement les lots entrant dans le périmètre de planification autorisé par l'utilisateur.
5. Appliquez une fois les changements examinés, puis vérifiez un snapshot frais, la préparation et les conflits. Consignez limites, absence volontaire de dates et accès non résolus au lieu de masquer des appels supplémentaires ou d'annoncer des économies non mesurées.

Pour l'installation et les commandes disponibles, consultez [CLI d'agent de code](/fr/docs/coding-agent-cli). Pour les frontières d'identité et de capacité, consultez [Clés API et scopes](/fr/docs/api-keys-scopes).
