{"version":3,"file":"supervisor.cjs","names":["createHandoffBackMessages","createHandoffTool","StateGraph","START"],"sources":["../src/supervisor.ts"],"sourcesContent":["import { LanguageModelLike } from \"@langchain/core/language_models/base\";\nimport { StructuredToolInterface, DynamicTool } from \"@langchain/core/tools\";\nimport type {\n  RunnableConfig,\n  RunnableToolLike,\n} from \"@langchain/core/runnables\";\nimport { InteropZodType } from \"@langchain/core/utils/types\";\nimport {\n  START,\n  StateGraph,\n  CompiledStateGraph,\n  AnnotationRoot,\n  MessagesAnnotation,\n} from \"@langchain/langgraph\";\nimport {\n  createReactAgent,\n  createReactAgentAnnotation,\n  CreateReactAgentParams,\n  withAgentName,\n  AgentNameMode,\n} from \"@langchain/langgraph/prebuilt\";\nimport {\n  BaseChatModel,\n  BindToolsInput,\n} from \"@langchain/core/language_models/chat_models\";\nimport type { RemoteGraph } from \"@langchain/langgraph/remote\";\nimport { v5 as uuidv5 } from \"@langchain/core/utils/uuid\";\nimport { createHandoffTool, createHandoffBackMessages } from \"./handoff.js\";\n\nexport type { AgentNameMode };\nexport { withAgentName };\n\ntype OutputMode = \"full_history\" | \"last_message\";\nconst PROVIDERS_WITH_PARALLEL_TOOL_CALLS_PARAM = new Set([\"ChatOpenAI\"]);\n\n// type guards\ntype ChatModelWithBindTools = BaseChatModel & {\n  bindTools(tools: BindToolsInput[], kwargs?: unknown): LanguageModelLike;\n};\n\ntype ChatModelWithParallelToolCallsParam = BaseChatModel & {\n  bindTools(\n    tools: BindToolsInput[],\n    kwargs?: { parallel_tool_calls?: boolean } & Record<string, unknown>\n  ): LanguageModelLike;\n};\n\nfunction isChatModelWithBindTools(\n  llm: LanguageModelLike\n): llm is ChatModelWithBindTools {\n  return (\n    \"_modelType\" in llm &&\n    typeof llm._modelType === \"function\" &&\n    llm._modelType() === \"base_chat_model\" &&\n    \"bindTools\" in llm &&\n    typeof llm.bindTools === \"function\"\n  );\n}\n\nfunction isChatModelWithParallelToolCallsParam(\n  llm: ChatModelWithBindTools\n): llm is ChatModelWithParallelToolCallsParam {\n  return llm.bindTools.length >= 2;\n}\n\nfunction isRemoteGraph(agent: unknown): agent is RemoteGraph {\n  if (agent == null || typeof agent !== \"object\") return false;\n  if (!(\"lc_id\" in agent)) return false;\n  if (!Array.isArray(agent.lc_id)) return false;\n\n  return agent.lc_id.join(\".\") === \"langgraph.pregel.RemoteGraph\";\n}\n\nconst makeCallAgent = (\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  agent: any, // TODO: agent should not be `any`\n  outputMode: OutputMode,\n  addHandoffBackMessages: boolean,\n  supervisorName: string\n) => {\n  if (![\"full_history\", \"last_message\"].includes(outputMode)) {\n    throw new Error(\n      `Invalid agent output mode: ${outputMode}. Needs to be one of [\"full_history\", \"last_message\"]`\n    );\n  }\n\n  return async (state: Record<string, unknown>, config?: RunnableConfig) => {\n    let conf = config;\n\n    if (isRemoteGraph(agent)) {\n      const threadId = config?.configurable?.thread_id;\n      const agentThreadId =\n        threadId && agent.name ? uuidv5(agent.name, threadId) : null;\n\n      conf = {\n        ...(config ?? {}),\n        configurable: {\n          ...(config?.configurable ?? {}),\n          ...{ thread_id: agentThreadId },\n        },\n      };\n    }\n    const output = await agent.invoke(state, conf);\n    let { messages } = output;\n\n    if (outputMode === \"last_message\") {\n      messages = messages.slice(-1);\n    }\n\n    if (addHandoffBackMessages) {\n      messages.push(...createHandoffBackMessages(agent.name, supervisorName));\n    }\n    return { ...output, messages };\n  };\n};\n\n/** @inline */\nexport type CreateSupervisorParams<\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  AnnotationRootT extends AnnotationRoot<any>,\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  StructuredResponseFormat extends Record<string, any> = Record<string, any>,\n> = {\n  /**\n   * List of agents to manage.\n   * Accepts compiled graphs from both `createReactAgent` (`@langchain/langgraph`)\n   * and `createAgent` (`langchain`) via `.graph`.\n   */\n  agents: (\n    | CompiledStateGraph<\n        AnnotationRootT[\"State\"],\n        AnnotationRootT[\"Update\"],\n        string,\n        AnnotationRootT[\"spec\"],\n        AnnotationRootT[\"spec\"]\n      >\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    | CompiledStateGraph<any, any, string, any, any>\n    | RemoteGraph\n  )[];\n\n  /**\n   * Language model to use for the supervisor\n   */\n  llm: LanguageModelLike;\n\n  /**\n   * Tools to use for the supervisor\n   */\n  tools?: (StructuredToolInterface | RunnableToolLike | DynamicTool)[];\n\n  /**\n   * An optional prompt for the supervisor. Can be one of:\n   * - `string`: This is converted to a SystemMessage and added to the beginning of the list of messages in state[\"messages\"]\n   * - `SystemMessage`: this is added to the beginning of the list of messages in state[\"messages\"]\n   * - `Function`: This function should take in full graph state and the output is then passed to the language model\n   * - `Runnable`: This runnable should take in full graph state and the output is then passed to the language model\n   */\n  prompt?: CreateReactAgentParams[\"prompt\"];\n\n  /**\n   * An optional schema for the final supervisor output.\n   *\n   * If provided, output will be formatted to match the given schema and returned in the 'structuredResponse' state key.\n   * If not provided, `structuredResponse` will not be present in the output state.\n   *\n   * Can be passed in as:\n   *   - Zod schema\n   *   - JSON schema\n   *   - { prompt, schema }, where schema is one of the above.\n   *        The prompt will be used together with the model that is being used to generate the structured response.\n   *\n   * @remarks\n   * **Important**: `responseFormat` requires the model to support `.withStructuredOutput()`.\n   *\n   * **Note**: The graph will make a separate call to the LLM to generate the structured response after the agent loop is finished.\n   * This is not the only strategy to get structured responses, see more options in [this guide](https://langchain-ai.github.io/langgraph/how-tos/react-agent-structured-output/).\n   */\n  responseFormat?:\n    | InteropZodType<StructuredResponseFormat>\n    | {\n        prompt: string;\n        schema:\n          | InteropZodType<StructuredResponseFormat>\n          | Record<string, unknown>;\n      }\n    | Record<string, unknown>;\n\n  /**\n   * State schema to use for the supervisor graph\n   */\n  stateSchema?: AnnotationRootT;\n\n  /**\n   * Context schema to use for the supervisor graph\n   */\n  contextSchema?: AnnotationRootT;\n\n  /**\n   * Mode for adding managed agents' outputs to the message history in the multi-agent workflow.\n   * Can be one of:\n   * - `\"full_history\"`: add the entire agent message history\n   * - `\"last_message\"`: add only the last message (default)\n   */\n  outputMode?: OutputMode;\n\n  /**\n   * Whether to add the supervisor-to-agent handoff messages (the supervisor\n   * `AIMessage` containing the handoff tool call and the handoff `ToolMessage`)\n   * to the message history forwarded to the expert agent. If `false`, those\n   * handoff bookkeeping messages are omitted from the expert agent's message\n   * history. This is useful for providers that strictly validate tool-call\n   * message sequences. Defaults to `true`.\n   */\n  addHandoffMessages?: boolean;\n\n  /**\n   * Whether to add a pair of (AIMessage, ToolMessage) to the message history\n   * when returning control to the supervisor to indicate that a handoff has occurred\n   * Defaults to the value of `addHandoffMessages`.\n   */\n  addHandoffBackMessages?: boolean;\n\n  /**\n   * Name of the supervisor node\n   */\n  supervisorName?: string;\n\n  /**\n   * Use to specify how to expose the agent name to the underlying supervisor LLM.\n   * - `undefined`: Relies on the LLM provider using the name attribute on the AI message. Currently, only OpenAI supports this.\n   * - `\"inline\"`: Add the agent name directly into the content field of the AI message using XML-style tags.\n   *   Example: \"How can I help you\" -> \"<name>agent_name</name><content>How can I help you?</content>\"\n   */\n  includeAgentName?: AgentNameMode;\n\n  /**\n   * An optional node to add before the LLM node in the supervisor agent (i.e., the node that calls the LLM).\n   * Useful for managing long message histories (e.g., message trimming, summarization, etc.).\n   *\n   * Pre-model hook must be a callable or a runnable that takes in current graph state and returns a state update in the form of:\n   * ```javascript\n   * {\n   *   messages: [new RemoveMessage({ id: REMOVE_ALL_MESSAGES }), ...],\n   *   llmInputMessages: [...]\n   *   ...\n   * }\n   * ```\n   * **Important**: At least one of `messages` or `llmInputMessages` MUST be provided and will be used as an input to the `agent` node.\n   * The rest of the keys will be added to the graph state.\n   *\n   *\n   * **Warning**: If you are returning `messages` in the pre-model hook, you should OVERWRITE the `messages` key by doing the following:\n   * ```javascript\n   * { messages: [new RemoveMessage({ id: REMOVE_ALL_MESSAGES }), ...newMessages], ... }\n   * ```\n   */\n  preModelHook?: CreateReactAgentParams<\n    AnnotationRootT,\n    StructuredResponseFormat\n  >[\"preModelHook\"];\n\n  /**\n   * An optional node to add after the LLM node in the supervisor agent (i.e., the node that calls the LLM).\n   * Useful for implementing human-in-the-loop, guardrails, validation, or other post-processing.\n   * Post-model hook must be a callable or a runnable that takes in current graph state and returns a state update.\n   */\n  postModelHook?: CreateReactAgentParams<\n    AnnotationRootT,\n    StructuredResponseFormat\n  >[\"postModelHook\"];\n};\n\n/**\n * Create a multi-agent supervisor.\n *\n * @param params Parameters for the supervisor.\n * @returns The supervisor graph.\n */\nconst createSupervisor = <\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  AnnotationRootT extends AnnotationRoot<any> = typeof MessagesAnnotation,\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  StructuredResponseFormat extends Record<string, any> = Record<string, any>,\n>({\n  agents,\n  llm,\n  tools,\n  prompt,\n  responseFormat,\n  stateSchema,\n  contextSchema,\n  outputMode = \"last_message\",\n  addHandoffMessages = true,\n  addHandoffBackMessages,\n  supervisorName = \"supervisor\",\n  includeAgentName,\n  preModelHook,\n  postModelHook,\n}: CreateSupervisorParams<\n  AnnotationRootT,\n  StructuredResponseFormat\n>): StateGraph<\n  AnnotationRootT[\"spec\"],\n  AnnotationRootT[\"State\"],\n  AnnotationRootT[\"Update\"],\n  string,\n  AnnotationRootT[\"spec\"],\n  AnnotationRootT[\"spec\"]\n> => {\n  const resolvedAddHandoffBackMessages =\n    addHandoffBackMessages ?? addHandoffMessages;\n  const agentNames = new Set<string>();\n\n  for (const agent of agents) {\n    if (!agent.name || agent.name === \"LangGraph\") {\n      throw new Error(\n        \"Please specify a name when you create your agent, either via `createReactAgent({ ..., name: agentName })` \" +\n          \"or via `graph.compile({ name: agentName })`.\"\n      );\n    }\n\n    if (agentNames.has(agent.name)) {\n      throw new Error(\n        `Agent with name '${agent.name}' already exists. Agent names must be unique.`\n      );\n    }\n\n    agentNames.add(agent.name);\n  }\n\n  const handoffTools = agents.map((agent) => {\n    const agentName = agent.name!;\n    const agentDescription =\n      \"description\" in agent && typeof agent.description === \"string\"\n        ? agent.description\n        : undefined;\n\n    return createHandoffTool({\n      agentName,\n      description: agentDescription,\n      addHandoffMessages,\n    });\n  });\n  const allTools = [...(tools ?? []), ...handoffTools];\n\n  let supervisorLLM = llm;\n  if (isChatModelWithBindTools(llm)) {\n    if (\n      isChatModelWithParallelToolCallsParam(llm) &&\n      PROVIDERS_WITH_PARALLEL_TOOL_CALLS_PARAM.has(llm.getName())\n    ) {\n      supervisorLLM = llm.bindTools(allTools, { parallel_tool_calls: false });\n    } else {\n      supervisorLLM = llm.bindTools(allTools);\n    }\n\n    // hack: with newer version of LangChain we've started using `withConfig()` instead of `bind()`\n    // when binding tools, thus older version of LangGraph will incorrectly try to bind tools twice.\n    // TODO: remove when we start handling tools from config in @langchain/langgraph\n\n    // @ts-expect-error hack\n    supervisorLLM.kwargs ??= {};\n\n    // @ts-expect-error hack\n    // eslint-disable-next-line prefer-destructuring\n    const kwargs = supervisorLLM.kwargs;\n\n    if (!(\"tools\" in kwargs)) {\n      if (\n        \"config\" in supervisorLLM &&\n        typeof supervisorLLM.config === \"object\" &&\n        supervisorLLM.config != null &&\n        \"tools\" in supervisorLLM.config\n      ) {\n        kwargs.tools = supervisorLLM.config.tools;\n      }\n    }\n  }\n\n  // Apply agent name handling if specified\n  if (includeAgentName) {\n    supervisorLLM = withAgentName(supervisorLLM, includeAgentName);\n  }\n\n  const schema = stateSchema ?? createReactAgentAnnotation();\n  const supervisorAgent = createReactAgent({\n    name: supervisorName,\n    llm: supervisorLLM,\n    tools: allTools,\n    prompt,\n    responseFormat,\n    stateSchema: schema as AnnotationRootT,\n    preModelHook,\n    postModelHook,\n  });\n\n  let builder = new StateGraph(schema, contextSchema)\n    .addNode(supervisorAgent.name!, supervisorAgent, {\n      ends: [...agentNames],\n    })\n    .addEdge(START, supervisorAgent.name!);\n\n  for (const agent of agents) {\n    builder = builder.addNode(\n      agent.name!,\n      makeCallAgent(\n        agent,\n        outputMode,\n        resolvedAddHandoffBackMessages,\n        supervisorName\n      ),\n      { subgraphs: isRemoteGraph(agent) ? undefined : [agent] }\n    );\n    builder = builder.addEdge(agent.name!, supervisorAgent.name!);\n  }\n\n  return builder;\n};\n\nexport { createSupervisor, type OutputMode };\n"],"mappings":"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"}