Files
az-agent-defaults/README.md
T
m3ta-chiron d428d53e9e feat(mcp): reference fragments + vault key naming schema + guard fixtures
README: add vault key naming schema (<server-name>-<verwendungszweck>,
kebab-case) and a key-exception example to the mcp/ guard rules.

Reference fragments in mcp/: zugferd-service.yaml (OAuth standard case,
no credential field) and az-zoll-service.yaml (documented key exception
using ${VAULT:az-zoll-service-api-key} placeholder) — neither contains
any secret.

Five invalid mcp fixtures under tests/fixtures/mcp/invalid/ covering all
README-documented failure modes: inline secret, missing server-name
fragment structure, missing url, missing type, wrong placeholder syntax.

Closes az-agent-defaults-95y
2026-08-22 10:26:56 +02:00

272 lines
10 KiB
Markdown

# az-agent-defaults — Company-Default-Set für Agenten-Artefakte
Dieses Repo ist die **eine Wahrheitsquelle** für die Standard-Artefakte, die jede
Agenten-Workstation der AZ-Gruppe gespiegelt bekommt. Es ist ein **reines
Content-Repo**: hier leben nur die Inhalte — die Technik, die sie ausliefert und
absichert, gehört in das Fleet-Repo `az-fleet` (siehe [Trennung Content /
Mechanismus](#trennung-content--mechanismus)).
Das Repo hervorgegangen aus `az-agent-skills` und löst es ab: der alte Name
würde lügen, seit neben Skills auch Commands, Agenten-Definitionen und
MCP-Server-Anbindungen dazugekommen sind.
---
## Wohin gehört mein Beitrag?
| Ich möchte beitragen … | Verzeichnis | Form |
|---|---|---|
| einen Skill (Verhaltens-Anweisung, die der Agent bei Bedarf lädt) | `skills/<name>/` | Ordner mit `SKILL.md` |
| einen Command (/slash-Befehl, wiederverwendbarer Prompt) | `commands/<name>.md` | Markdown-Datei mit Frontmatter |
| einen Agenten (spezialisiertes Profil als Primäragent oder Subagent) | `agents/<name>.md` | Markdown-Datei mit Frontmatter |
| einen MCP-Server (Werkzeug-Anbindung) | `mcp/<name>.yaml` | Konfigurations-Fragment |
Kurzform zum Einsortieren:
- **Verhalten beibringen** („mach X, wenn Y") → `skills/`
- **Wiederkehrenden Prompt als Tastendruck** → `commands/`
- **Eigenes Agenten-Profil / Prüf-Subagenten** → `agents/`
- **Werkzeug anbinden** (API, Datenquelle) → `mcp/`
Alle vier Verzeichnisse werden von der Delivery-Rolle des Fleet-Repos gelesen
— und **nur** diese vier. Alles andere im Repo (z. B. `tests/fixtures/`, diese
README, die Spec) wird nie ausgeliefert.
---
## Guard-Regeln je Artefakt-Typ
Die Delivery-Rolle in `az-fleet` führt vor jedem Rollout einen **deterministischen
Pre-Flight-Guard** aus: Struktur-, Frontmatter- und Platzhalter-Checks je Typ.
Ein ungültiges Artefakt **bricht den Run kontrolliert ab** — kaputte Inhalte
erreichen nie eine Maschine. Die Regeln unten beschreiben, was der Guard
mindestens prüft; die Implementierung lebt in `az-fleet`, nicht hier.
### `skills/` — Skills
**Struktur:** ein Ordner pro Skill, darin genau eine `SKILL.md`.
```
skills/
└── mein-skill/
└── SKILL.md
```
**Anforderungen:**
- Ordnername = Skill-Name (kein Leerzeichen, keine Umlaute; kebab-case).
- `SKILL.md` beginnt mit einem YAML-Frontmatter-Öffner (Delimited by `---`).
- Frontmatter enthält **Pflichtfelder** `name` und `description`.
- `name` muss zum Ordnernamen passen.
- `description` ist ein Satz, der sagt, wann der Skill greift.
- Darunter: Anweisungen als normales Markdown.
**Minimalbeispiel:**
```markdown
---
name: mein-skill
description: Prüft Zugferd-Rechnungen auf formal korrektes XML, wenn der Nutzer eine XRechnung validieren will.
---
# Zugferd-Validierung
Prüfe die übergebene Datei gegen das CIUS-XRechnung-Schema …
```
**Typische Fehler, die der Guard abbricht:** fehlender Ordner, fehlende
`SKILL.md`, fehlendes/leeres Frontmatter, `name` ≠ Ordnername, fehlende
`description`.
### `commands/` — Commands (/slash-Befehle)
**Struktur:** eine Markdown-Datei pro Command, direkt in `commands/`.
```
commands/
└── ticket-abarbeiten.md
```
**Anforderungen:**
- Dateiname ohne `.md` = Command-Name → in der Sitzung als `/ticket-abarbeiten` verfügbar.
- Frontmatter mit:
- `description` (**Pflicht**) — erscheint in der Command-Übersicht;
- `agent` (optional) — Agent, der den Command ausführt;
- `model` (optional) — Modell für die Ausführung.
- Body = **Template**. Argument-Platzhalter sind erlaubt und erwünscht:
- `$ARGUMENTS` — alles, was der Nutzer nach dem Command tippt;
- `$1` … `$n` — positionelle Argumente.
**Minimalbeispiel:**
```markdown
---
description: Arbeitet das genannte beads-Ticket ab (claimen, umsetzen, schließen).
agent: build
---
Arbeite das Ticket $ARGUMENTS ab: zeige es mir, claime es, setze es um und
schließ es nach meiner Freigabe.
```
**Typische Fehler:** fehlendes Frontmatter, fehlende `description`, Command-Name
mit Leerzeichen/Umlauten (die später zum /slash-Namen wird).
### `agents/` — Agenten-Definitionen
**Struktur:** eine Markdown-Datei pro Agent, direkt in `agents/`. Dateiname =
Agentenname.
**Anforderungen:**
- Frontmatter mit:
- `description` (**Pflicht**) — sagt, wofür der Agent da ist;
- `mode` (**Pflicht**) — `primary` (per Agentenwechsel wählbar) oder
`subagent` (per @mention und automatisch über das Task-Tool startbar);
- `model`, `temperature` (optional);
- Permission-/Tool-Profil (optional, aber für Subagents empfohlen) — z. B.
ein Read-only-Prüfer ohne Edit/Bash.
- Body = Systemprompt des Agenten.
**Harte Sicherheitsregeln (Guard prüft mit):**
1. **Subagent-Fähigkeit bleibt erhalten:** keine Definition darf das Task-Tool
bzw. die Delegation an Subagents so einschränken, dass Subagents nicht mehr
startbar wären. Spezialisierung ja — die Fähigkeit von Agenten, selbst zu
delegieren und zu parallelisieren, wird nie verbaut.
2. **Niemals Rechte ausweiten:** Permission-Profile dürfen innerhalb des
verwalteten Regelwerks (Managed-Layer) nur **einschränken**, nie erlauben,
was der Managed-Layer verweigert. Provider-Lock und Permission-Regelwerk
gelten unabhängig vom aktiven Agenten weiter.
**Minimalbeispiel (Read-only-Subagent):**
```markdown
---
description: Prüft Ergebnisse gegen Abnahme-Kriterien, ohne selbst zu ändern.
mode: subagent
temperature: 0.1
tools:
- read
- grep
- glob
---
Du bist ein Read-only-Prüfer. Gleiche das vorgelegte Ergebnis gegen die
Abnahme-Kriterien ab und berichte nur — du editierst und schreibst nichts.
```
**Typische Fehler:** fehlende `mode`, `mode` mit ungültigem Wert, Frontmatter
ohne `description`.
### `mcp/` — MCP-Server-Fragmente
**Struktur:** eine YAML-Datei pro Server: `mcp/<server-name>.yaml`. Jede Datei
ist ein **Fragment für den `mcp`-Konfigurationsschlüssel** — der Server-Name
steht als Schlüssel, darunter die Definition. Die Fragmente werden auf dem
Controller in die verwaltete Konfiguration (Managed-Layer) gemerged — MCPs sind
Werkzeuge und damit sicherheitsrelevant, sie gehören in den admin-kontrollierten
Layer, nicht auf die nutzerbeschreibbare Ebene.
**Anforderungen:**
- **Standard ist remote/streamable** mit OAuth: `type: remote` plus `url`;
die Anmeldung läuft zur Laufzeit einmalig pro Nutzer über dessen
Microsoft-Konto — identitätsgebunden. Ein OAuth-Server braucht daher **kein**
Credential-Feld im Fragment.
- `enabled` (optional) — Standard ist an.
- `local`-Server (`command`/`env`) nur als dokumentierte Ausnahme.
- **Secrets niemals im Repo — ohne Ausnahme.** Wo ein statischer Key nötig
ist (Nicht-OAuth-Ausnahme), steht im Fragment nur ein Platzhalter der Form
`` ${VAULT:<key-name>} ``; der echte Key liegt im Vault des Fleet-Repos und
wird erst beim Merge auf dem Controller substituiert. Im Repo bleibt nie ein
Secret.
- **Vault-Key-Namensschema:** `<server-name>-<verwendungszweck>` in
kebab-case — z. B. `${VAULT:az-zoll-service-api-key}` für den API-Key
des Servers `az-zoll-service`. Ein Key pro Credential, im Vault der IT
eindeutig zuordenbar.
**Minimalbeispiel (OAuth-Standardfall):**
```yaml
# mcp/zugferd-service.yaml
zugferd-service:
type: remote
url: https://mcp.example.az.local/zugferd
enabled: true
```
**Beispiel (dokumentierte Key-Ausnahme):**
```yaml
# mcp/az-zoll-service.yaml — kein OAuth verfügbar: statischer Key aus dem Vault
az-zoll-service:
type: remote
url: https://mcp.example.az.local/zoll
headers:
Authorization: Bearer ${VAULT:az-zoll-service-api-key}
enabled: true
```
**Typische Fehler:** Server-Name fehlt (Datei ist keine Fragment-Struktur),
fehlende `url`, `type` fehlt bei remote, ein Secret im Klartext (Guard bricht
ab — auch in Kommentaren), Platzhalter in anderer Syntax als `${VAULT:…}`.
---
## Trennung Content / Mechanismus
| Zuständigkeit | Repo |
|---|---|
| **Inhalte** (Skills, Commands, Agents, MCP-Fragmente) | **az-agent-defaults** (dieses Repo) |
| **Mechanismus** (Guard-Engine, Auslieferung/Spiegel, Drift-Reparatur, Vault-Substitution) | **az-fleet** |
Konsequenzen für Contributors:
- Dieses Repo enthält **keine** Auslieferungs-Logik, kein Playbook, kein Secret.
- Skills, Commands und Agenten-Definitionen werden als **exakter
Nutzerebene-Spiegel** ausgeliefert (inklusive Entfernen gelöschter Artefakte).
- MCP-Fragmente werden auf dem Controller in den **Managed-Layer** gemerged und
unterliegen dessen Admin-ACL.
- Der Stand dieses Repos wird über einen **Repo-Ref gepinnt** (Default: `main`).
Jeder Rollout ist damit deterministisch reproduzierbar; die Pin-Logik lebt in
`az-fleet`.
## `tests/fixtures/` — Testgegenstände, nie ausgeliefert
Guard-Tests brauchen gültige und ungültige Artefakt-Exemplare als
Testgegenstände. Diese **Fixtures** leben unter `tests/fixtures/` — denn die
Delivery-Rolle liest **nur die vier Typ-Verzeichnisse**, also kann unter
`tests/fixtures/` nichts „mitschwimmen" und versehentlich ausgeliefert werden.
(Sonntags-Entscheidung: bewusst kein eigener Auslieferungs-Ausschluss-Mechanismus,
sondern Trennung durch das Lese-Muster der Delivery-Rolle.)
Konvention: je Artefakt-Typ ein Unterordner, darin `valid/`- und
`invalid/`-Exemplare, an denen der Guard durch- bzw. abbricht.
```
tests/fixtures/
├── skills/valid/… skills/invalid/…
├── commands/valid/… commands/invalid/…
├── agents/valid/… agents/invalid/…
└── mcp/valid/… mcp/invalid/…
```
**Regel:** alles unter `tests/fixtures/` ist Testgegenstand und wird **nie
ausgeliefert** — nichts daraus in die Typ-Verzeichnisse schieben; umgekehrt
sind echte Artefakte dort fehl am Platz.
---
## Beitrags-Kurzanleitung
1. Richtiges Verzeichnis anhand der Tabelle oben wählen.
2. Artefakt gemäß Guard-Regeln des Typs anlegen (Minimalbeispiel als Vorlage).
3. Prüfen: erfüllt das Artefakt **alle** Pflichtpunkte der Checkliste seines Typs?
Wenn unsicher — die Checklisten sind vollständig; es braucht kein
Architektur-Wissen.
4. Commit/PR wie gewohnt. Der Guard läuft als Pre-Flight beim nächsten
Rollout in `az-fleet`; erst nach Rollout und App-Neustart ist das Artefakt
auf den Workstations.