@openai/agents-core 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/runState.mjs CHANGED
@@ -40,8 +40,10 @@ import { getSerializedApplyPatchToolPlaceholder, getSerializedComputerToolPlaceh
40
40
  * aliasing to serialized run state payloads.
41
41
  * - 1.9: Adds optional sandbox session persistence with a versioned session-state
42
42
  * envelope for sandbox-agent resume.
43
+ * - 1.10: Adds optional stable agent identity keys so duplicate-name agent graphs can
44
+ * serialize and resume without ambiguous name resolution.
43
45
  */
44
- export const CURRENT_SCHEMA_VERSION = '1.9';
46
+ export const CURRENT_SCHEMA_VERSION = '1.10';
45
47
  const SUPPORTED_SCHEMA_VERSIONS = [
46
48
  '1.0',
47
49
  '1.1',
@@ -52,11 +54,13 @@ const SUPPORTED_SCHEMA_VERSIONS = [
52
54
  '1.6',
53
55
  '1.7',
54
56
  '1.8',
57
+ '1.9',
55
58
  CURRENT_SCHEMA_VERSION,
56
59
  ];
57
60
  const $schemaVersion = z.enum(SUPPORTED_SCHEMA_VERSIONS);
58
61
  const serializedAgentSchema = z.object({
59
62
  name: z.string(),
63
+ identity: z.string().optional(),
60
64
  });
61
65
  const serializedSpanBase = z.object({
62
66
  object: z.literal('trace.span'),
@@ -470,10 +474,10 @@ export class RunState {
470
474
  */
471
475
  _trace = null;
472
476
  /**
473
- * Runtime-only tool_search-loaded tools, scoped by agent name and preserved across turns for
477
+ * Runtime-only tool_search-loaded tools, scoped by agent object and preserved across turns for
474
478
  * the lifetime of this in-memory run.
475
479
  */
476
- _toolSearchRuntimeToolsByAgentName = new Map();
480
+ _toolSearchRuntimeToolsByAgent = new Map();
477
481
  /**
478
482
  * Persisted sandbox session metadata for sandbox-agent resume.
479
483
  */
@@ -517,20 +521,20 @@ export class RunState {
517
521
  setCurrentAgentSpan(span) {
518
522
  this._currentAgentSpan = span;
519
523
  }
520
- getOrCreateToolSearchRuntimeToolState(agentName) {
521
- let state = this._toolSearchRuntimeToolsByAgentName.get(agentName);
524
+ getOrCreateToolSearchRuntimeToolState(agent) {
525
+ let state = this._toolSearchRuntimeToolsByAgent.get(agent);
522
526
  if (!state) {
523
527
  state = {
524
528
  anonymousEntries: [],
525
529
  keyedEntries: new Map(),
526
530
  nextOrder: 0,
527
531
  };
528
- this._toolSearchRuntimeToolsByAgentName.set(agentName, state);
532
+ this._toolSearchRuntimeToolsByAgent.set(agent, state);
529
533
  }
530
534
  return state;
531
535
  }
532
536
  recordToolSearchRuntimeTools(agent, toolSearchOutput, tools) {
533
- const runtimeState = this.getOrCreateToolSearchRuntimeToolState(agent.name);
537
+ const runtimeState = this.getOrCreateToolSearchRuntimeToolState(agent);
534
538
  const entry = {
535
539
  order: runtimeState.nextOrder++,
536
540
  tools,
@@ -543,7 +547,7 @@ export class RunState {
543
547
  runtimeState.anonymousEntries.push(entry);
544
548
  }
545
549
  getToolSearchRuntimeTools(agent) {
546
- const runtimeState = this._toolSearchRuntimeToolsByAgentName.get(agent.name);
550
+ const runtimeState = this._toolSearchRuntimeToolsByAgent.get(agent);
547
551
  if (!runtimeState) {
548
552
  return [];
549
553
  }
@@ -680,15 +684,13 @@ export class RunState {
680
684
  * rehydrate in a separate process that lacks the original environment variables).
681
685
  */
682
686
  toJSON(options = {}) {
683
- buildAgentMap(this.#startingAgent);
687
+ const agentIdentity = buildAgentIdentityMap(this.#startingAgent);
684
688
  const includeTracingApiKey = options.includeTracingApiKey === true;
685
689
  const contextJson = this._context.toJSON();
686
690
  const output = {
687
691
  $schemaVersion: CURRENT_SCHEMA_VERSION,
688
692
  currentTurn: this._currentTurn,
689
- currentAgent: {
690
- name: this._currentAgent.name,
691
- },
693
+ currentAgent: serializeAgentReference(this._currentAgent, agentIdentity.byAgent),
692
694
  originalInput: this._originalInput,
693
695
  modelResponses: this._modelResponses.map((response) => {
694
696
  return {
@@ -720,7 +722,9 @@ export class RunState {
720
722
  };
721
723
  }),
722
724
  context: contextJson,
723
- toolUseTracker: this._toolUseTracker.toJSON(),
725
+ toolUseTracker: this._toolUseTracker.toJSON({
726
+ agentIdentityKeys: agentIdentity.byAgent,
727
+ }),
724
728
  maxTurns: this._maxTurns,
725
729
  currentAgentSpan: this._currentAgentSpan?.toJSON(),
726
730
  noActiveAgentRun: this._noActiveAgentRun,
@@ -728,16 +732,18 @@ export class RunState {
728
732
  inputGuardrailResults: this._inputGuardrailResults,
729
733
  outputGuardrailResults: this._outputGuardrailResults.map((r) => ({
730
734
  ...r,
731
- agent: r.agent.toJSON(),
735
+ agent: serializeAgentReference(r.agent, agentIdentity.byAgent),
732
736
  })),
733
737
  toolInputGuardrailResults: this._toolInputGuardrailResults,
734
738
  toolOutputGuardrailResults: this._toolOutputGuardrailResults,
735
- currentStep: this._currentStep,
739
+ currentStep: serializeCurrentStep(this._currentStep, agentIdentity.byAgent),
736
740
  lastModelResponse: this._lastTurnResponse,
737
- generatedItems: this._generatedItems.map((item) => item.toJSON()),
741
+ generatedItems: this._generatedItems.map((item) => serializeRunItem(item, agentIdentity.byAgent)),
738
742
  pendingAgentToolRuns: Object.fromEntries(this._pendingAgentToolRuns.entries()),
739
743
  currentTurnPersistedItemCount: this._currentTurnPersistedItemCount,
740
- lastProcessedResponse: this._lastProcessedResponse,
744
+ lastProcessedResponse: this._lastProcessedResponse
745
+ ? serializeProcessedResponse(this._lastProcessedResponse, agentIdentity.byAgent)
746
+ : undefined,
741
747
  conversationId: this._conversationId,
742
748
  previousResponseId: this._previousResponseId,
743
749
  reasoningItemIdPolicy: this._reasoningItemIdPolicy,
@@ -797,7 +803,9 @@ async function buildRunStateFromString(initialAgent, str, options = {}) {
797
803
  return buildRunStateFromJson(initialAgent, stateJson, options);
798
804
  }
799
805
  function assertSchemaVersionSupportsToolSearch(schemaVersion, stateJson) {
800
- if (schemaVersion === '1.8' || schemaVersion === '1.9') {
806
+ if (schemaVersion === '1.8' ||
807
+ schemaVersion === '1.9' ||
808
+ schemaVersion === CURRENT_SCHEMA_VERSION) {
801
809
  return;
802
810
  }
803
811
  if (!containsSerializedToolSearchState(stateJson)) {
@@ -805,6 +813,9 @@ function assertSchemaVersionSupportsToolSearch(schemaVersion, stateJson) {
805
813
  }
806
814
  throw new UserError(`Run state schema version ${schemaVersion} does not support tool_search items. Please reserialize the run state with schema ${CURRENT_SCHEMA_VERSION}.`);
807
815
  }
816
+ function schemaVersionSupportsAgentIdentity(schemaVersion) {
817
+ return schemaVersion === CURRENT_SCHEMA_VERSION;
818
+ }
808
819
  function containsSerializedToolSearchState(stateJson) {
809
820
  return (containsToolSearchProtocolItems(stateJson.originalInput) ||
810
821
  containsToolSearchInModelResponses(stateJson.modelResponses) ||
@@ -908,17 +919,17 @@ function assertRuntimeToolKeysMatch(args) {
908
919
  throw new UserError(`RunState cannot resume custom client tool_search call ${callId} for agent ${agent.name} because the registered execute callback returned runtime tools [${formatRuntimeToolKeys(actualRuntimeToolKeys)}] but the serialized state expects [${formatRuntimeToolKeys(expectedRuntimeToolKeys)}].`);
909
920
  }
910
921
  async function getConfiguredAgentTools(args) {
911
- const { agent, context, configuredToolsByAgentName } = args;
912
- const existing = configuredToolsByAgentName.get(agent.name);
922
+ const { agent, context, configuredToolsByAgent } = args;
923
+ const existing = configuredToolsByAgent.get(agent);
913
924
  if (existing) {
914
925
  return existing;
915
926
  }
916
927
  const configuredTools = (await agent.getAllTools(context));
917
- configuredToolsByAgentName.set(agent.name, configuredTools);
928
+ configuredToolsByAgent.set(agent, configuredTools);
918
929
  return configuredTools;
919
930
  }
920
931
  async function rehydrateToolSearchRuntimeTools(state) {
921
- const configuredToolsByAgentName = new Map();
932
+ const configuredToolsByAgent = new Map();
922
933
  const pendingToolSearchCalls = new Map();
923
934
  for (const item of state._generatedItems) {
924
935
  if (item instanceof RunToolSearchCallItem) {
@@ -926,10 +937,14 @@ async function rehydrateToolSearchRuntimeTools(state) {
926
937
  continue;
927
938
  }
928
939
  const callId = resolveToolSearchCallId(item.rawItem);
929
- pendingToolSearchCalls.set(`${item.agent.name}:${callId}`, {
940
+ const agent = item.agent;
941
+ const pendingCallsById = pendingToolSearchCalls.get(agent) ??
942
+ new Map();
943
+ pendingCallsById.set(callId, {
930
944
  agent: item.agent,
931
945
  toolSearchCall: item.rawItem,
932
946
  });
947
+ pendingToolSearchCalls.set(agent, pendingCallsById);
933
948
  continue;
934
949
  }
935
950
  if (!(item instanceof RunToolSearchOutputItem)) {
@@ -941,7 +956,7 @@ async function rehydrateToolSearchRuntimeTools(state) {
941
956
  const configuredTools = await getConfiguredAgentTools({
942
957
  agent: item.agent,
943
958
  context: state._context,
944
- configuredToolsByAgentName,
959
+ configuredToolsByAgent,
945
960
  });
946
961
  const configuredToolKeys = getRuntimeToolKeys(configuredTools, {
947
962
  allowUnsupported: true,
@@ -951,7 +966,9 @@ async function rehydrateToolSearchRuntimeTools(state) {
951
966
  continue;
952
967
  }
953
968
  const callId = resolveToolSearchCallId(item.rawItem);
954
- const pendingCall = pendingToolSearchCalls.get(`${item.agent.name}:${callId}`);
969
+ const pendingCall = pendingToolSearchCalls
970
+ .get(item.agent)
971
+ ?.get(callId);
955
972
  if (!pendingCall) {
956
973
  throw new UserError(`RunState cannot resume custom client tool_search output ${callId} for agent ${item.agent.name} because the serialized state is missing the matching tool_search call item.`);
957
974
  }
@@ -994,7 +1011,9 @@ async function rehydrateToolSearchRuntimeTools(state) {
994
1011
  }
995
1012
  }
996
1013
  async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
997
- const agentMap = buildAgentMap(initialAgent);
1014
+ const agentMap = schemaVersionSupportsAgentIdentity(stateJson.$schemaVersion)
1015
+ ? buildAgentIdentityMap(initialAgent).byIdentity
1016
+ : buildAgentMap(initialAgent);
998
1017
  const contextOverride = options.contextOverride;
999
1018
  const contextStrategy = options.contextStrategy ?? 'merge';
1000
1019
  //
@@ -1019,10 +1038,7 @@ async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
1019
1038
  //
1020
1039
  // Find the current agent from the initial agent
1021
1040
  //
1022
- const currentAgent = agentMap.get(stateJson.currentAgent.name);
1023
- if (!currentAgent) {
1024
- throw new UserError(`Agent ${stateJson.currentAgent.name} not found`);
1025
- }
1041
+ const currentAgent = resolveSerializedAgent(stateJson.currentAgent, agentMap);
1026
1042
  const state = new RunState(context, '', initialAgent, stateJson.maxTurns);
1027
1043
  state._currentAgent = currentAgent;
1028
1044
  state._currentTurn = stateJson.currentTurn;
@@ -1033,7 +1049,13 @@ async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
1033
1049
  // rebuild tool use tracker
1034
1050
  state._toolUseTracker = new AgentToolUseTracker();
1035
1051
  for (const [agentName, toolNames] of Object.entries(stateJson.toolUseTracker)) {
1036
- state._toolUseTracker.addToolUse(agentMap.get(agentName), toolNames, { allowEmpty: true });
1052
+ const agent = agentMap.get(agentName);
1053
+ if (!agent) {
1054
+ throw new UserError(`Agent ${agentName} not found`);
1055
+ }
1056
+ state._toolUseTracker.addToolUse(agent, toolNames, {
1057
+ allowEmpty: true,
1058
+ });
1037
1059
  }
1038
1060
  state._pendingAgentToolRuns = new Map(Object.entries(stateJson.pendingAgentToolRuns ?? {}));
1039
1061
  // rebuild current agent span
@@ -1056,7 +1078,7 @@ async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
1056
1078
  stateJson.inputGuardrailResults;
1057
1079
  state._outputGuardrailResults = stateJson.outputGuardrailResults.map((r) => ({
1058
1080
  ...r,
1059
- agent: agentMap.get(r.agent.name),
1081
+ agent: resolveSerializedAgent(r.agent, agentMap),
1060
1082
  }));
1061
1083
  state._toolInputGuardrailResults =
1062
1084
  stateJson.toolInputGuardrailResults;
@@ -1079,7 +1101,7 @@ async function buildRunStateFromJson(initialAgent, stateJson, options = {}) {
1079
1101
  if (stateJson.currentStep?.type === 'next_step_handoff') {
1080
1102
  state._currentStep = {
1081
1103
  type: 'next_step_handoff',
1082
- newAgent: agentMap.get(stateJson.currentStep.newAgent.name),
1104
+ newAgent: resolveSerializedAgent(stateJson.currentStep.newAgent, agentMap),
1083
1105
  };
1084
1106
  }
1085
1107
  else if (stateJson.currentStep?.type === 'next_step_interruption') {
@@ -1100,7 +1122,9 @@ export async function rehydrateProcessedResponseTools(initialAgent, state, execu
1100
1122
  if (!state._lastProcessedResponse) {
1101
1123
  return;
1102
1124
  }
1103
- state._lastProcessedResponse = await deserializeProcessedResponse(buildAgentMap(initialAgent), state, state._lastProcessedResponse, {
1125
+ const agentIdentity = buildAgentIdentityMap(initialAgent);
1126
+ const serializedProcessedResponse = serializeProcessedResponse(state._lastProcessedResponse, agentIdentity.byAgent);
1127
+ state._lastProcessedResponse = await deserializeProcessedResponse(agentIdentity.byIdentity, state, serializedProcessedResponse, {
1104
1128
  executionTools,
1105
1129
  allowSerializedExecutionToolPlaceholder: false,
1106
1130
  });
@@ -1140,6 +1164,249 @@ export function buildAgentMap(initialAgent) {
1140
1164
  }
1141
1165
  return map;
1142
1166
  }
1167
+ /**
1168
+ * @internal
1169
+ */
1170
+ export function buildAgentIdentityMap(initialAgent) {
1171
+ const agents = collectAgentGraph(initialAgent);
1172
+ const groups = new Map();
1173
+ const literalNames = new Set();
1174
+ for (const entry of agents) {
1175
+ literalNames.add(entry.agent.name);
1176
+ const group = groups.get(entry.agent.name) ?? [];
1177
+ group.push(entry);
1178
+ groups.set(entry.agent.name, group);
1179
+ }
1180
+ const byIdentity = new Map();
1181
+ const byAgent = new Map();
1182
+ const usedIdentities = new Set();
1183
+ for (const [agentName, group] of groups) {
1184
+ const sortedGroup = group.length === 1
1185
+ ? group
1186
+ : [...group].sort((left, right) => {
1187
+ if (left.agent === initialAgent) {
1188
+ return -1;
1189
+ }
1190
+ if (right.agent === initialAgent) {
1191
+ return 1;
1192
+ }
1193
+ const leftSignature = getAgentIdentitySignature(left.agent);
1194
+ const rightSignature = getAgentIdentitySignature(right.agent);
1195
+ if (leftSignature !== rightSignature) {
1196
+ return leftSignature < rightSignature ? -1 : 1;
1197
+ }
1198
+ return left.index - right.index;
1199
+ });
1200
+ let nextSuffix = 0;
1201
+ for (const { agent } of sortedGroup) {
1202
+ let identity;
1203
+ do {
1204
+ identity =
1205
+ nextSuffix === 0 ? agentName : `${agentName}#${nextSuffix + 1}`;
1206
+ nextSuffix += 1;
1207
+ } while (usedIdentities.has(identity) ||
1208
+ (identity !== agent.name && literalNames.has(identity)));
1209
+ usedIdentities.add(identity);
1210
+ byIdentity.set(identity, agent);
1211
+ byAgent.set(agent, identity);
1212
+ }
1213
+ }
1214
+ return { byIdentity, byAgent };
1215
+ }
1216
+ function collectAgentGraph(initialAgent) {
1217
+ const agents = [];
1218
+ const visitedAgents = new Set();
1219
+ const queue = [initialAgent];
1220
+ while (queue.length > 0) {
1221
+ const currentAgent = queue.shift();
1222
+ if (visitedAgents.has(currentAgent)) {
1223
+ continue;
1224
+ }
1225
+ visitedAgents.add(currentAgent);
1226
+ agents.push({ agent: currentAgent, index: agents.length });
1227
+ for (const handoff of currentAgent.handoffs) {
1228
+ if (handoff instanceof Agent) {
1229
+ queue.push(handoff);
1230
+ }
1231
+ else if (handoff.agent) {
1232
+ queue.push(handoff.agent);
1233
+ }
1234
+ }
1235
+ for (const tool of currentAgent.tools) {
1236
+ const sourceAgent = getAgentToolSourceAgent(tool);
1237
+ if (sourceAgent) {
1238
+ queue.push(sourceAgent);
1239
+ }
1240
+ }
1241
+ }
1242
+ return agents;
1243
+ }
1244
+ function getAgentIdentitySignature(agent) {
1245
+ const sandboxAgent = agent;
1246
+ const signature = {
1247
+ type: agent.constructor?.name,
1248
+ name: agent.name,
1249
+ handoffDescription: agent.handoffDescription,
1250
+ instructions: summarizeIdentityValue(agent.instructions),
1251
+ prompt: summarizeIdentityValue(agent.prompt),
1252
+ model: summarizeIdentityValue(agent.model),
1253
+ modelSettings: summarizeIdentityValue(agent.modelSettings),
1254
+ tools: agent.tools.map(summarizeToolIdentity),
1255
+ handoffs: agent.handoffs.map((entry) => entry instanceof Agent
1256
+ ? { type: 'agent', name: entry.name }
1257
+ : {
1258
+ type: 'handoff',
1259
+ toolName: entry.toolName,
1260
+ agentName: entry.agentName,
1261
+ targetName: entry.agent?.name,
1262
+ }),
1263
+ mcpServers: agent.mcpServers.map(summarizeIdentityValue),
1264
+ inputGuardrails: agent.inputGuardrails.map(summarizeIdentityValue),
1265
+ outputGuardrails: agent.outputGuardrails.map(summarizeIdentityValue),
1266
+ outputType: summarizeIdentityValue(agent.outputType),
1267
+ toolUseBehavior: summarizeIdentityValue(agent.toolUseBehavior),
1268
+ resetToolChoice: agent.resetToolChoice,
1269
+ defaultManifest: summarizeIdentityValue(sandboxAgent.defaultManifest),
1270
+ baseInstructions: summarizeIdentityValue(sandboxAgent.baseInstructions),
1271
+ capabilities: sandboxAgent.capabilities?.map(summarizeIdentityValue),
1272
+ runAs: summarizeIdentityValue(sandboxAgent.runAs),
1273
+ };
1274
+ return stableStringify(signature);
1275
+ }
1276
+ function summarizeToolIdentity(tool) {
1277
+ return {
1278
+ type: tool.type,
1279
+ name: tool.name,
1280
+ namespace: tool.namespace,
1281
+ strict: tool.strict,
1282
+ parameters: summarizeIdentityValue(tool.parameters),
1283
+ };
1284
+ }
1285
+ function summarizeIdentityValue(value) {
1286
+ return normalizeForIdentity(value, new WeakSet(), 0);
1287
+ }
1288
+ function normalizeForIdentity(value, seen, depth) {
1289
+ if (value === null || typeof value === 'undefined') {
1290
+ return value;
1291
+ }
1292
+ if (typeof value === 'string' ||
1293
+ typeof value === 'number' ||
1294
+ typeof value === 'boolean') {
1295
+ return value;
1296
+ }
1297
+ if (typeof value === 'function') {
1298
+ return `[function:${value.name || 'anonymous'}]`;
1299
+ }
1300
+ if (typeof value !== 'object') {
1301
+ return String(value);
1302
+ }
1303
+ if (seen.has(value)) {
1304
+ return '[circular]';
1305
+ }
1306
+ if (depth >= 4) {
1307
+ return `[${value.constructor?.name ?? 'Object'}]`;
1308
+ }
1309
+ seen.add(value);
1310
+ if (Array.isArray(value)) {
1311
+ return value.map((item) => normalizeForIdentity(item, seen, depth + 1));
1312
+ }
1313
+ if (value instanceof Map) {
1314
+ return [...value.entries()]
1315
+ .map(([key, entryValue]) => [
1316
+ normalizeForIdentity(key, seen, depth + 1),
1317
+ normalizeForIdentity(entryValue, seen, depth + 1),
1318
+ ])
1319
+ .sort((left, right) => stableStringify(left).localeCompare(stableStringify(right)));
1320
+ }
1321
+ if (value instanceof Set) {
1322
+ return [...value.values()]
1323
+ .map((entry) => normalizeForIdentity(entry, seen, depth + 1))
1324
+ .sort((left, right) => stableStringify(left).localeCompare(stableStringify(right)));
1325
+ }
1326
+ const record = value;
1327
+ const normalized = {
1328
+ constructor: value.constructor?.name,
1329
+ };
1330
+ for (const key of Object.keys(record).sort()) {
1331
+ normalized[key] = normalizeForIdentity(record[key], seen, depth + 1);
1332
+ }
1333
+ return normalized;
1334
+ }
1335
+ function stableStringify(value) {
1336
+ return JSON.stringify(value, (_key, currentValue) => {
1337
+ if (!currentValue ||
1338
+ typeof currentValue !== 'object' ||
1339
+ Array.isArray(currentValue)) {
1340
+ return currentValue;
1341
+ }
1342
+ return Object.fromEntries(Object.entries(currentValue).sort(([left], [right]) => left.localeCompare(right)));
1343
+ });
1344
+ }
1345
+ function serializeAgentReference(agent, agentIdentityKeys) {
1346
+ const identity = agentIdentityKeys.get(agent);
1347
+ if (!identity || identity === agent.name) {
1348
+ return { name: agent.name };
1349
+ }
1350
+ return { name: agent.name, identity };
1351
+ }
1352
+ function resolveSerializedAgent(serializedAgent, agentMap, fallbackAgent) {
1353
+ const identity = serializedAgent.identity ?? serializedAgent.name;
1354
+ const agent = agentMap.get(identity);
1355
+ if (agent) {
1356
+ return agent;
1357
+ }
1358
+ if (!serializedAgent.identity && fallbackAgent) {
1359
+ return fallbackAgent;
1360
+ }
1361
+ if (serializedAgent.identity) {
1362
+ throw new UserError(`Agent identity ${serializedAgent.identity} not found`);
1363
+ }
1364
+ throw new UserError(`Agent ${serializedAgent.name} not found`);
1365
+ }
1366
+ function serializeRunItem(item, agentIdentityKeys) {
1367
+ const serialized = item.toJSON();
1368
+ switch (item.type) {
1369
+ case 'handoff_output_item':
1370
+ serialized.sourceAgent = serializeAgentReference(item.sourceAgent, agentIdentityKeys);
1371
+ serialized.targetAgent = serializeAgentReference(item.targetAgent, agentIdentityKeys);
1372
+ return serialized;
1373
+ default:
1374
+ serialized.agent = serializeAgentReference(item.agent, agentIdentityKeys);
1375
+ return serialized;
1376
+ }
1377
+ }
1378
+ function serializeCurrentStep(currentStep, agentIdentityKeys) {
1379
+ if (!currentStep) {
1380
+ return undefined;
1381
+ }
1382
+ if (currentStep.type === 'next_step_handoff') {
1383
+ return {
1384
+ ...currentStep,
1385
+ newAgent: serializeAgentReference(currentStep.newAgent, agentIdentityKeys),
1386
+ };
1387
+ }
1388
+ if (currentStep.type === 'next_step_interruption') {
1389
+ const interruptions = Array.isArray(currentStep.data?.interruptions)
1390
+ ? currentStep.data.interruptions.map((item) => item instanceof RunToolApprovalItem
1391
+ ? serializeRunItem(item, agentIdentityKeys)
1392
+ : item)
1393
+ : currentStep.data?.interruptions;
1394
+ return {
1395
+ ...currentStep,
1396
+ data: {
1397
+ ...currentStep.data,
1398
+ interruptions,
1399
+ },
1400
+ };
1401
+ }
1402
+ return currentStep;
1403
+ }
1404
+ function serializeProcessedResponse(processedResponse, agentIdentityKeys) {
1405
+ return {
1406
+ ...processedResponse,
1407
+ newItems: processedResponse.newItems.map((item) => serializeRunItem(item, agentIdentityKeys)),
1408
+ };
1409
+ }
1143
1410
  /**
1144
1411
  * @internal
1145
1412
  */
@@ -1178,23 +1445,23 @@ export function deserializeModelResponse(serializedModelResponse) {
1178
1445
  export function deserializeItem(serializedItem, agentMap) {
1179
1446
  switch (serializedItem.type) {
1180
1447
  case 'message_output_item':
1181
- return new RunMessageOutputItem(serializedItem.rawItem, agentMap.get(serializedItem.agent.name));
1448
+ return new RunMessageOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
1182
1449
  case 'tool_search_call_item':
1183
- return new RunToolSearchCallItem(serializedItem.rawItem, agentMap.get(serializedItem.agent.name));
1450
+ return new RunToolSearchCallItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
1184
1451
  case 'tool_search_output_item':
1185
- return new RunToolSearchOutputItem(serializedItem.rawItem, agentMap.get(serializedItem.agent.name));
1452
+ return new RunToolSearchOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
1186
1453
  case 'tool_call_item':
1187
- return new RunToolCallItem(serializedItem.rawItem, agentMap.get(serializedItem.agent.name));
1454
+ return new RunToolCallItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
1188
1455
  case 'tool_call_output_item':
1189
- return new RunToolCallOutputItem(serializedItem.rawItem, agentMap.get(serializedItem.agent.name), serializedItem.output);
1456
+ return new RunToolCallOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap), serializedItem.output);
1190
1457
  case 'reasoning_item':
1191
- return new RunReasoningItem(serializedItem.rawItem, agentMap.get(serializedItem.agent.name));
1458
+ return new RunReasoningItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
1192
1459
  case 'handoff_call_item':
1193
- return new RunHandoffCallItem(serializedItem.rawItem, agentMap.get(serializedItem.agent.name));
1460
+ return new RunHandoffCallItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap));
1194
1461
  case 'handoff_output_item':
1195
- return new RunHandoffOutputItem(serializedItem.rawItem, agentMap.get(serializedItem.sourceAgent.name), agentMap.get(serializedItem.targetAgent.name));
1462
+ return new RunHandoffOutputItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.sourceAgent, agentMap), resolveSerializedAgent(serializedItem.targetAgent, agentMap));
1196
1463
  case 'tool_approval_item':
1197
- return new RunToolApprovalItem(serializedItem.rawItem, agentMap.get(serializedItem.agent.name), serializedItem.toolName);
1464
+ return new RunToolApprovalItem(serializedItem.rawItem, resolveSerializedAgent(serializedItem.agent, agentMap), serializedItem.toolName);
1198
1465
  }
1199
1466
  }
1200
1467
  function deserializeInterruptionItem(serializedItem, agentMap, currentAgent) {
@@ -1204,7 +1471,7 @@ function deserializeInterruptionItem(serializedItem, agentMap, currentAgent) {
1204
1471
  const parsed = itemSchema.safeParse(serializedItem);
1205
1472
  if (parsed.success) {
1206
1473
  if (parsed.data.type === 'tool_approval_item') {
1207
- const mappedAgent = agentMap.get(parsed.data.agent.name) ?? currentAgent;
1474
+ const mappedAgent = resolveSerializedAgent(parsed.data.agent, agentMap, currentAgent);
1208
1475
  return new RunToolApprovalItem(parsed.data.rawItem, mappedAgent, parsed.data.toolName);
1209
1476
  }
1210
1477
  const item = deserializeItem(parsed.data, agentMap);
@@ -1228,7 +1495,15 @@ function deserializeInterruptionItem(serializedItem, agentMap, currentAgent) {
1228
1495
  const agentName = value.agent && typeof value.agent.name === 'string'
1229
1496
  ? value.agent.name
1230
1497
  : undefined;
1231
- const mappedAgent = (agentName ? agentMap.get(agentName) : undefined) ?? currentAgent;
1498
+ const agentIdentity = value.agent && typeof value.agent.identity === 'string'
1499
+ ? value.agent.identity
1500
+ : undefined;
1501
+ const mappedAgent = agentName || agentIdentity
1502
+ ? resolveSerializedAgent({
1503
+ name: agentName ?? currentAgent.name,
1504
+ identity: agentIdentity,
1505
+ }, agentMap, currentAgent)
1506
+ : currentAgent;
1232
1507
  const toolName = typeof value.toolName === 'string'
1233
1508
  ? value.toolName
1234
1509
  : typeof rawItem.name === 'string'