@@ -10,6 +10,7 @@ import {
1010 isSubagentSessionKey ,
1111 normalizeAgentId ,
1212 resolveAgentIdFromSessionKey ,
13+ toAgentStoreSessionKey ,
1314} from "../../routing/session-key.js" ;
1415import { annotateInterSessionPromptText } from "../../sessions/input-provenance.js" ;
1516import { SESSION_LABEL_MAX_LENGTH } from "../../sessions/session-label.js" ;
@@ -18,6 +19,7 @@ import {
1819 type GatewayMessageChannel ,
1920 INTERNAL_MESSAGE_CHANNEL ,
2021} from "../../utils/message-channel.js" ;
22+ import { listAgentIds } from "../agent-scope.js" ;
2123import { resolveNestedAgentLaneForSession } from "../lanes.js" ;
2224import {
2325 type AgentWaitResult ,
@@ -53,6 +55,78 @@ const SessionsSendToolSchema = Type.Object({
5355type GatewayCaller = typeof callGateway ;
5456const SESSIONS_SEND_REPLY_HISTORY_LIMIT = 50 ;
5557
58+ function resolveConfiguredAgentMainSessionKey ( params : {
59+ cfg : OpenClawConfig ;
60+ agentId : string ;
61+ mainKey : string ;
62+ } ) : string | undefined {
63+ const agentId = normalizeAgentId ( params . agentId ) ;
64+ if ( ! listAgentIds ( params . cfg ) . includes ( agentId ) ) {
65+ return undefined ;
66+ }
67+ return toAgentStoreSessionKey ( {
68+ agentId,
69+ requestKey : "main" ,
70+ mainKey : params . mainKey ,
71+ } ) ;
72+ }
73+
74+ function isConfiguredAgentMainSessionKey ( params : {
75+ cfg : OpenClawConfig ;
76+ sessionKey : string ;
77+ mainKey : string ;
78+ } ) : boolean {
79+ const agentId = resolveAgentIdFromSessionKey ( params . sessionKey ) ;
80+ return (
81+ params . sessionKey ===
82+ resolveConfiguredAgentMainSessionKey ( {
83+ cfg : params . cfg ,
84+ agentId,
85+ mainKey : params . mainKey ,
86+ } )
87+ ) ;
88+ }
89+
90+ async function ensureConfiguredAgentMainSession ( params : {
91+ cfg : OpenClawConfig ;
92+ callGateway : GatewayCaller ;
93+ sessionKey : string ;
94+ mainKey : string ;
95+ } ) : Promise < { ok : true } | { ok : false ; error : string } > {
96+ if (
97+ ! isConfiguredAgentMainSessionKey ( {
98+ cfg : params . cfg ,
99+ sessionKey : params . sessionKey ,
100+ mainKey : params . mainKey ,
101+ } )
102+ ) {
103+ return { ok : true } ;
104+ }
105+
106+ try {
107+ await params . callGateway ( {
108+ method : "sessions.resolve" ,
109+ params : { key : params . sessionKey } ,
110+ timeoutMs : 10_000 ,
111+ } ) ;
112+ return { ok : true } ;
113+ } catch {
114+ try {
115+ await params . callGateway ( {
116+ method : "sessions.create" ,
117+ params : {
118+ key : params . sessionKey ,
119+ agentId : resolveAgentIdFromSessionKey ( params . sessionKey ) ,
120+ } ,
121+ timeoutMs : 10_000 ,
122+ } ) ;
123+ return { ok : true } ;
124+ } catch ( err ) {
125+ return { ok : false , error : formatErrorMessage ( err ) } ;
126+ }
127+ }
128+ }
129+
56130type SessionsSendRouteEntry = Pick < SessionEntry , "acp" | "parentSessionKey" | "spawnedBy" > ;
57131
58132function isRequesterParentOfNativeSubagentSession ( params : {
@@ -145,6 +219,21 @@ export function createSessionsSendTool(opts?: {
145219 }
146220
147221 let sessionKey = sessionKeyParam ;
222+ if ( ! sessionKey && ! labelParam && labelAgentIdParam ) {
223+ const agentMainKey = resolveConfiguredAgentMainSessionKey ( {
224+ cfg,
225+ agentId : labelAgentIdParam ,
226+ mainKey,
227+ } ) ;
228+ if ( ! agentMainKey ) {
229+ return jsonResult ( {
230+ runId : crypto . randomUUID ( ) ,
231+ status : "error" ,
232+ error : `agent not found: ${ labelAgentIdParam } ` ,
233+ } ) ;
234+ }
235+ sessionKey = agentMainKey ;
236+ }
148237 if ( ! sessionKey && labelParam ) {
149238 const requesterAgentId = resolveAgentIdFromSessionKey ( effectiveRequesterKey ) ;
150239 const requestedAgentId = labelAgentIdParam
@@ -294,6 +383,21 @@ export function createSessionsSendTool(opts?: {
294383 } ) ;
295384 }
296385
386+ const ensuredSession = await ensureConfiguredAgentMainSession ( {
387+ cfg,
388+ callGateway : gatewayCall ,
389+ sessionKey : resolvedKey ,
390+ mainKey,
391+ } ) ;
392+ if ( ! ensuredSession . ok ) {
393+ return jsonResult ( {
394+ runId : crypto . randomUUID ( ) ,
395+ status : "error" ,
396+ error : ensuredSession . error ,
397+ sessionKey : displayKey ,
398+ } ) ;
399+ }
400+
297401 // Capture the pre-run assistant snapshot before starting the nested run.
298402 // Fast in-process test doubles and short-circuit agent paths can finish
299403 // before we reach the post-run read, which would otherwise make the new
0 commit comments