From c45c70f4693e12159e439cb199976aa7956c233d Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Sun, 26 Jul 2026 16:35:56 -0400 Subject: [PATCH] fix: normalize missing agent handoff edges --- .../agents/__tests__/run-summarization.test.ts | 18 ++++++++++++++++++ .../handoffPromptKeyCompatibility.spec.ts | 14 ++++++++++++++ .../agents/handoffPromptKeyCompatibility.ts | 5 +++-- packages/api/src/agents/run.ts | 2 +- 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/packages/api/src/agents/__tests__/run-summarization.test.ts b/packages/api/src/agents/__tests__/run-summarization.test.ts index 83ee5f6959..95fd6f19d9 100644 --- a/packages/api/src/agents/__tests__/run-summarization.test.ts +++ b/packages/api/src/agents/__tests__/run-summarization.test.ts @@ -465,6 +465,24 @@ describe('summarizationConfig field passthrough', () => { // Suite 5: Multi-agent + per-agent overrides // --------------------------------------------------------------------------- describe('multi-agent + per-agent overrides', () => { + it('normalizes missing persisted edges before creating the SDK graph', async () => { + await createRun({ + agents: [makeAgent({ id: 'agent_1' }), makeAgent({ id: 'agent_2' })] as never, + signal: new AbortController().signal, + streaming: true, + streamUsage: true, + }); + + const createMock = Run.create as jest.Mock; + const runConfig = createMock.mock.calls[0][0] as { + graphConfig: { type: string; edges: unknown[] }; + }; + expect(runConfig.graphConfig).toMatchObject({ + type: 'multi-agent', + edges: [], + }); + }); + it('different agents get different effectiveMaxContextTokens', async () => { const agents = await callAndCapture({ agents: [ diff --git a/packages/api/src/agents/handoffPromptKeyCompatibility.spec.ts b/packages/api/src/agents/handoffPromptKeyCompatibility.spec.ts index 77c6d5cbfa..0593b3bad4 100644 --- a/packages/api/src/agents/handoffPromptKeyCompatibility.spec.ts +++ b/packages/api/src/agents/handoffPromptKeyCompatibility.spec.ts @@ -73,6 +73,20 @@ const createSdkProcess = (): jest.MockedFunction => }); describe('applyCustomHandoffPromptKeyCompatibility', () => { + it('leaves multi-agent graphs without edges unpatched', () => { + const sdkProcess = createSdkProcess(); + const { run, graph } = createRun(sdkProcess); + const originalProcess = graph.processHandoffReception; + // Persisted agents can predate `edges`, even though the current SDK type requires it. + const graphConfig = { + type: 'multi-agent', + agents: [], + } as unknown as RunConfig['graphConfig']; + + expect(() => applyCustomHandoffPromptKeyCompatibility(run, graphConfig)).not.toThrow(); + expect(graph.processHandoffReception).toBe(originalProcess); + }); + it('recovers a custom prompt key for scalar and array handoff endpoints', () => { const sdkProcess = createSdkProcess(); const { run, graph } = createRun(sdkProcess); diff --git a/packages/api/src/agents/handoffPromptKeyCompatibility.ts b/packages/api/src/agents/handoffPromptKeyCompatibility.ts index f4b9ab30d7..f954fa8746 100644 --- a/packages/api/src/agents/handoffPromptKeyCompatibility.ts +++ b/packages/api/src/agents/handoffPromptKeyCompatibility.ts @@ -121,7 +121,8 @@ export function applyCustomHandoffPromptKeyCompatibility( return; } - const hasCustomPromptKey = graphConfig.edges.some((edge) => { + const edges = graphConfig.edges ?? []; + const hasCustomPromptKey = edges.some((edge) => { const promptKey = edge.promptKey; return ( edge.edgeType !== 'direct' && @@ -152,7 +153,7 @@ export function applyCustomHandoffPromptKeyCompatibility( return result; } - const labels = getCustomPromptLabels(graphConfig.edges, agentId); + const labels = getCustomPromptLabels(edges, agentId); if (labels.length === 0) { return result; } diff --git a/packages/api/src/agents/run.ts b/packages/api/src/agents/run.ts index 258b612ccb..1ffe249b2d 100644 --- a/packages/api/src/agents/run.ts +++ b/packages/api/src/agents/run.ts @@ -1362,7 +1362,7 @@ export async function createRun({ const graphConfig: RunConfig['graphConfig'] = { signal, agents: agentInputs, - edges: agents[0].edges, + edges: agents[0].edges ?? [], }; if (agentInputs.length > 1 || ((graphConfig as MultiAgentGraphConfig).edges?.length ?? 0) > 0) {