ADR-005: カスタム属性ゼロ
HyperGenはカスタムHTMX属性をゼロ個定義。標準HTMX + SSE拡張がすべてのGenerative UIパターンに十分。
ステータス: 承認済み 日付: 2026-03-29
コンテキスト
HyperGenの属性システム設計中に、HTMXの拡張API(htmx.defineExtension + getSelectors)を使用してカスタムHTMX属性(例: hg-agent、hg-stream、hg-context)を定義するかどうかを評価しました。
HTMXはカスタム属性プレフィックスを完全にサポートしています — SSE拡張はsse-connect/sse-swapを使用し、WebSocketはws-connect/ws-sendを使用。hg-*プレフィックスは技術的に実現可能でした。
しかし、カスタム属性はHyperGenのコア哲学に反すると結論付けました。
A2UI v0.9からの教訓
GoogleのA2UI仕様はv0.8からv0.9へ、明確なテーマを持って進化しました: 抜本的な簡素化。主な変更:
- ネストされたツリーの代わりにフラットなコンポーネント配列
- ラッパーオブジェクトの代わりにディスクリミネーターパターン(
"component": "Text") - 型ラッパーの代わりにネイティブJSON型(
{"valueString": "Alice"}の代わりに"Alice") - 交換可能なカタログ付きのモジュラースキーマ
- 「プロンプトファースト」設計(構造化出力の制約ではなく、LLMシステムプロンプトに最適化)
教訓: 最良のプロトコル設計は抽象化を追加するのではなく、削除する。
HyperGenはこの原則をさらに推し進めます。A2UIがJSONスキーマを簡素化したところで、HyperGenはJSONレイヤーを完全に排除します — HTMLがプロトコルです。そしてA2UIがコンポーネントボキャブラリーを定義する(基本カタログで18タイプ)ところで、HyperGenはボキャブラリーを一切強制しません。
決定
HyperGenはカスタムHTMX属性をゼロ個定義します。 すべての機能は標準HTMX属性と公式SSE拡張で実現。
標準HTMXがすでに提供するもの
| ニーズ | HTMXの解決策 | 例 |
|---|---|---|
| エージェントからUIをストリーミング | SSE拡張 | sse-connect="/api/agent/stream" sse-swap="message" |
| ユーザーアクションをエージェントに送信 | 標準属性 | hx-post="/api/agent/action" |
| レンダリング先の指定 | 標準属性 | hx-target="#output" hx-swap="innerHTML" |
| コンテキストデータを含める | 標準属性 | hx-vals='{"key":"value"}' |
| ローディングインジケーター | 標準属性 | hx-indicator="#spinner" |
| トリガー条件 | 標準属性 | hx-trigger="click" hx-trigger="submit" |
| アクション前の確認 | 標準属性 | hx-confirm="Are you sure?" |
HyperGenの責任ではないもの
| 関心事 | スコープ外の理由 |
|---|---|
| セッション管理 | エージェントフレームワークの関心事。標準HTTPヘッダー/Cookieを使用。 |
| 会話履歴 | エージェントフレームワークの関心事。UIプロトコルの問題ではない。 |
| ツール呼び出し確認 | エージェントが他のUIと同様に確認HTMLを生成。特別な属性不要。 |
| 認証 | アプリケーションの関心事。標準の認証メカニズムを使用。 |
| コンテキスト/メモリ | エージェントフレームワークの関心事。必要に応じてhx-valsやHTTPヘッダーで渡す。 |
例: カスタム属性ゼロの完全なHyperGen UI
<!-- Inside sandboxed iframe (see ADR-004) -->
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/htmx.org@2"></script>
<script src="https://unpkg.com/htmx-ext-sse@2"></script>
<style>
body { margin: 0; font-family: system-ui, sans-serif; }
.card { background: var(--hg-surface); padding: var(--hg-space-4); border-radius: var(--hg-radius); }
.btn { background: var(--hg-accent); color: var(--hg-accent-fg); border: none; padding: 8px 16px; cursor: pointer; }
</style>
</head>
<body>
<!-- Stream agent-generated UI -->
<div hx-ext="sse"
sse-connect="/api/agent/stream"
sse-swap="message"
hx-swap="innerHTML">
</div>
</body>
</html>エージェントはSSE経由で到着するHTMLフラグメントを生成:
<!-- Agent generates this fragment -->
<div class="card">
<h2>Weather in Tokyo</h2>
<p>Currently 18°C, partly cloudy</p>
<button class="btn"
hx-post="/api/agent/action"
hx-vals='{"action": "show_forecast"}'
hx-target="closest .card"
hx-swap="outerHTML">
Show 7-day forecast
</button>
</div>ユーザーがボタンをクリックすると、HTMXがエージェントにPOSTを送信し、エージェントはカードを置換する新しいHTMLフラグメントで応答します。どこにもカスタム属性はありません。
結果
ポジティブ
- 学ぶことがない。 HTMXを知っている開発者はすでにHyperGenを知っている。新しい概念ゼロ。
- インストールすることがない。 HyperGen固有のJavaScript拡張なし。HTMX + SSE拡張のみ。
- LLMがネイティブに生成。 標準HTMX属性はLLMのトレーニングデータに豊富に含まれる。
- 最大限のシンプルさ。 プロトコルは「HTMX属性付きのHTMLをSSE経由でストリーミング」。以上。
- 将来性。 HTMXが進化して機能を追加すると、HyperGenは仕様の更新なしに自動的に恩恵を受ける。
ネガティブ
- 「ブランドプレゼンス」が薄い。
hg-*属性がないため、HyperGenはHTMLレベルで見えない。これは意図的 — プロトコルは見えないべき。 - プロトコルレベルの検証がない。 カスタム属性がなければ、「これはHyperGen UI」と「これは通常のHTMX」を構文的に区別する方法がない。仕様はこれをトランスポート/エンベロープレベルで処理。
HyperGenの仕様が実際に定義するもの
HyperGenにカスタム属性がないなら、何を仕様化するのか?仕様は以下を定義:
- iframeブートストラップドキュメント — サンドボックス化されたiframeに読み込まれる最小限のHTML(HTMX + SSE拡張 + CSS変数ブリッジ + postMessageハンドラー)。ADR-004参照。
- SSEメッセージフォーマット — エージェント生成HTMLフラグメントがSSEイベント内でどう構造化されるか。
- postMessageプロトコル — iframe ↔ ホスト通信のメッセージタイプ(テーマ、リサイズ、ナビゲーション)。
- セキュリティ要件 — sandbox属性、CSPポリシー、許可されるオリジン。
- CSS変数規約 — デザインシステム統合のための
--hg-*変数名前空間。 - エージェント作成ガイドライン — HyperGen互換HTMLを生成するエージェント向けのベストプラクティス。
仕様はシステムアーキテクチャについてであり、新しいHTML属性の発明ではありません。
参考資料
- A2UI v0.9 Specification — 簡素化されたJSONベースのGenerative UI(設計哲学のインスピレーション)
- HTMX Extensions API — 使用しないことを選んだ拡張メカニズム
- HTMX SSE Extension — HyperGenが必要とする唯一の拡張
- ADR-003: HTMX技術選定 — HTMXを選んだ理由
- ADR-004: セキュリティモデル — iframeアーキテクチャ