Wie verwaltet man KI-Agenten aus einem Skript heraus?
Ein API-Schlüssel meldet Skripte und Pipelines an der covey-API an. Was er darf, was nur der Browser kann und wie Rotation und Widerruf wirken.
Eine Pipeline soll nach jedem Merge die Konfiguration eines bestehenden Agenten in covey einspielen, und ein Skript soll am Monatsende die Kosten der Läufe abholen. Beides sind Aufrufe gegen dieselbe API, die auch die Weboberfläche benutzt. Die Oberfläche meldet sich dort mit einem Sitzungscookie an, das als HttpOnly und SameSite=Strict gesetzt ist. Das Attribut HttpOnly verhindert dabei, dass ein Skript es liest. Die Dokumentation beschreibt, was ohne einen zweiten Weg geschieht: Die Arbeit läuft dann neben dem Produkt, in einer fremden CI, mit kopiertem Cookie oder von Hand.
Ein naheliegender Ausweg ist das persönliche Token eines Menschen mit dessen vollen Rechten. Wie das ausgehen kann, zeigt ein Beitrag, der im Juli 2024 auf Hacker News mit 114 Punkten unter dem Titel „Leaked admin access token to Python, PyPI, and PSF GitHub repos“ stand. Ein Kommentar hielt fest, das Geheimnis habe nie im Repository gelegen, sondern im Container-Image. Laut einem anderen Kommentar war das Token zu diesem Zeitpunkt seit 15 Monaten im Umlauf.
covey beantwortet dieselbe Aufgabe mit einem API-Schlüssel, der im Browser unter „API-Schlüssel“ im eigenen Profil erzeugt wird und danach als Header Authorization: Bearer covey_… mitgeht. Bis auf die Ausnahmen weiter unten funktioniert damit jede Route der Oberfläche auf dieselbe Weise. Die Pipeline schickt damit POST /api/v1/agents/{id}/config/import mit dem Bündel des Agenten als Rumpf.
Ein Schlüssel trägt genau die Rechte des Sitzes, aus dem er stammt
Ein Konto kann Mitglied in mehreren Organisationen sein, jeweils mit eigener Rolle. Diese Mitgliedschaft heißt in covey Sitz. Der Schlüssel hängt an dem Sitz, von dem aus er erzeugt wurde. Verliert die Person diesen Sitz, verschwindet der Schlüssel mit ihm, da die Tabelle api_keys laut Migration 0077 per Kaskade an der Mitgliedschaft hängt.
Auf einen eigenen Geltungsbereich verzichtet covey bei Schlüsseln mit Absicht. Die Dokumentation begründet das damit, dass ein Scope, der nur auf dem Papier existiert, wie eine Einschränkung aussieht und trotzdem nichts durchsetzt. Die Rolle dagegen wird an jeder Route geprüft. Der Schlüssel eines Auditors liest deshalb, und der Schlüssel eines Org-Admins kann alles, was ein Org-Admin kann. Für das Kostenskript reicht ein Auditor-Sitz, da GET /api/v1/cost/runs allen Rollen offensteht.
Darin liegt zugleich die Schwäche dieser Lösung. Wer der Pipeline weniger Rechte geben will als sich selbst, braucht dafür einen Sitz mit engerer Rolle, weil der Schlüssel immer so weit reicht wie sein Sitz.
Für die Pipeline aus dem Beispiel genügt ein Sitz als agent_owner, solange ein Merge die Werkzeugfreigaben in ACCESS.md und die Egress-Regeln in EGRESS.md gegenüber dem Stand des Agenten unverändert lässt. Ändert das Bündel eines davon, antwortet covey mit 403, sodass von den Rollen, die diese Route überhaupt zulässt, nur org_admin es einspielen kann. Der Schlüssel eines Org-Admins in einer Pipeline ist damit dieselbe Art Token wie das aus dem Hacker-News-Faden.
Anlegen, Rotieren, Widerrufen und ein neues Passwort verlangen den Browser
Die Routen für Schlüssel sind in server.go mit sessionOnly umschlossen und antworten auf einen Schlüssel mit 403 und der Aufforderung, sich im Browser anzumelden. Für das Passwort prüft profile.go dasselbe, während die Liste der eigenen Schlüssel auch mit einem Schlüssel lesbar bleibt.
Der Grund steht in der Dokumentation in einem Satz: Ein abhandengekommener Schlüssel soll sich nicht selbst verewigen können. Einen zweiten Schlüssel anlegen und den Besitzer aussperren sind die ersten Schritte eines Angreifers, und beide verlangen in covey das Passwort.
Beim Anlegen erscheint das Token einmal, danach steht in der Liste sein Anfang
Beim Anlegen bekommt der Schlüssel einen Namen mit höchstens 80 Zeichen und auf Wunsch eine Laufzeit von bis zu zehn Jahren. Das Token erscheint ein einziges Mal, denn gespeichert wird nur sein SHA-256-Hash. In der Liste bleiben der Name, die ersten acht Zeichen nach covey_ und die Angabe „Zuletzt benutzt“, die höchstens alle fünf Minuten fortgeschrieben wird.
Rotation, Widerruf und Ablauf wirken ab der nächsten Anfrage
Rotieren erzeugt ein neues Token mit demselben Namen und demselben Sitz. Ohne neue Angabe behält es auch die Laufzeit, gezählt ab jetzt und selbst dann, wenn der Schlüssel schon abgelaufen war. Das alte Token verliert seine Gültigkeit in derselben Transaktion, sodass es keinen Moment mit zwei gültigen Tokens für einen Zweck gibt. Ein Widerruf löscht die Zeile und wirkt ab der nächsten Anfrage, da jeder Aufruf den Hash in der Datenbank nachschlägt und dabei das Ablaufdatum prüft.
Diese nächste Anfrage bekommt bei einem widerrufenen und bei einem abgelaufenen Schlüssel die Antwort 401 mit „api key invalid or expired“. Dieselbe Antwort erhält ein Schlüssel, dessen Sitz verschwunden ist, damit niemand die drei Fälle durch Ausprobieren unterscheiden kann.
Am Präfix covey_ erkennen Scanner und die API einen Schlüssel
Ein Kommentar unter dem Hacker-News-Beitrag „My adventure in designing API keys“ vom April 2026 beschreibt den Zweck eines solchen Präfixes. Es sei vor allem für Scanner gedacht, die einen eingecheckten oder abgeflossenen Schlüssel erkennen und ungültig machen. Der Quelltext von covey nennt denselben Grund. Auch die API selbst prüft das Präfix, denn ein Bearer-Token ohne covey_ gilt dort gar nicht als Schlüssel, und die Anfrage endet mit 401 „not signed in“.
Repository, offene CI-Variable, URL und Agenten-Sandbox sind die falschen Orte für einen Schlüssel
Die Dokumentation nennt als Erstes das Repository und eine CI-Variable, die jeder mit Zugang zur Pipeline lesen kann. In die URL gehört ein Schlüssel ebenso wenig, weil ein Query-String im Zugriffsprotokoll landet und ein Header dort fehlt. Auch die Sandbox eines Agenten ist der falsche Ort, da der Agent covey über den Action-Proxy erreicht und dafür ohne Zugangsdaten auskommt.
Das Audit-Log verzeichnet die Person und lässt die Verwaltung der Schlüssel aus
Bei verändernden Anfragen hält das Audit-Log die Person, ihre Rolle, Methode, Pfad und Ergebnis fest. Der einzelne Schlüssel fehlt darin, sodass offen bleibt, welcher von zwei Schlüsseln derselben Person eine Konfiguration eingespielt hat. Pfade unter /api/v1/auth/ sind vom Audit-Log ausgenommen, und damit auch das Anlegen, Rotieren und Widerrufen eines Schlüssels.
Für die Pipeline aus dem Beispiel folgt daraus ein Schlüssel, der ihren Namen trägt und eine Laufzeit hat. Ob sie den Schlüssel noch benutzt, zeigt die Angabe „Zuletzt benutzt“ in der Liste.