← Back to PRs

#22205: fix: expose resolvedTo as currentChannelId so sub-agents inherit thread routing

by Galygious open 2026-02-20 21:52 View on GitHub →
gateway size: XS
## Summary When a sub-agent is spawned via `sessions_spawn`, the gateway's `agent` handler already receives and resolves `to` and `threadId` from the requester session context. However, `resolvedTo` was never mapped to `runContext.currentChannelId`, leaving the message tool's zero-param target inference with nothing to fall back on. **Symptom:** Sub-agents calling `message` with `action=send` and no explicit `to`, `channel`, or `threadId` would fail with `Action send requires a target` — even though the parent session had a fully-resolved delivery target. ## Root Cause `buildThreadingToolContext()` (in `agent-runner-utils.ts`) sets `currentChannelId = sessionCtx.To?.trim()` for the main session. For sub-agents launched via `sessions_spawn`, `sessionCtx.To` is empty because the sub-agent session has no inbound message context — it only has the `runContext` passed from the gateway handler. `resolvedTo` was present in that handler but was never forwarded into `runContext.currentChannelId`. ## Fix One line added to `src/gateway/server-methods/agent.ts`: ```ts // Before runContext: { messageChannel: resolvedChannel, // ... currentThreadTs: resolvedThreadId != null ? String(resolvedThreadId) : undefined, }, // After runContext: { messageChannel: resolvedChannel, // ... currentThreadTs: resolvedThreadId != null ? String(resolvedThreadId) : undefined, currentChannelId: resolvedTo || undefined, }, ``` This flows through: `agentCommand` → `runEmbeddedPiAgent` → `createOpenClawCodingTools` → `createMessageTool` → tool context inference in `message-action-runner.ts`. ## Verification Tested end-to-end on Discord thread sessions: - Sub-agent spawned with prompt `Count to 10. Send each number as a separate message.` — no thread info passed - All 10 messages delivered to the correct Discord thread (`channel:1474502983390593189`) - Zero explicit `to`, `channel`, or `threadId` params used by the sub-agent Explicit routing params still take full precedence when provided. This change only affects the fallback inference path. ## Drawbacks / Considerations - Sub-agents now silently inherit the parent's delivery target. Previously they'd error if `to` was omitted; now they succeed and send to the parent thread. This is almost always desirable but worth noting as a behavior change for sub-agents intended to run silently. - Cron/hook-spawned sub-agents will inherit whatever `resolvedTo` the triggering context resolves to, which may be an unrelated channel. Same mitigation as always: pass an explicit `to` to override. ## AI-Submitted PR > ⚠️ This PR was identified, implemented, and submitted by **Cognis**, an AI agent running on OpenClaw (user: Galygious). It has been manually end-to-end tested as described above but has **not** been run through the automated test suite. Please review accordingly. > > A regression test covering sub-agent message tool target inference (verifying `currentChannelId` is populated from `resolvedTo` in the `agent` handler) would be a valuable addition.

Most Similar PRs