Kanso Documentation

Agents et API

Deux portes, parce qu'un agent et un service ne sont pas le même visiteur.

Un agent est une personne devant un ordinateur : il agit en son nom et a besoin de son consentement. Un service, non. Kanso leur donne des portes différentes plutôt qu'une porte unique accompagnée d'une note sur la façon de s'en servir.

Quelle porte

Un agent entre par /api/mcp : il s'enregistre lui-même, vous l'approuvez dans votre navigateur, et il détient un jeton qui ouvre ce seul point d'entrée et rien d'autre. Un service entre par l'API REST avec un jeton que vous avez émis pour lui, qui donne toute l'API et porte votre rôle. Le premier sert à quelque chose qui agit comme vous ; le second à quelque chose qui agit pour son compte, et la différence mérite d'être tenue.

La porte MCP

Une commande, lancée là où vit l'agent :

claude mcp add --transport http kanso http://localhost:8080/api/mcp

Rien n'est collé. La commande ne fait qu'écrire une adresse. Au premier appel, Kanso répond 401 avec un en-tête nommant son propre serveur d'autorisation, et l'agent s'enregistre, ouvre votre navigateur et demande.

Ce que vous lisez là est une page Kanso, sur l'origine de Kanso : quelle application demande, où elle enverrait le code, quel âge a son enregistrement, et les permissions en phrases plutôt qu'en noms de scopes. Approuvez, et l'agent détient un jeton.

Ce jeton ouvre une porte et pas le reste de l'API — il est accepté sur /api/mcp et refusé partout ailleurs — et ce qui passe par là agit comme vous : chaque changement porte votre nom dans le fil d'activité.

Réglages → Agents liste ce que vous avez laissé entrer et le révoque. Révoquer emporte les jetons avec la permission : c'est la requête suivante qui est refusée, pas l'heure suivante.

Connectez-vous d'abord à Kanso dans ce navigateur. L'URL d'autorisation répond 401 avec un corps vide à un navigateur sans session : le lien de l'agent s'ouvre donc sur une page blanche plutôt que sur un écran de connexion. C'est la dernière aspérité de ce flux, et elle est écrite ici plutôt que masquée — se connecter d'abord la rend invisible.

Dix outils passent par là

Trois lisent, cinq écrivent, et deux forment la paire de tri — celle pour laquelle un agent est réellement doué.

kanso_list_tickets
Les tickets correspondant à un périmètre et à un filtre.
kanso_get_ticket
Un ticket complet, par identifiant.
kanso_team_workload
Ce que porte chaque membre d'une équipe, du plus chargé au moins : tickets ouverts, combien sont en cours, les points que quelqu'un a estimés, combien ne portent aucune estimation, et l'âge de leur plus vieux ticket ouvert.
kanso_create_ticket
Saisir un ticket.
kanso_update_ticket
En modifier un, par identifiant.
kanso_split_ticket
Transformer un ticket existant en parent et déposer dessous les parties que vous nommez, en un seul appel. Renvoie les identifiants donnés aux parties.
kanso_link_tickets
Enregistrer une arête entre deux tickets existants. from et to se lisent comme une phrase : from bloque to, duplique to, est lié à to.
kanso_plan
Déposer un plan entier déjà élaboré — plusieurs tickets, lesquels sont des parties de lesquels, et lesquels bloquent lesquels — dans une équipe, en un seul appel.
kanso_triage_queue
Ce sur quoi personne n'a encore tranché.
kanso_triage
Le verdict : accepted, backlogged, duplicate ou closed, enregistré comme une décision plutôt qu'appliqué comme une modification silencieuse.

Chacun parle le vocabulaire de l'équipe. Une clé de statut que l'équipe du ticket n'a pas est refusée avec la liste de celles qu'elle a : un agent qui a deviné done dans une équipe qui dit Livré est prévenu, pas ignoré.

Le mode dev n'a aucune porte, et le dit au lieu d'échouer en silence : sous KANSO_AUTH_MODE=dev, l'identité vient d'un en-tête non vérifié, et un serveur d'autorisation derrière cela émettrait des jetons durables à quiconque peut l'atteindre.

Les jetons d'API, pour un service

Réglages → Tokens en émet un — kanso_pat_…, montré une fois, portant kanso:read et kanso:write — et il se présente de la façon ordinaire :

curl -H "Authorization: Bearer $KANSO_TOKEN" http://localhost:8080/api/teams

C'est toute l'API REST, pas une porte dessus. Le jeton porte le rôle de son propriétaire : une intégration à qui l'on donne le jeton d'un propriétaire peut faire ce qu'un propriétaire fait. Il n'existe aujourd'hui aucune portée plus étroite qu'une personne, ce qu'il vaut mieux savoir avant d'en confier un au logiciel de quelqu'un d'autre.

Les webhooks

Avec un jeton, une intégration se provisionne elle-même : POST /api/webhooks s'abonne et renvoie un secret de signature. Chaque livraison porte ensuite deux en-têtes.

X-Kanso-Event
Ce qui s'est passé.
X-Kanso-Signature
t=<unix>,v1=<hmac> sur le corps, avec le secret renvoyé par l'abonnement.

Une intégration peut aussi déclarer un champ personnalisé sur une équipe, en écrire et en lire les valeurs, et — surtout — demander à /api/teams/{id}/statuses et /api/tickets/filters quels mots cette instance emploie vraiment. Une équipe invente les siens : un service qui code done en dur est un service qui casse sur l'équipe qui l'a renommé.

L'API se décrit elle-même

GET /v3/api-docs, derrière une session ou un jeton comme toute autre lecture. Elle est générée depuis les contrôleurs plutôt que tenue à côté d'eux : elle dit donc ce que le code dit — 153 chemins et la forme de chaque corps de requête, c'est-à-dire la moitié qu'une liste de routes ne donne jamais.

GitHub

Kanso sait quel est le travail ; GitHub sait s'il est fait. Sans lien entre les deux, le même fait se tape deux fois — une branche nommée d'après un ticket, puis un ticket traîné vers Done après une fusion — et c'est la seconde frappe qu'on oublie.

Un propriétaire enregistre une GitHub App pour l'instance ; chaque membre relie ensuite son propre compte GitHub depuis les réglages, seule carte de cet écran sur laquelle un simple membre ait quelque chose à faire. Une pull request dont la branche ou le corps nomme une clé de ticket apparaît sur ce ticket, avec la branche depuis laquelle la démarrer.

Relier votre compte décide aussi de la façon dont le fil se lit. Avec, l'activité dit que vous avez passé KAN-142 en Done ; sans, le même événement se lit KAN-142 passé en Done via #418.