🪆 fix: Preserve Nested Subagent Delegation (#14392)

Co-authored-by: Sien Nuyens <sien.nuyens@ixor.be>
This commit is contained in:
Danny Avila 2026-07-22 09:30:53 -04:00 committed by GitHub
parent af7b2761eb
commit 4c0ac8844c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 1 deletions

View file

@ -81,7 +81,7 @@ jest.mock('~/agents/checkpointer', () => ({
getAgentCheckpointer: jest.fn().mockResolvedValue({}),
}));
import { Run } from '@librechat/agents';
import { Run, buildChildInputs } from '@librechat/agents';
/** Minimal RunAgent factory */
function makeAgent(
@ -1020,6 +1020,36 @@ describe('subagentConfigs', () => {
expect(configs[0].self).toBeUndefined();
});
it('preserves explicit nested subagents across the SDK child graph boundary', async () => {
const grandchild = makeAgent({ id: 'agent_grandchild', name: 'Grandchild' });
const child = makeAgent({
id: 'agent_child',
name: 'Child',
subagents: { enabled: true, allowSelf: false, agent_ids: ['agent_grandchild'] },
subagentAgentConfigs: [grandchild],
});
const agents = await callAndCapture({
agents: [
makeAgent({
subagents: { enabled: true, allowSelf: false, agent_ids: ['agent_child'] },
subagentAgentConfigs: [child],
}),
],
});
expect(agents[0].maxSubagentDepth).toBe(MAX_SUBAGENT_DEPTH);
const childConfig = (agents[0].subagentConfigs as Parameters<typeof buildChildInputs>[0][])[0];
expect(childConfig.allowNested).toBe(true);
const childInputs = buildChildInputs(childConfig, 'agent_child', MAX_SUBAGENT_DEPTH);
expect(childInputs.maxSubagentDepth).toBe(MAX_SUBAGENT_DEPTH - 1);
expect(childInputs.subagentConfigs).toHaveLength(1);
expect(childInputs.subagentConfigs?.[0]).toMatchObject({
type: 'agent_grandchild',
allowNested: true,
});
});
it('combines self-spawn and explicit subagents when both enabled', async () => {
const child = makeAgent({ id: 'agent_child', name: 'Helper' });
const agents = await callAndCapture({

View file

@ -991,6 +991,8 @@ function buildSubagentConfigs(
child.description ??
`Delegate a subtask to the ${child.name ?? child.id} agent in an isolated context.`,
agentInputs: childInputs,
/** Preserve the child's resolved subagent configs when the SDK builds its isolated graph. */
allowNested: true,
/** Honor each child agent's own resolved recursion limit. */
maxTurns: resolveSubagentMaxTurns(agentsEConfig, child),
});
@ -1350,6 +1352,8 @@ export async function createRun({
);
if (subagentConfigs.length > 0) {
agentInput.subagentConfigs = subagentConfigs;
/** Seed the SDK countdown that bounds nested delegation across isolated child graphs. */
agentInput.maxSubagentDepth = MAX_SUBAGENT_DEPTH;
}
agentInputs.push(agentInput);
}