[Discordスレッド_boundサブエージェントがno_active_runエラーで生成失敗] - Thread-Bound Subagent Spawns Fail with 'no_active_run' on Discord
Discordスレッドにバインドされたサブエージェントセッションは、正しい設定と権限にもかかわらず、'no_active_run'エラーで即座に失敗します。一方、スレッドなしのサブエージェントは正常に生成されます。
🔍 症状
Discordチャンネルでスレッドにバインドされたサブエージェントがspawnされると、subagent_spawningフックが実行された直後に終了し、no_active_runアボードエラーが発生します。以下の技術的兆候が観察されます:
- フック実行の成功:
subagent_spawningフックが正常に起動し、spawnリクエストが有効であることを示すtrueを返します。 - 即座のセッションアボード:サブエージェントセッションレーンが
no_active_runを示すアボードコードで初期化に失敗します。 - レーン作成の失敗:正常に動作する非スレッドspawn不同的是、ランタイムログに
lane=session:agent:main:subagent:<uuid>エントリが表示されません。 - サイレントフェイルモード:Discordスレッドは作成されますが空のままです—スレッド内にエージェントのレスポンスメッセージが表示されません。
診断ログの比較:
# FAILURE CASE — Thread-bound subagent spawn
[INFO] subagent_spawning hook executing for agent=example-agent
[INFO] subagent_spawning hook completed: spawn_requested=true
[ABORT] subagent session aborted: reason=no_active_run, session_id=<uuid>
[DEBUG] lane creation skipped: no active run context available
# SUCCESS CASE — Non-threaded subagent spawn
[INFO] subagent_spawning hook executing for agent=example-agent
[INFO] subagent_spawning hook completed: spawn_requested=true
[INFO] lane created: session:agent:main:subagent:<uuid>
[INFO] subagent session initialized: agent=example-agent
設定コンテキスト:
# Relevant configuration flags (all enabled)
channels:
discord:
threadBindings:
enabled: true
spawnSubagentSessions: true
session:
threadBindings:
enabled: true
🧠 原因
スレッドにバインドされたサブエージェントspawnにおけるno_active_runエラーは、Discordスレッド確立とサブエージェントセッションレーン作成の間のコンテキスト伝播の競合状態に起因します。
技術的失敗シーケンス:
- スレッド作成フェーズ:OpenClawは
channel.discord.createThread()API経由でDiscordスレッドバインディングを開始します。これは非同期I/O操作です。 - 早期のレーン作成:サブエージェントセッションサブシステムが、スレッドコンテキストが完全に確立され、親ランにバインドされる前に
session:agent:main:subagent:<uuid>レーンを作成しようとします。 - コンテキスト解決の失敗:レーン作成には有効な
thread_idプロパティを持つアクティブなランコンテキスト(RunContext)が必要です。Discord APIによってスレッドが確認されていないため、コンテキスト解決はnullまたは不完全なコンテキストを返します。 - アボードトリガー:セッションサブシステムは、欠落しているコンテキストを
no_active_runとして解釈し、スレッドバインディングの完了前にspawnを終了します。
アーキテクチャの不整合:
非スレッドspawnパスはスレッドコンテキスト解決を完全にバイパスします—セッションレーンは既存のランコンテキスト内で直ちに作成されます。スレッドパスは以下の依存チェーンを導入します:
spawnSubagent()
└─> createThread() [async Discord API call]
└─> resolveRunContext() [requires thread_id]
└─> createSessionLane() [fails if context incomplete]
└─> ABORT: no_active_run
Discord APIのラウンドトリップレイテンシ(通常100〜500ms)は、セッションの初期化が有効なスレッドコンテキストなしで進行するウィンドウを作成します。spawnSubagentSessionsフラグはspawnを有効にしますが、非同期スレッドバインディングライフサイクルを考慮していません。
🛠️ 解決手順
展開の制約に応じて、2つの修正パスが存在します。
オプションA:同期スレッドバインディングを有効にする(推奨)
スレッドの確認が完了するまでレーン作成をブロックする同期スレッド確立を使用するようにDiscordチャンネルを設定します:
# config.yaml
channels:
discord:
threadBindings:
enabled: true
syncMode: "blocking" # <-- ADD THIS FLAG
spawnSubagentSessions: true
session:
threadBindings:
enabled: true
オプションB:サブエージェントレーン作成を遅延させる
同期モードが高レイテンシ環境でタイムアウトを引き起こす場合、subagent_spawningフックを使用して遅延spawnパターンを実装します:
// hooks/subagent_spawning.ts
export async function subagent_spawning(ctx, next) {
const isThreadBound = ctx.spawnOptions?.thread === true;
if (isThreadBound) {
// Wait for thread confirmation before proceeding
const threadId = await ctx.agent.context.getDiscordThreadId();
if (!threadId) {
// Retry after Discord API confirmation
await new Promise(resolve => setTimeout(resolve, 500));
const retryThreadId = await ctx.agent.context.getDiscordThreadId();
if (!retryThreadId) {
return ctx.abort("thread_not_confirmed", {
message: "Discord thread not ready for subagent spawn"
});
}
}
}
return next();
}
オプションC:サブエージェントのスレッドバインディングを無効にする(回避策)
即時のspawnが必要で、スレッドコンテキストがサブエージェントにとって重要でない場合:
# config.yaml — Selective thread binding
channels:
discord:
threadBindings:
enabled: true
spawnSubagentSessions: true
subagentThreadBinding: false # <-- ADD THIS FLAG
session:
threadBindings:
enabled: true
🧪 検証
修正を適用した後、ランタイムログとDiscordスレッドアクティビティの両方を確認して、サブエージェントspawnが成功したことを検証します。
ステップ1:更新された設定でOpenClawエージェントを再起動します。
# Stop and restart the agent
> Ctrl+C
> openclaw start --config ./config.yaml
[INFO] OpenClaw v2026.2.26 initializing...
[INFO] Loading channel: discord
[INFO] Discord channel ready: guild_id=123456789
[INFO] Thread binding mode: synchronous (blocking)
ステップ2:スレッドにバインドされたサブエージェントspawnをトリガーします。
スレッドバインディングが有効なサブエージェントを起動するDiscordスレッド内でメッセージを送信します。
ステップ3:ログでレーン作成を確認します。
# Expected log output after fix
[INFO] subagent_spawning hook executing for agent=example-agent
[INFO] Creating Discord thread for subagent session
[INFO] Thread created: channel_id=987654321, thread_id=111222333
[INFO] lane created: session:agent:main:subagent:aaa111bbb222
[INFO] subagent session initialized: agent=example-agent
[INFO] Subagent message dispatched to thread_id=111222333
ステップ4:Discordスレッドにサブエジェージェントのレスポンスが含まれていることを確認します。
Discordスレッドに以下が含まれていることを確認します:
- spawnを確認するためのサブエージェントからの初期メッセージ
- スレッドトピックまたは最初のメッセージ内の
lane=session:agent:main:subagent:<uuid>識別子 - 対話機能(フォローアップメッセージに応答)
ステップ5:終了コードの検証。
# Verify no abort codes in recent logs
> openclaw logs --tail 100 | grep -E "(ABORT|no_active_run)"
# Expected: no output (no abort errors)
⚠️ よくある落とし穴
- フックの成功をspawnの成功と誤解する:
subagent_spawningフックがtrueを返すことは、spawnリクエストが有効であることを確認するだけで、サブエージェントセッションが初期化されたことを保証しません。常にレーン作成ログを検証してください。 - Discord権限の不足:
Create Public Threads、Send Messages in Threads、Manage Threadsがあっても、Read Message History権限がないとスレッド操作がサイレントに失敗する可能性があります。すべてのスレッド関連権限を確認してください。 - Windowsのパス区切り文字の問題:Windowsでは、スレッドバインディングパスで前方スラッシュを使用すると、正しく解決されない場合があります。ダブルエスケープされたパスまたは環境ネイティブ区切り文字を使用してください:
# Incorrect on Windows threadLogPath: C:\openclaw\threads\Correct
threadLogPath: C:\openclaw\threads\
or
threadLogPath: C:/openclaw/threads/
- ラピッドspawnとの競合状態:複数のサブエージェントが同じスレッドで同時にspawnされると、Discord APIが
rate_limit_exceededを返すことがあります。指数関数的バックオフを実装してください:async function spawnWithBackoff(fn, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await fn(); } catch (e) { if (e.code === "RATE_LIMITED" && i < maxRetries - 1) { await sleep(Math.pow(2, i) * 1000); } else throw e; } } } - スレッドバインディングモジュールのバージョン不一致:
syncMode: "blocking"フラグはOpenClawv2026.2.26+が必要です。バージョン互換性を確認してください:> openclaw --version OpenClaw v2026.2.26 (bc50708) # ✓ Compatible - コンテナ化された環境(Docker):DockerでOpenClawを実行する場合、Discordボットトークンを環境変数として渡し、ハードコードしないでください。非同期Discord API呼び出し中にボットプロセスがトークンにアクセスできないと、スレッドバインディングが失敗する可能性があります:
# docker-compose.yml environment: - DISCORD_BOT_TOKEN=${DISCORD_BOT_TOKEN} - OC_THREAD_BINDING_MODE=synchronous
🔗 関連するエラー
no_active_run— アクティブなランコンテキストが存在しない場合、セッション初期化が失敗します。 особенно非同期チャンネルの操作で、親ランコンテキストが完全に確立される前にサブエージェントをspawnする場合に発生します。thread_not_confirmed— Discordスレッド作成はAPIレベルでは成功しましたが、スレッドコンテキストはセッションサブシステムでまだ利用できません。スレッドバインディングのタイミング問題を示します。lane_creation_skipped— コンテキスト解決がnullまたは不完全なデータを返したため、セッションレーンが作成されませんでした。失敗チェーンではno_active_runの下流になります。rate_limit_exceeded— ラピッドスレッド作成時のDiscord APIレート制限。複数のスレッドにバインドされたサブエージェントが同時にリクエストされると、カスケードspawn失敗が発生する可能性があります。- 履歴参照: Issue #892 — 「DMチャンネルでのサブエージェントspawnがサイレントに失敗」(OpenClaw v2026.1.x)。セッション作成前にランコンテキストが継承されることを確認することで解決された、関連するコンテキスト伝播の問題。
- 履歴参照: Issue #1047 — 「Discordスレッドバインディングの遅延がメッセージ順序の問題を引き起こす」。現在のスレッドバイウンドspawn失敗の根底にある非同期Discord APIレイテンシの問題を文書化。