@@ -388,6 +388,86 @@ describe("tool.task", () => {
388388 } ) ,
389389 )
390390
391+ it . instance ( "prevents subagents from launching subagents by default" , ( ) =>
392+ Effect . gen ( function * ( ) {
393+ const sessions = yield * Session . Service
394+ const { chat, assistant } = yield * seed ( )
395+ const child = yield * sessions . create ( { parentID : chat . id , title : "child" } )
396+ const nestedAssistant = yield * sessions . updateMessage ( {
397+ ...assistant ,
398+ id : MessageID . ascending ( ) ,
399+ parentID : MessageID . ascending ( ) ,
400+ sessionID : child . id ,
401+ } )
402+ const tool = yield * TaskTool
403+ const def = yield * tool . init ( )
404+ let asked = false
405+
406+ const exit = yield * def
407+ . execute (
408+ {
409+ description : "inspect bug" ,
410+ prompt : "look into the cache key path" ,
411+ subagent_type : "general" ,
412+ } ,
413+ {
414+ sessionID : child . id ,
415+ messageID : nestedAssistant . id ,
416+ agent : "general" ,
417+ abort : new AbortController ( ) . signal ,
418+ extra : { promptOps : stubOps ( ) } ,
419+ messages : [ ] ,
420+ metadata : ( ) => Effect . void ,
421+ ask : ( ) => Effect . sync ( ( ) => ( asked = true ) ) ,
422+ } ,
423+ )
424+ . pipe ( Effect . exit )
425+
426+ expect ( Exit . isFailure ( exit ) ) . toBe ( true )
427+ expect ( asked ) . toBe ( false )
428+ expect ( yield * sessions . children ( child . id ) ) . toHaveLength ( 0 )
429+ } ) ,
430+ )
431+
432+ it . instance (
433+ "allows nested subagents up to the configured depth" ,
434+ ( ) =>
435+ Effect . gen ( function * ( ) {
436+ const sessions = yield * Session . Service
437+ const { chat, assistant } = yield * seed ( )
438+ const child = yield * sessions . create ( { parentID : chat . id , title : "child" } )
439+ const nestedAssistant = yield * sessions . updateMessage ( {
440+ ...assistant ,
441+ id : MessageID . ascending ( ) ,
442+ parentID : MessageID . ascending ( ) ,
443+ sessionID : child . id ,
444+ } )
445+ const tool = yield * TaskTool
446+ const def = yield * tool . init ( )
447+
448+ const result = yield * def . execute (
449+ {
450+ description : "inspect bug" ,
451+ prompt : "look into the cache key path" ,
452+ subagent_type : "general" ,
453+ } ,
454+ {
455+ sessionID : child . id ,
456+ messageID : nestedAssistant . id ,
457+ agent : "general" ,
458+ abort : new AbortController ( ) . signal ,
459+ extra : { promptOps : stubOps ( ) } ,
460+ messages : [ ] ,
461+ metadata : ( ) => Effect . void ,
462+ ask : ( ) => Effect . void ,
463+ } ,
464+ )
465+
466+ expect ( ( yield * sessions . get ( result . metadata . sessionId ) ) . parentID ) . toBe ( child . id )
467+ } ) ,
468+ { config : { subagent_depth : 2 } } ,
469+ )
470+
391471 it . instance (
392472 "execute shapes child permissions for task, todowrite, and primary tools" ,
393473 ( ) =>
0 commit comments