fix: preserve subagent thread routing (#1241)

Thanks @gnarco.

Co-authored-by: gnarco <gnarco@users.noreply.github.com>
This commit is contained in:
Peter Steinberger
2026-01-20 17:22:07 +00:00
parent ae1c6f4313
commit 02ca148583
32 changed files with 195 additions and 32 deletions

View File

@@ -27,6 +27,10 @@ export function createClawdbotTools(options?: {
agentSessionKey?: string;
agentChannel?: GatewayMessageChannel;
agentAccountId?: string;
/** Delivery target (e.g. telegram:group:123:topic:456) for topic/thread routing. */
agentTo?: string;
/** Thread/topic identifier for routing replies to the originating thread. */
agentThreadId?: string | number;
agentDir?: string;
sandboxRoot?: string;
workspaceDir?: string;
@@ -108,6 +112,8 @@ export function createClawdbotTools(options?: {
agentSessionKey: options?.agentSessionKey,
agentChannel: options?.agentChannel,
agentAccountId: options?.agentAccountId,
agentTo: options?.agentTo,
agentThreadId: options?.agentThreadId,
sandboxed: options?.sandboxed,
}),
createSessionStatusTool({

View File

@@ -208,6 +208,8 @@ export async function runEmbeddedPiAgent(
messageChannel: params.messageChannel,
messageProvider: params.messageProvider,
agentAccountId: params.agentAccountId,
messageTo: params.messageTo,
messageThreadId: params.messageThreadId,
currentChannelId: params.currentChannelId,
currentThreadTs: params.currentThreadTs,
replyToMode: params.replyToMode,

View File

@@ -148,6 +148,8 @@ export async function runEmbeddedAttempt(
sandbox,
messageProvider: params.messageChannel ?? params.messageProvider,
agentAccountId: params.agentAccountId,
messageTo: params.messageTo,
messageThreadId: params.messageThreadId,
sessionKey: params.sessionKey ?? params.sessionId,
agentDir,
workspaceDir: effectiveWorkspace,

View File

@@ -23,6 +23,10 @@ export type RunEmbeddedPiAgentParams = {
messageChannel?: string;
messageProvider?: string;
agentAccountId?: string;
/** Delivery target (e.g. telegram:group:123:topic:456) for topic/thread routing. */
messageTo?: string;
/** Thread/topic identifier for routing replies to the originating thread. */
messageThreadId?: string | number;
/** Current channel ID for auto-threading (Slack). */
currentChannelId?: string;
/** Current thread timestamp for auto-threading (Slack). */

View File

@@ -21,6 +21,8 @@ export type EmbeddedRunAttemptParams = {
messageChannel?: string;
messageProvider?: string;
agentAccountId?: string;
messageTo?: string;
messageThreadId?: string | number;
currentChannelId?: string;
currentThreadTs?: string;
replyToMode?: "off" | "first" | "all";

View File

@@ -102,6 +102,8 @@ export function createClawdbotCodingTools(options?: {
exec?: ExecToolDefaults & ProcessToolDefaults;
messageProvider?: string;
agentAccountId?: string;
messageTo?: string;
messageThreadId?: string | number;
sandbox?: SandboxContext | null;
sessionKey?: string;
agentDir?: string;
@@ -265,6 +267,8 @@ export function createClawdbotCodingTools(options?: {
agentSessionKey: options?.sessionKey,
agentChannel: resolveGatewayMessageChannel(options?.messageProvider),
agentAccountId: options?.agentAccountId,
agentTo: options?.messageTo,
agentThreadId: options?.messageThreadId,
agentDir: options?.agentDir,
sandboxRoot,
workspaceDir: options?.workspaceDir,

View File

@@ -98,6 +98,8 @@ function resolveAnnounceOrigin(
async function sendAnnounce(item: AnnounceQueueItem) {
const origin = item.origin;
const threadId =
origin?.threadId != null && origin.threadId !== "" ? String(origin.threadId) : undefined;
await callGateway({
method: "agent",
params: {
@@ -106,6 +108,7 @@ async function sendAnnounce(item: AnnounceQueueItem) {
channel: origin?.channel,
accountId: origin?.accountId,
to: origin?.to,
threadId,
deliver: true,
idempotencyKey: crypto.randomUUID(),
},
@@ -424,6 +427,11 @@ export async function runSubagentAnnounceFlow(params: {
deliver: true,
channel: directOrigin?.channel,
accountId: directOrigin?.accountId,
to: directOrigin?.to,
threadId:
directOrigin?.threadId != null && directOrigin.threadId !== ""
? String(directOrigin.threadId)
: undefined,
idempotencyKey: crypto.randomUUID(),
},
expectFinal: true,

View File

@@ -61,6 +61,8 @@ export function createSessionsSpawnTool(opts?: {
agentSessionKey?: string;
agentChannel?: GatewayMessageChannel;
agentAccountId?: string;
agentTo?: string;
agentThreadId?: string | number;
sandboxed?: boolean;
}): AnyAgentTool {
return {
@@ -83,6 +85,8 @@ export function createSessionsSpawnTool(opts?: {
const requesterOrigin = normalizeDeliveryContext({
channel: opts?.agentChannel,
accountId: opts?.agentAccountId,
to: opts?.agentTo,
threadId: opts?.agentThreadId,
});
const runTimeoutSeconds = (() => {
const explicit =