カスタムエージェントの作成
カスタムペルソナは独自の specialist で Ongrid を拡張します。組み込みと まったく同じく、<name>.md ファイル + YAML フロントマターとしてディスク上に 存在します —— 同じローダー、同じレジストリ、同じ dispatch パスです。書いて マウントすれば coordinator が dispatch できるようになります。
このページがその契約です。
ファイル配置
ペルソナは YAML フロントマター付きの 1 枚の Markdown ファイルです。
---
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".フロントマターリファレンス
パーサーが理解するフィールド (ParseAgentMd):
| フィールド | 必須 | 型 | 目的 |
|---|---|---|---|
name | はい | string | spawn キー。一意であること。snake_case または kebab-case。 |
description | はい | string | coordinator のエージェントカタログに表示される。 |
when_to_use | はい | string | 1 行目がカタログに表示される。coordinator がこれなしには ペルソナを選べないため必須。 |
tools | いいえ | []string | BaseTool 名のホワイトリスト。空 = 何も継承しない。 |
disallowed_tools | いいえ | []string | ブラックリスト。ホワイトリストより優先。ワイルドカード(*_skill)対応。 |
permission_mode | いいえ | string | read-only / mutating-with-confirm / dual-sign-required。現状はインフォメーション目的。将来的にはこの値でデコレーターを自動配線する可能性あり。 |
max_turns | いいえ | int | ReAct ループのハードキャップ。デフォルト 15。 |
model | いいえ | string | LLM 識別子(例:anthropic/claude-sonnet-4-7)。組織のデフォルトにフォールバック。 |
critical_reminder | いいえ | string | システムプロンプト内で <critical-reminder>...</critical-reminder> でラップ。graph レイヤーがターンごとにも再注入。 |
initial_prompt | いいえ | string | ワーカー初回ユーザーターンの先頭に付与。稀に使用。 |
background | いいえ | bool | true = 非同期 spawn(UI ブロックしない)。reviewer が使用。 |
omit_claude_md | いいえ | bool | このペルソナでランタイムの base prompt を抑制。 |
metadata | いいえ | map | 自由形式。metadata.ongrid.{scope, min_ongrid_version} はレジストリが読む。それ以外はパススルー。 |
未知のフィールドは Agent.UnknownFields に保持されるので、将来の Claude Code ペルソナフォーマット追加(effort、isolation、mcp_servers、hooks、…)が ロードを壊しません。
tools vs disallowed_tools
ホワイトリスト + ブラックリストで、ブラックが勝ちます。つまり次のように 書くと:
tools: ["query_*", "host_bash"] # everything starting with query_, plus bash
disallowed_tools: ["query_devices"] # but not this onequery_promql、query_logql、query_traceql、query_knowledge … と host_bash が残り、query_devices だけ除外されます。
ワイルドカード:*_skill は _skill で終わるすべてのツール名にマッチします。 reviewer が全スキル実行を 1 行でブロックしている やり方がこれです。
AgentTool はどのワーカーの bag からも 自動で取り除かれます —— ワーカーはワーカーを spawn できません。 disallowed_tools に書く必要はありません。
ペルソナの置き場所
ランタイムは 2 つのルートを歩きます。
- イメージ焼き込みルート —— manager コンテナ内の
/app/agents/。 同梱の 6 つのペルソナが入っています。イメージ内では読み取り専用で、 コンテナ再起動には残りますがカスタムコードは入りません。 - マーケットプレースルート ——
/var/lib/ongrid/agents/(マウント ボリューム)。Settings → Agents UI またはマーケットプレースの インストールパスから、ユーザーが書いたペルソナがここに着地します。
両方が同じ AgentRegistry にマージされます。name 衝突が起きるとローダーは警告を記録し、最初に ロードしたものを保持します。組み込みペルソナを オーバーライド するに は、同じ name で Settings UI 経由で保存します —— AgentRegistry.Replace が in-place で upsert します。
スタート地点
最速ルートは agents/specialist-disk.md をエディタにコピーし、リネームして tool bag を調整することです。形が coordinator とうまく噛み合う規約(KB 優先、4 ステップレシピ、出力フォー マット)すべてを内包しています。
ホットリロード vs 再起動
| アクション | ホットリロード可能? | 方法 |
|---|---|---|
| ペルソナ本文の編集(システムプロンプト) | はい | Settings → Agents → Save |
| ツールホワイトリストの変更 | はい | 同上。フィルターは spawn ごとに適用。 |
model / max_turns の変更 | はい | 同上。新規 spawn が新しい値を拾う。 |
| 新規ペルソナの追加 | はい | Settings → Agents → New、またはファイル投下 + Reload |
| ペルソナの削除 | はい | Settings → Agents → Delete、またはファイル削除 + Reload |
組み込みのオーバーライド(同 name) | はい | Replace で upsert。coordinator は新しい方を使う。 |
| bag に存在するツールの集合の変更 | いいえ | BaseTool 登録はバイナリ側。 |
| 新規 BaseTool の追加 | いいえ | コード変更 + manager 再起動が必要。 |
default_locale セマンティクスの変更 | いいえ | ランタイムコード。 |
AgentRegistry のロックは sync.RWMutex です。すでにペルソナポインタを 取得済みの実行中 coordinator ターンはそのスナップショットを使い続けます。 次の coordinator ターンが新しいペルソナを見ます。
デバッグ
「coordinator が私のペルソナに dispatch しない」
- coordinator のシステムプロンプト内の エージェントカタログ を確認します (manager は
--log-level=debugで起動時に描画後のプロンプトをログ出力します)。 自分のペルソナがdescriptionとwhen_to_useの 1 行目とともに現れる はずです。 - カタログに無い場合:ローダーが警告を記録しています。API (
GET /api/v1/agents/warnings) でAgentRegistry.Warnings()を確認するか、 manager ログでchatruntime: parse <path>行を探してください。 - カタログにはあるが LLM が選ばない場合:
when_to_useを引き締めます。 具体的なトリガーパターンを冒頭に書いてください。LLM は 1 行目をマッチング ヒントとして読むように促されています。
「ワーカーは spawn するがすぐ失敗する」
よくある原因:
- ホワイトリストしたツールが bag に無い。 ランタイムフィルターは無い ものを黙って捨てるので、ワーカーは存在しないものを呼べません。
GET /api/v1/skillsでアクティブな bag を確認してください。 - モデル識別子が間違っている。 chat model resolver は未設定だと
anthropic/<x>をdefault_providerにマップします。Settings → LLM でdefault_providerをanthropicに設定するか、ペルソナで具体的な provider+model を固定してください。 max_turnsが低すぎる。 最終 assistant メッセージを出す前にターンが 尽きたワーカーはfailedで返ります。non-trivial なペルソナでは 15+ に 上げてください。
「ワーカーは OK で返すが出力がゴミ」
ペルソナ本文があなたのシステムプロンプトです。引き締めましょう。
- Step 0 から始める:1 回必須の KB 呼び出し。ワーカーを錨で固定します。
- 出力フォーマット を本文中に逐語で指定する。coordinator はこのフォーマット でパースします。
- ハード制約(読み取り専用、PII 不可、出力言語)には
critical_reminderを 使用。<critical-reminder>でラップされ、ターンごとにも 再注入されます —— LLM は毎イテレーションで見ます。
ペルソナのテスト
統合ポイントは 2 つです。
チャット画面から
/chat を開き、ペルソナの when_to_use にマッチする質問をします。SPA を 見て、coordinator が dispatch すればペルソナの name + AgentTool の description 入りの「Agent タイル」が現れます。クリックでワーカーの トランスクリプトを表示。
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>"}'ストリーミングレスポンスは以下を出します。
textデルタ —— coordinator の散文。agent_tileエンベロープ —— AgentTool dispatch ごと。task_notificationエンベロープ —— ワーカー完了。
自分のペルソナが dispatch されると、マッチした agent_tile.persona が 自分の name になります。
カスタムペルソナを書か ない べきとき
- タスクが 1 ツールで答えられる。 「自前 Prometheus にクエリ」を ペルソナでラップしないでください。カスタム BaseTool を登録して coordinator に呼ばせます。
- 一回限りのタスク。 ペルソナは繰り返しパターン用です。一回きりの 調査は coordinator に直接訊いてください。
- 5 specialist 全部に跨る呼び出しが必要。 それはまさに coordinator の 仕事です。coordinator の挙動を再現するメタ specialist を書かないで ください。
良いルール:同じ形の質問が繰り返し 来て、回答に 5+ のツール呼び出し が 要り、tool bag が coordinator の持つものより 狭い ときに、ペルソナを 書きましょう。
ペルソナの共有
.mdファイルを自分のopsリポに置きます。manager コンテナの/var/lib/ongrid/agents/下にマウントします。レジストリが起動時 (または Reload 呼び出し時)に拾います。- 組織全体への展開は スキルマーケットプレース 経由で出荷します —— マーケットプレースインストールはペルソナ + スキルを まとめてバンドルし、
Reloadを自動でトリガーします。
関連
- エージェント概要 —— 全体像。
- ペルソナフォーマット —— 全フィールド、 散文なし。
- スキルマニフェスト —— カスタムスキルと 一緒にペルソナを出荷する伴侶フォーマット。