Benutzerdefinierte Agenten verfassen
Benutzerdefinierte Personas erweitern Ongrid um Ihre eigenen Specialists. Sie liegen auf Disk als <name>.md-Dateien mit YAML-Frontmatter, genau wie die eingebauten — gleicher Loader, gleiche Registry, gleicher Dispatch-Pfad. Schreiben Sie eine, mounten Sie sie, und der coordinator kann zu ihr dispatchen.
Diese Seite ist der Vertrag.
Datei-Layout
Eine Persona ist eine einzelne Markdown-Datei mit YAML-Frontmatter:
---
name: specialist-clickhouse
description: ClickHouse 查询性能 / 分区健康 / mutation backlog 专家
when_to_use: |
When the user asks about:
- ClickHouse query plan / scan / shuffle slow
- Partition merges / mutation backlog
- Replication lag between replicas
- System.parts / system.mutations inspection
tools:
- query_knowledge
- query_clickhouse_system # custom BaseTool you registered
- query_promql # for clickhouse_* metrics
- host_bash
- get_edge_summary
disallowed_tools:
- host_restart_service
permission_mode: read-only
max_turns: 12
model: anthropic/claude-sonnet-4-7
critical_reminder: |
You're read-only. Never propose direct ALTER / OPTIMIZE without
citing the system.mutations evidence first. Always check the
replication lag before recommending any maintenance command.
---
# specialist-clickhouse
You are Ongrid's ClickHouse specialist.
## Step 0: knowledge base check (mandatory)
Before any inspection, call `query_knowledge` once with a natural-
language description of the question. Hit (score >= 0.6) → follow
the playbook. Cite as `(参考 KB: <title>)` in your final reply.
## Working style
1. Start with `query_clickhouse_system` for system.parts /
system.mutations / system.replication_queue. One call, broad
snapshot.
2. If a specific table is suspect, drill into `system.parts` for
that table with bytes / rows / merge_state.
3. For replication: `system.replication_queue` for failures,
`clickhouse_replica_delay_seconds` PromQL series for trend.
4. For query perf: `system.query_log` with `query_duration_ms`
sort + `read_rows` to find the heavy query.
## Output
- 现状 (1-2 sentences): which table, which metric, what's wrong.
- 证据 (2-3 lines): system.* row excerpts + PromQL value.
- 建议 (1 line): observation only, or "recommend dispatching
specialist-ops to run OPTIMIZE/ALTER under reviewer".Frontmatter-Referenz
Die Felder, die der Parser versteht (ParseAgentMd):
| Feld | Erforderlich | Typ | Zweck |
|---|---|---|---|
name | ja | string | Spawn-Key. Muss eindeutig sein. snake_case oder kebab-case. |
description | ja | string | Im Agent-Katalog des coordinators sichtbar. |
when_to_use | ja | string | Erste Zeile erscheint im Katalog. Strikt erforderlich, weil der coordinator ohne sie keine Persona wählen kann. |
tools | nein | []string | Whitelist von BaseTool-Namen. Leer = nichts erben. |
disallowed_tools | nein | []string | Blacklist. Gewinnt über Whitelist; unterstützt Wildcards (*_skill). |
permission_mode | nein | string | read-only / mutating-with-confirm / dual-sign-required. Heute informativ; zukünftige Versionen könnten Decorators basierend darauf automatisch verdrahten. |
max_turns | nein | int | Harte ReAct-Loop-Obergrenze. Default 15. |
model | nein | string | LLM-Identifier (z. B. anthropic/claude-sonnet-4-7). Fällt auf Org-Default zurück. |
critical_reminder | nein | string | In <critical-reminder>...</critical-reminder> im System-Prompt eingewickelt. Wird auch pro-Turn von der Graph-Schicht reinjeziert. |
initial_prompt | nein | string | Wird dem ersten User-Turn des Workers vorangestellt. Selten verwendet. |
background | nein | bool | true = async Spawn (UI blockiert nicht). Vom reviewer verwendet. |
omit_claude_md | nein | bool | Unterdrückt den Base-Prompt der Runtime für diese Persona. |
metadata | nein | map | Frei. metadata.ongrid.{scope, min_ongrid_version} wird von der Registry gelesen; alles andere ist Pass-Through. |
Unbekannte Felder werden in Agent.UnknownFields erhalten, sodass zukünftige Claude-Code-Persona-Format-Ergänzungen (effort, isolation, mcp_servers, hooks, …) das Laden nicht brechen.
tools vs. disallowed_tools
Whitelist + Blacklist, Schwarz gewinnt. Also:
tools: ["query_*", "host_bash"] # everything starting with query_, plus bash
disallowed_tools: ["query_devices"] # but not this onelässt query_promql, query_logql, query_traceql, query_knowledge, … und host_bash übrig, minus query_devices.
Wildcards: *_skill matcht jeden Tool-Namen, der auf _skill endet. So blockiert der reviewer alle Skill-Ausführungen in einer Zeile.
Das AgentTool wird auch automatisch aus der Tasche jedes Workers gestrippt — Workers können keine Workers spawnen. Sie müssen es nicht unter disallowed_tools listen.
Wo Personas liegen
Die Runtime durchläuft zwei Roots:
- Das image-gebackene Root —
/app/agents/innerhalb des Manager-Containers. Enthält die sechs ausgelieferten Personas. Schreibgeschützt innerhalb des Images; überlebt Container-Restart, aber keinen Custom-Code. - Das Marketplace-Root —
/var/lib/ongrid/agents/(gemountetes Volume). Nutzerverfasste Personas landen hier via die Settings → Agents-UI oder via den Marketplace-Install-Pfad.
Beide werden in dieselbe AgentRegistry gemerged. Bei einer Namenskollision protokolliert der Loader eine Warnung und behält den ersten Load. Um eine eingebaute Persona zu überschreiben, speichern Sie Ihre Version mit demselben name via die Settings-UI — AgentRegistry.Replace upsertet an Ort und Stelle.
Wo anfangen
Der schnellste Pfad ist, agents/specialist-disk.md in Ihren Editor zu kopieren, umzubenennen und die Tool-Tasche anzupassen. Die Form trägt alle Konventionen (KB-First, 4-Schritte-Rezept, Ausgabeformat), die gut mit dem coordinator funktionieren.
Hot Reload vs. Restart
| Aktion | Hot-reloadbar? | Wie |
|---|---|---|
| Persona-Body editieren (System-Prompt) | Ja | Settings → Agents → Save |
| Tool-Whitelist ändern | Ja | Gleich. Filter wird pro Spawn angewendet. |
model / max_turns ändern | Ja | Gleich. Neue Spawns übernehmen die neuen Werte. |
| Eine neue Persona hinzufügen | Ja | Settings → Agents → New, oder Datei ablegen + Reload |
| Eine Persona löschen | Ja | Settings → Agents → Delete, oder Datei entfernen + Reload |
Eine eingebaute überschreiben (gleicher name) | Ja | Replace upsertet; coordinator verwendet die neue. |
| Ändern, welche Tools in der Tasche existieren | Nein | BaseTool-Registrierung ist binäreitig. |
| Ein neues BaseTool hinzufügen | Nein | Erfordert Code-Änderung + Manager-Restart. |
default_locale-Semantik ändern | Nein | Das ist Runtime-Code. |
Das Lock um AgentRegistry ist ein sync.RWMutex. Ein in-flight Coordinator-Turn, der bereits einen Persona-Pointer geholt hat, verwendet weiter den Snapshot; der nächste Coordinator-Turn sieht die neue Persona.
Debugging
„Coordinator dispatcht nie zu meiner Persona"
- Prüfen Sie den Agent-Katalog im System-Prompt des coordinators (der Manager loggt den gerenderten Prompt beim Start mit
--log-level=debug). Ihre Persona sollte mit ihrerdescriptionund der ersten Zeile vonwhen_to_useerscheinen. - Wenn der Katalog sie vermisst: der Loader hat eine Warnung erfasst. Prüfen Sie
AgentRegistry.Warnings()via die API (GET /api/v1/agents/warnings) oder suchen Sie nachchatruntime: parse <path>-Zeilen im Manager-Log. - Wenn der Katalog sie hat, aber das LLM sie nicht wählt: verschärfen Sie
when_to_use. Beginnen Sie mit einem konkreten Trigger-Muster; das LLM wird angewiesen, die erste Zeile als Matching-Hinweis zu lesen.
„Worker spawnt, scheitert aber sofort"
Häufige Ursachen:
- Ein whitelisted Tool ist nicht in der Tasche. Die Runtime filtert und droppt stillschweigend alles nicht Vorhandene; der Worker kann nicht aufrufen, was nicht da ist. Prüfen Sie
GET /api/v1/skillsfür die aktive Tasche. - Der Modell-Identifier ist falsch. Der Chat-Modell-Resolver mappt
anthropic/<x>aufdefault_provider, wenn nicht konfiguriert. Setzen Siedefault_provideraufanthropicin Settings → LLM oder pinnen Sie einen konkreten Provider+Modell in der Persona. max_turnsist zu niedrig. Ein Worker, dem die Turns ausgehen, bevor er eine endgültige Assistant-Nachricht produziert, gibtfailedzurück. Erhöhen Sie auf 15+ für jede nicht-triviale Persona.
„Worker gibt OK zurück, aber die Ausgabe ist Müll"
Der Persona-Body ist Ihr System-Prompt. Verschärfen:
- Beginnen Sie mit Schritt 0: einem einzelnen erzwungenen KB-Aufruf. Verankert den Worker.
- Spezifizieren Sie das Ausgabeformat wörtlich im Body. Der coordinator parst auf dieses Format.
- Verwenden Sie
critical_reminderfür harte Constraints (read-only, kein PII, Ausgabesprache). Es wird in<critical-reminder>eingewickelt UND pro-Turn reinjeziert — das LLM sieht es bei jeder Iteration.
Ihre Persona testen
Zwei Integrationspunkte:
Von der Chat-Oberfläche
Öffnen Sie /chat, stellen Sie eine Frage, die zur when_to_use Ihrer Persona passt. Beobachten Sie die SPA — wenn der coordinator dispatcht, erscheint ein „Agent-Tile" mit dem name Ihrer Persona + der AgentTool-description. Klicken Sie für das Worker-Transkript.
Von der API
curl -X POST http://localhost:8080/api/v1/chat \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"prompt": "<the question that should trigger your persona>"}'Die Streaming-Response zeigt:
text-Deltas — die Prose des coordinators.agent_tile-Envelopes — jeder AgentTool-Dispatch.task_notification-Envelopes — Worker-Completion.
Wenn Ihre Persona dispatched wird, ist das passende agent_tile.persona Ihr name.
Wann KEINE benutzerdefinierte Persona schreiben
- Die Aufgabe ist eine 1-Tool-Antwort. Wickeln Sie „query my custom Prometheus" nicht in eine Persona. Registrieren Sie ein benutzerdefiniertes BaseTool und lassen Sie den coordinator es aufrufen.
- Die Aufgabe ist einmalig. Personas sind für wiederholte Muster. Für eine One-Shot-Untersuchung fragen Sie den coordinator einfach direkt.
- Die Aufgabe muss über alle 5 Specialists hinweg aufrufen. Das ist genau das, wofür der coordinator da ist; schreiben Sie keinen Meta-Specialist, um das Verhalten des coordinators nachzubauen.
Eine gute Regel: schreiben Sie eine Persona, wenn dieselbe Frageform wiederkehrt, die Antwort 5+ Tool-Aufrufe erfordert und die Tool-Tasche schmaler ist als das, was der coordinator trägt.
Personas teilen
- Legen Sie die
.md-Datei in Ihrops-Repo. Mounten Sie sie in den Manager-Container unter/var/lib/ongrid/agents/. Die Registry nimmt sie beim Start auf (oder bei einem Reload-Aufruf). - Für org-weites Rollout liefern Sie über den Skill-Marketplace aus — der Marketplace-Install bündelt Personas + Skills zusammen und triggert automatisch ein
Reload.
Verwandt
- Agents-Übersicht — das Gesamtbild.
- Persona-Format — jedes Feld, keine Prosa.
- Skill-Manifest — Companion-Format zum Versand von Personas zusammen mit benutzerdefinierten Skills.