エージェント作成ガイドライン
AIエージェントがHyperGen互換HTMLフラグメントを生成するためのベストプラクティス: HTMX属性、CSSテーマ、自己完結性、アクセシビリティ。
本セクションでは、HyperGen用のHTMLフラグメントを生成するAIエージェント(または任意のシステム)向けのガイドラインを提供します。サンドボックス化されたiframeで正しくレンダリングされ、ホストアプリケーションとうまく統合されるHTMLを生成するための推奨事項です。
フラグメントの自己完結性
SSE経由で配信される各HTMLフラグメントは自己完結すべきです (SHOULD) — 以前に配信されたフラグメントに依存せず、正しくレンダリングするために必要なすべてのマークアップ、スタイル、動作を含むべきです。
自己完結性が重要な理由
- SSEイベントは再接続後に順序が入れ替わる可能性がある。
- HTMXのスワップ戦略(
innerHTML、outerHTML)はサブツリー全体を置換する可能性がある。 - 新しいフラグメントのストリーミング中にユーザーがUIを操作する可能性がある。
実際に自己完結が意味すること
- フラグメントが新しいCSSクラスを導入する場合、フラグメント内またはその隣に
<style>ブロックを含める。 - スコープされたクラス名を使用(
.cardではなく.hg-weather-cardなど)して、他のフラグメントとの衝突を回避。 - フラグメントが特定のDOM構造に依存する場合、フラグメント自身が作成するIDを持つ
hx-targetを使用。
<!-- 独自のスタイルを持つ自己完結フラグメント -->
<style>
.hg-weather-card {
background: var(--hg-surface-elevated, #f9fafb);
border: 1px solid var(--hg-border, #e5e7eb);
border-radius: var(--hg-radius, 8px);
padding: var(--hg-space-4, 16px);
}
</style>
<div class="hg-weather-card">
<h2>Weather in Tokyo</h2>
<p>18°C, partly cloudy</p>
<div id="weather-detail"></div>
<button hx-get="/api/agent/weather/detail"
hx-target="#weather-detail"
hx-swap="innerHTML">
Show Forecast
</button>
</div>HTMX属性の使用
エージェントはHTML内に標準HTMX属性を含めることでインタラクティビティを生成します。カスタム属性や拡張は不要です(ADR-005参照)。
よく使用される属性
| 属性 | 用途 | 例 |
|---|---|---|
hx-get | ユーザーアクションでコンテンツを取得 | hx-get="/api/agent/detail" |
hx-post | エージェントにデータを送信 | hx-post="/api/agent/action" |
hx-target | レスポンスの配置先 | hx-target="#result" |
hx-swap | レスポンスの挿入方法 | hx-swap="innerHTML"またはhx-swap="outerHTML" |
hx-trigger | リクエスト送信のタイミング | hx-trigger="click"またはhx-trigger="submit" |
hx-vals | 含める追加データ | hx-vals='{"action":"approve","id":42}' |
hx-indicator | ローディング要素を表示 | hx-indicator="#spinner" |
hx-confirm | 確認を要求 | hx-confirm="Delete this item?" |
スワップ戦略
インタラクションパターンに基づいてスワップ戦略を選択:
| 戦略 | 使用タイミング |
|---|---|
innerHTML | ターゲット内のコンテンツを置換し、ターゲット要素自体は保持。ほとんどの場合のデフォルト。 |
outerHTML | ターゲット要素全体を置換。レスポンスが現在のコンポーネントの完全な置換の場合に使用。 |
beforeend | ターゲットに追加。チャットメッセージ、ログエントリ、リストアイテムに使用。 |
afterend | ターゲット要素の後に挿入。兄弟コンテンツの追加に使用。 |
none | スワップしない。リクエストが可視UIを変更せずに副作用(例: hg:dataイベント)をトリガーする場合に使用。 |
ターゲティングパターン
<!-- IDでターゲット -->
<button hx-get="/api/data" hx-target="#output">Load</button>
<div id="output"></div>
<!-- トリガー要素からの相対ターゲット -->
<div class="card">
<button hx-post="/api/update"
hx-target="closest .card"
hx-swap="outerHTML">
Update Card
</button>
</div>
<!-- 要素自体をターゲット(デフォルト動作) -->
<div hx-get="/api/refresh" hx-trigger="every 30s" hx-swap="innerHTML">
Auto-refreshing content
</div>コンテキストデータの送信
hx-valsを使用してエージェントサーバーにコンテキストを渡す:
<button hx-post="/api/agent/action"
hx-vals='{"action":"analyze","dataset":"sales_q4","format":"chart"}'
hx-target="#result"
hx-swap="innerHTML">
Analyze Sales Data
</button>フォームの場合、HTMXは自動的にすべてのフォームフィールド値を含めます。標準フォーム送信にhx-valsは不要です:
<form hx-post="/api/agent/query" hx-target="#result" hx-swap="innerHTML">
<input type="text" name="query" placeholder="Ask anything..." />
<select name="model">
<option value="fast">Fast</option>
<option value="thorough">Thorough</option>
</select>
<button type="submit">Ask</button>
</form>
<div id="result"></div>CSSスタイリングのベストプラクティス
--hg-*変数を使用
ホストのデザインシステムに合わせるべきすべての視覚プロパティは、フォールバック値付きの--hg-*変数を参照しなければなりません (MUST)。完全な変数リストはCSS変数テーマを参照。
/* 良い例: フォールバック付きテーマ変数を使用 */
.my-component {
background: var(--hg-surface, #ffffff);
color: var(--hg-text, #111827);
border: 1px solid var(--hg-border, #e5e7eb);
}
/* 悪い例: ホストテーマに合わないハードコードされた色 */
.my-component {
background: #ffffff;
color: #333333;
border: 1px solid #ccc;
}固定寸法を避ける
フラグメントは任意の幅のiframe内にレンダリングされます。レスポンシブ手法を使用:
/* 良い例: レスポンシブ */
.chart-container {
width: 100%;
max-width: 600px;
aspect-ratio: 16 / 9;
}
/* 悪い例: 固定幅はオーバーフローする可能性 */
.chart-container {
width: 600px;
height: 400px;
}クラス名にプレフィックスを付ける
フラグメント間の衝突を避けるため、CSSクラス名にプレフィックスを付けます。コンポーネントの目的に関連する短いプレフィックスで十分です:
/* このフラグメントにスコープ */
.hg-weather-card { ... }
.hg-weather-temp { ... }
.hg-weather-icon { ... }インラインスタイルとスタイルブロック
- 複数のスタイル付き要素を持つフラグメントには
<style>ブロックを使用。 - 単一要素へのワンオフスタイリングにはインライン
style属性を使用。 - 外部スタイルシートのロードに
<link>を使用すべきではない (SHOULD NOT)(レイテンシが増加し、CSPにブロックされる可能性あり)。
インラインスクリプト
エージェント生成HTMLは、サーバーへのラウンドトリップを必要としないクライアントローカルの動作のためにインライン<script>ブロックを含めてもよいです (MAY)。
インラインスクリプトを使用する場合
- ローカル計算(スライダー値の表示、ライブ文字数カウントなど)
- クライアントサイドレンダリング(ブートストラップに読み込まれたチャートライブラリによるチャートなど)
- アニメーションとビジュアルエフェクト
- ホストへの
hg:dataイベント送信 - ホストレベルナビゲーション用の
hg:navigateトリガー
インラインスクリプトを使用しない場合
- サーバー通信 — 代わりにHTMX属性(
hx-get、hx-post)を使用 - フラグメント間で永続化すべき状態管理 — エージェントサーバーを使用
- 外部スクリプトの読み込み — CSPがブロックする可能性あり
SSEフラグメント内のスクリプト実行
HTMXが<script>タグを含むHTMLをスワップすると、スクリプトは自動的に実行されます(HTMXがこれを処理します)。エージェントはSSEフラグメントに含まれるスクリプトのこの動作に依存できます。
<div id="chart-container" style="width:100%; height:300px;"></div>
<script>
// This script runs when HTMX swaps this fragment into the DOM
var container = document.getElementById('chart-container');
// ... render a chart using a library loaded in the bootstrap
</script>ホストへのデータ送信
<button onclick="document.dispatchEvent(new CustomEvent('hg:data', {
detail: { action: 'selected', itemId: 42 }
}))">
Select Item
</button>ホストナビゲーションのトリガー
<a data-hg-navigate="/dashboard" href="#">Go to Dashboard</a>またはスクリプト経由:
<button onclick="window.parent.postMessage({
type: 'hg:navigate', url: '/settings'
}, '*')">
Open Settings
</button>ローディングインジケーター
HTMXの組み込みインジケーターメカニズムを使用して、エージェントインタラクション中のローディング状態を表示:
<button hx-post="/api/agent/analyze"
hx-target="#result"
hx-indicator="#spinner">
Analyze
</button>
<span id="spinner" class="hg-indicator">Loading...</span>
<div id="result"></div>ブートストラップドキュメントには、デフォルトで.hg-indicatorを非表示にし、保留中のリクエスト時にHTMXが.htmx-requestクラスを追加した際に表示するCSSが含まれています。
エラーハンドリング
エージェントはHTTPエラーコードに依存するのではなく、ユーザーフレンドリーなエラー状態をHTMLとして生成すべきです (SHOULD):
<div class="hg-error" style="
background: var(--hg-surface-elevated, #f9fafb);
border: 1px solid #ef4444;
border-radius: var(--hg-radius, 8px);
padding: var(--hg-space-4, 16px);
color: var(--hg-text, #111827);
">
<strong>Something went wrong</strong>
<p style="color: var(--hg-text-muted, #6b7280);">
Unable to retrieve weather data. Please try again.
</p>
<button hx-get="/api/agent/weather"
hx-target="closest .hg-error"
hx-swap="outerHTML">
Retry
</button>
</div>SSEストリームエラーの場合、ブートストラップドキュメントの接続状態CSSクラス(hg-connected / hg-disconnected)が自動的な視覚フィードバックを提供します。
アクセシビリティに関する考慮事項
エージェント生成HTMLはWebアクセシビリティのベストプラクティスに従うべきです (SHOULD):
セマンティックHTML
適切なHTML要素をその意図された目的に使用:
<!-- 良い例: セマンティック -->
<nav aria-label="Results navigation">
<button hx-get="/api/page/1" hx-target="#results">Page 1</button>
<button hx-get="/api/page/2" hx-target="#results">Page 2</button>
</nav>
<!-- 悪い例: divだらけ -->
<div>
<div onclick="...">Page 1</div>
<div onclick="...">Page 2</div>
</div>ARIA属性
セマンティックHTMLだけでは不十分な場合にARIA属性を追加:
<div role="alert" aria-live="polite">
Analysis complete: 3 anomalies found.
</div>
<button hx-post="/api/agent/action"
aria-label="Delete report for Q4 2025"
hx-confirm="Delete this report?">
Delete
</button>キーボードナビゲーション
すべてのインタラクティブ要素がキーボードアクセス可能であることを確認:
- クリック可能なアクションには
<button>を使用(<div onclick>ではなく)。 - ナビゲーションには
<a>を使用(ホストナビゲーションにはdata-hg-navigate付き)。 - カスタムウィジェットには適切な
tabindex、role、キーボードイベントハンドラーを設定。
カラーコントラスト
--hg-*テーマ変数を使用する場合、コントラスト比はホストのテーマに依存します。エージェントは以下をすべきです (SHOULD):
--hg-text/--hg-surfaceペアに依存する(ホストが適切なコントラストを担保する責任がある)。--hg-surface背景上のテキスト色として--hg-accentを使用しない(アクセントカラーはサーフェスカラーと十分なコントラストを持たない可能性がある)。--hg-accent背景上のテキストには--hg-accent-fgを使用する。
ライブリージョン
動的に更新されるコンテンツ(ストリーミング結果など)には、ARIAライブリージョンを使用:
<div aria-live="polite" aria-atomic="false">
<div id="result" hx-swap="innerHTML">
<!-- ストリーミングコンテンツがここに表示、スクリーンリーダーが更新をアナウンス -->
</div>
</div>やるべきこと・やるべきでないことのまとめ
| やるべきこと | やるべきでないこと |
|---|---|
テーマ依存のすべてのスタイルに--hg-*変数を使用 | 色、フォント、スペーシングをハードコード |
var()フォールバック値を含める | テーマ変数が常に設定されていると仮定 |
サーバー通信にhx-post/hx-getを使用 | エージェント通信にfetch()やXMLHttpRequestを使用 |
| フラグメントを自己完結させる | 以前のフラグメントのCSS/JSに依存 |
| セマンティックHTML要素を使用 | すべてに<div>と<span>を使用 |
| CSSクラス名にプレフィックスを付ける | 衝突する可能性のある汎用クラス名を使用 |
レスポンシブレイアウト(%、max-width)を使用 | 固定ピクセル寸法を使用 |
| アクセシビリティのためのARIA属性を含める | キーボードナビゲーションとスクリーンリーダーを無視 |
| エラー状態をHTMLとして生成 | HTTPステータスコードだけに依存 |