SOP ファンイン:概要
fan-in は、SOP の実行を開始する外部イベントソースです。各ソースは dispatch_sop_event を通じて SOP エンジンにイベントを配信し、この関数は読み込まれたすべての SOP のトリガーに対して各イベントを照合し、一致したものの実行を開始します。
1 つの ZeroClaw インスタンスは、複数のファンインを同時にバインドできます。MQTT トピック、ファイルシステムパス、AMQP ルーティングキーがすべて、別々のプロセスなしで同じエンジンにフィードできます。各ソースには以下に専用ガイドがあります。
ディスパッチの仕組み
- 1つのマッチャーパス: 単一のマッチャーがすべてのトリガータイプを評価するため、マッチングはソースに関係なく同じように動作します。
- 実行開始監査: 開始された実行は
SopAuditLoggerを介して永続化されます。 - ヘッドレス実行: cron トリガーと webhook 配信は、そのランを完了まで駆動します。メンテナンスティックは、開始された cron の
ExecuteStepまたはDeterministicStepを、ヘッドレス実行ドライバーに渡します。webhook ルートも、開始されたExecuteStepをドライバーに渡します(ディスパッチは既に決定論的ステップを実行します)。ドライバーは、そのステップを SOP 自身のエージェントとして実行します。まだライブのドライバーがないソースでは、ExecuteStepアクションを実行せず、process_headless_resultsを通じて保留として記録します。 - ヘッドレス時の所有者: ヘッドレスステップは、ステップの
agentで指定されたエージェントとして実行され、指定がない場合は SOP のagentにフォールバックします。そのエージェントは設定済みかつ有効でなければなりません。ヘッドレスステップが継承できる環境的なエージェントターンは存在しないため、所有者のない手順は作成時に拒否され、ディスパッチ時にも実行を拒否されます。別の設定済みエージェントとして実行されることはありません。手動 SOP は、所有者なしで保存できる唯一のケースです。これはsop_executeが所有者を提供するためです。背後にエージェントを持たないダッシュボードの実行エンドポイントは、そのような手順の開始を拒否します。 - ヘッドレスツールのスコープ: ヘッドレスステップのターンは、ライブのターンと同じように絞り込まれます。SOP制御ツール(
sop_execute、sop_advance、sop_approve)は常に削除されるため、ステップが自身の実行を操作することはできません。sop.step_scope_enforceが設定されている場合は、ステップで宣言されたscopeがその上に適用されます。ステップから生成された子エージェントも、同じ除外設定を引き継ぎます。 - 信頼できない入力: トピックとペイロードのテキストは、モデルコンテキストに到達する前に上限が設定され、正規化され、prompt-guard でスクリーニングされ、フレーム化されます。
ソース
SopTrigger レジストリから直接投影された、すべての SOP トリガータイプ、そのフィールド、およびそのディスパッチステータス:
| タイプ | フィールド | 注釈 |
|---|---|---|
mqtt | expression | MQTTメッセージの到着。ライブ: MQTTリスナーによって配信されます。 |
webhook | path | 受信 HTTP リクエスト。稼働中: ゲートウェイの /sop/* と SOP-first の /webhook ルート。 |
cron | expression | 時間ベースの発火。ライブ: SOP メンテナンスティック(デーモン / チャネル開始パス)によってディスパッチされます。 |
peripheral | 5. 条件構文 | ハードウェア信号。定義されマッチしているが、ペリフェラルリスナーがそれをフィードしていない。 |
filesystem | path、オプションの condition、オプションの events | Filesystem の変更。Live: ファイルシステムウォッチャーによって配信されます。 |
calendar | calendar_source、オプションの calendar_ids、オプションの condition | カレンダーイベントの状態。定義されマッチしているが、ポーラーがライブでフィードしていない。 |
channel | channel、オプションの alias、オプションの condition | 設定済みチャネル (telegram、discord、slack、git、…) 上のインバウンドメッセージまたは forge/プラットフォームイベント。Live: チャネルの SOP ディスパッチが有効なときに、チャネルオーケストレーターによって配信されます。Git forge プロデューサーは <channel>.<alias>:<event_type> 形式のイベントトピックを設定し、ペイロードに event_type を格納するため、作成された condition は 2 つ目のトリガー形状なしで forge イベントをタイプでフィルタリングします。 |
manual | sop_executeツールによってトリガーされます(zeroclaw sop run CLI コマンドではありません)。 | エージェントが sop_execute ツール経由で開始した実行。外部のファンインではありません。 |
amqp | routing_key、オプションの condition | AMQP 配信。ライブ: SOP ディスパッチ モードで AMQP コンシューマーによって配信されます。 |
各ソースにはサイドバーに専用ガイドがあります。ライブソース(実行中のリスナーまたは認証済みゲートウェイリクエストによって配信されるもの)はイベントの到着時に実行を開始します。cronトリガーはデーモンの定期的なSOPメンテナンスティックによってディスパッチされます。エージェントによって開始された実行は、エージェントターン内から sop_execute を介して開始されます。残りの定義済みだが未接続のソース(周辺機器とカレンダー)は検証および照合を行いますが、ディスパッチャーにルーティングされるライブイベントソースはまだありません。
セキュリティのデフォルト設定
| 懸念 | メカニズム |
|---|---|
| Webhook 認証 | Gateway ペアリングのベアラー認証に加えて、オプションの gateway.webhook_secret/X-Webhook-Secret を使用します。/sop/* と /webhook は同じレートリミッターを共有します。SOP ディスパッチ用に少なくとも 1 つの制御を構成し、構成されたすべての制御に合格する必要があります。別個の [channels.webhook] エイリアスシークレットがこれらのルートを認可することはありません |
| Webhook のリプレイ攻撃対策 | オプションの X-Idempotency-Key。SOP パスごとに名前空間が分かれ、/sop/* と /webhook の間でも個別に扱われます。キーはディスパッチ前に予約されるため、試行は高々1回に制限されますが、以前の実行が開始されたことを示すものではありません。 |
| MQTT トランスポート | TLS トランスポート用の use_tls = true を指定した mqtts:// |
| Filesystem ルート | 広範なルート (/, /home, /etc, /var, /proc, /sys, /dev, /tmp) は allow_broad_roots がない限り設定検証で拒否される; include/exclude グロブがイベントをスコープする |
| Filesystem シンボリックリンク | デフォルトでは、シンボリックリンクのイベントパスはメタデータ、ハッシュ、コンテンツの読み取りが行われる前に拒否されます。follow_symlinks = true を指定するとこれを有効にできますが、それでも正規化されたターゲットが監視対象のルート内で解決される必要があります。 |
| 信頼できないトリガー入力 | トピックとペイロードのテキストは、上限の適用、正規化、プロンプトガードによるスクリーニング、フレーミングを経てからモデルコンテキストに渡されます |
| 安全でないトリガーブロック | untrusted_input_guard = "block" は安全でない信頼できないイベントを BlockedUnsafe で拒否します。デフォルトの warn は監査を行い許可します |
| Cron 検証 | 無効な cron 式は、パースおよびキャッシュビルド中にフェールクローズで失敗します |
| Headless ownership | ヘッドレスSOPは、設定済みかつenabledの状態にある所有agentを宣言しなければなりません。オーサリング時にはその保存がブロックされ、ドライバーは他の設定済みagentを流用することなくそのステップを拒否します。ダッシュボードから開始された手動実行も、同様に拒否されます。 |
| Headless ツールのスコープ | Headlessのステップターンでは、SOP制御ツールは常に除外され、ステップで宣言されたscopeがstep_scope_enforceの下で適用されます。ステップから生成された子エージェントも、これらの除外設定を引き継ぎます。 |
| ヘッドレスドライバーのライフタイム | cron および webhook のドライバーは、起動したデーモン世代が所有します。リロードで設定と SOP エンジンを再構築する前に、まずドレイン(30s)を行い、その後 abort して join(5s)します。この猶予時間内に await ポイントに到達しないドライバーは実行を継続し、次の世代に引き継がれます。その際は detach されるのではなく、ログに記録されます。 |
| ヘッドレスディスパッチ | Live driver ログのないソースでは、ExecuteStep を自動実行する代わりに進行状況を記録する |
トラブルシューティング
| 症状 | 考えられる原因 | 修正 |
|---|---|---|
| SOPは決してライブソースから開始しません | トリガーパターンの不一致または condition の失敗 | トリガーパターンが配信されたイベントと一致することを確認します。condition をペイロードと照合してください |
| SOP は開始されましたが、ステップが実行されませんでした | ライブドライバーのない(peripheral、calendar)ソースが ExecuteStep に到達しました | cron、webhook、またはその他のライブソースを使用する、ExecuteStep 用のエージェントループを実行する、あるいは承認待ちで一時停止するように実行を設計する |
| Cronの SOP が開始されますが、毎回「no owning agent」というエラーで失敗します | 手順では agent が宣言されておらず、ヘッドレス実行には継承すべき agent が存在しません。 | SOP.toml(またはステップ上)のagentを、設定済みのエージェントエイリアスに設定する |
| Cron SOPが毎回「which is disabled」というエラーで失敗します | 所有者のエージェントは enabled = false で設定されています | エージェントを再度有効にするか、有効なエージェントをagentに指定してください |
Dashboardの実行ボタンで、手動SOPに対して422が返される | 手順のexecuteステップには所有者が宣言されておらず、ダッシュボードの実行にはそれを引き継ぐエージェントのターンもありません。 | SOP.toml(またはステップ側)で agent を設定するか、エージェントから sop_execute で手順を開始してください |
| cronのステップは、対話的に使用したツールを呼び出すことができません | the step’s scope で step_scope_enforce によって除外されているか、SOP 制御ツールである | ステップの scope を広げてください。SOP制御ツールは設計上、引き続き除外されます。 |
| Webhook トリガーが一度も発火しない | 正確なトリガーパスの不一致、SOP サブシステムの利用不可、または認証の拒否 | sop.sops_dir を設定して zeroclaw daemon を実行し、完全なリクエストパスに正確に一致させ、設定済みの bearer/secret ヘッダーを指定します |
| 周辺機器またはカレンダーのトリガーが一度も発火しない | イベントソースがディスパッチャーに接続されていません | ライブソース(Webhook、MQTT、Filesystem、AMQP)を使用するか、sop_execute で実行を開始します |
| Cron トリガーがまったく実行されない | メンテナンスの定期実行が動作していない(zeroclaw daemon または zeroclaw channel start が実行されていない。単独の gateway start では実行されない)、sops_dir が未設定または空、あるいは maintenance_interval_secs = 0 | sop.sops_dir に空でない値(デフォルトでは未設定。ドキュメントで記載されている値は shared/sops)を設定し、sop.maintenance_interval_secs をゼロ以外(デフォルトは 60)に設定した状態で、zeroclaw daemon(または zeroclaw channel start)を実行します。 |