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.
Sur cette page
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.
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.
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 :
{"operation":"operation.describe","params":{},"query":{"operation":"roadmap-planning.bulk-replace"}}Un agent externe peut lire le même contrat déployé via la CLI :
bernops --json app operation describe --project "$PROJECT_ID" \
--query operation=roadmap-planning.bulk-replaceL'é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 :
paramsest 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: falsesignifie omettrebody, 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.querycontient 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înessort_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 :
{"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.
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 :
{
"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 :
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
- 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.
- Découvrez seulement les contrats utiles à la tâche. Utilisez des lectures ciblées autorisées et suivez chaque page/curseur pertinent.
- 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.
- 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.
- 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. Pour les frontières d'identité et de capacité, consultez Clés API et scopes.