{"componentChunkName":"component---src-gatsby-theme-chronoblog-templates-note-js","path":"/notes/ai-agents-langchain-nodejs/","result":{"data":{"mdx":{"parent":{"__typename":"File","fields":{"gitLogLatestDate":"2026-06-16 20:11:46 +0200"}},"id":"0ec1c25a-ce96-53c6-af57-223b43dae638","excerpt":"LangChain  agents are built on  LangGraph : the model calls tools in a loop until it returns a final answer. The high-level entry point is…","frontmatter":{"title":"Building AI agents with LangChain","date":"2026-06-17 00:01:00 UTC","job_ad":null,"job_ad_id":null,"job_ad_url":null,"tags":["langchain","ai","llm","node","openai","agents"],"cover":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAPoAAAD6AG1e1JrAAABW0lEQVQoz4WTi26rMBBE+//f2KvSpIEECMHG7wenshNa0qq6SIDsHY53R8MLwLqu5Yk1cDwqTidL8CDFytvbzOXs8A7a1tI0EikSRlN1l0us2vJ94bzsgc7Bx3Hh8C7RKnIdHf9eR4beEQNczpb3ZmaRCWehay39JRDCD+C2qO8Mi9SM48g0TejF1VpKiZwy0eeqK3eKKzmt7Jt6ALcNSOku3C5nI1rfDzCmWJG/ar+BfI+8B8aQS691rZXDGIMQM8NQxp8QQuCDx2hHjJk940/gZoM1xaOA9x61KIb+inOu7lnjSf8FxueRrQ6IWdAPA8uiqgUP1+vBm/YJuPegTBp8YFESrRXeBZyzSCnx3n15VqX5u5FfHhZSyVOJSNcqlPLcJsu5MywykxPMt1TrRme8W7mOkduUiHH9I4cWTh+KrjWPYGea5sbQ34Ne4IeDqDksP0HXWYb+OYefXc4OG4T4WS4AAAAASUVORK5CYII=","aspectRatio":2.0869565217391304,"src":"/static/d7fd6c2fc0f9ef896e7e8198841e8bf5/c4ecb/cover.png","srcSet":"/static/d7fd6c2fc0f9ef896e7e8198841e8bf5/57ab0/cover.png 192w,\n/static/d7fd6c2fc0f9ef896e7e8198841e8bf5/f4739/cover.png 384w,\n/static/d7fd6c2fc0f9ef896e7e8198841e8bf5/c4ecb/cover.png 768w","srcWebp":"/static/d7fd6c2fc0f9ef896e7e8198841e8bf5/dd090/cover.webp","srcSetWebp":"/static/d7fd6c2fc0f9ef896e7e8198841e8bf5/ae504/cover.webp 192w,\n/static/d7fd6c2fc0f9ef896e7e8198841e8bf5/fef30/cover.webp 384w,\n/static/d7fd6c2fc0f9ef896e7e8198841e8bf5/dd090/cover.webp 768w","sizes":"(max-width: 768px) 100vw, 768px","presentationWidth":768,"presentationHeight":366},"resize":{"src":"/static/d7fd6c2fc0f9ef896e7e8198841e8bf5/c4ecb/cover.png"}}}},"fields":{"slug":"/notes/ai-agents-langchain-nodejs/","readingTime":{"text":"5 min read"}},"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Building AI agents with LangChain\",\n  \"date\": \"2026-06-17 00:01:00 UTC\",\n  \"cover\": \"./cover.png\",\n  \"tags\": [\"langchain\", \"ai\", \"llm\", \"node\", \"openai\", \"agents\"],\n  \"canonical_url\": \"https://sevic.dev/notes/ai-agents-langchain-nodejs/\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://docs.langchain.com/oss/javascript/langchain/overview\"\n  }), \"LangChain\"), \" agents are built on \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"LangGraph\"), \": the model calls tools in a loop until it returns a final answer. The high-level entry point is \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://docs.langchain.com/oss/javascript/langchain/agents\"\n  }), mdx(\"inlineCode\", {\n    parentName: \"a\"\n  }, \"createAgent\")), \" - pass a model, tools defined with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"tool()\"), \", and an optional \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"systemPrompt\"), \".\"), mdx(\"p\", null, \"This post builds the same \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"support triage agent\"), \" as the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/ai-agents-vercel-ai-sdk/\"\n  }), \"Vercel AI SDK agents\"), \" and \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/ai-agents-openai-sdk/\"\n  }), \"OpenAI Agents SDK\"), \" posts so you can compare SDKs on one scenario. It follows the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/langchain-overview-nodejs/\"\n  }), \"LangChain overview for Node.js\"), \" and fits as post \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"#4\"), \" in the LangChain series (after loaders/chunking and the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://sevic.dev/notes/rag-openai-embeddings-pgvector-langchain/\"\n  }), \"RAG with pgvector\"), \" pipeline).\"), mdx(\"h3\", {\n    \"id\": \"prerequisites\"\n  }, \"Prerequisites\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"OpenAI account\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Generated API key\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Enabled billing\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Node.js version 26\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"langchain\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"@langchain/openai\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"@langchain/core\"), \", and \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"zod\"), \" installed:\")), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-bash\"\n  }), \"npm i langchain @langchain/openai @langchain/core zod\\n\")), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"OPENAI_API_KEY\"), \" set in the environment\")), mdx(\"h3\", {\n    \"id\": \"mental-model---turns-and-the-agent-loop\"\n  }, \"Mental model - turns and the agent loop\"), mdx(\"p\", null, \"A \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"turn\"), \" is one model generation. In that turn the model either:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"returns \", mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"final text\"), \" (the run ends), or\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"returns \", mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"tool calls\"), \" (LangChain executes them and starts another turn with the results)\")), mdx(\"p\", null, \"Typical flow for the support triage agent: user question \\u2192 model calls lookup tools (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"get_customer\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"get_invoice\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"search_knowledge_base\"), \") \\u2192 model creates a ticket or escalates \\u2192 final answer.\"), mdx(\"p\", null, \"A single turn can include \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"multiple parallel tool calls\"), \". Set \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"recursionLimit\"), \" on \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"invoke\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"stream\"), \" to cap how many graph steps run (each model generation and tool batch counts toward the limit).\"), mdx(\"h3\", {\n    \"id\": \"defining-tools\"\n  }, \"Defining tools\"), mdx(\"p\", null, \"Use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"tool()\"), \" from \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"langchain\"), \" with a Zod \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"schema\"), \", plus \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"name\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"description\"), \" so the model knows when to call each tool:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import { tool } from 'langchain';\\nimport { z } from 'zod';\\n\\nconst getInvoice = tool(\\n  async ({ invoiceId }) => {\\n    const invoice = invoices.find((item) => item.id === invoiceId);\\n    if (!invoice) {\\n      return { found: false, invoiceId, error: 'Invoice not found' };\\n    }\\n    return { found: true, invoice };\\n  },\\n  {\\n    name: 'get_invoice',\\n    description: 'Look up an invoice by ID, including payment IDs and status',\\n    schema: z.object({\\n      invoiceId: z.string().describe('Invoice ID, e.g. inv_8891'),\\n    }),\\n  },\\n);\\n\")), mdx(\"p\", null, \"LangChain uses \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"schema\"), \" (not Vercel's \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"inputSchema\"), \" or OpenAI Agents' \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"parameters\"), \"). The handler receives validated input as the first argument.\"), mdx(\"h3\", {\n    \"id\": \"createagent\"\n  }, \"createAgent\"), mdx(\"p\", null, \"Wire the model, tools, and triage instructions:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import { createAgent } from 'langchain';\\n\\nconst agent = createAgent({\\n  model: 'gpt-5.5',\\n  tools: [getInvoice],\\n  systemPrompt: `You are a billing support triage agent.\\nLook up records before recommending refunds or creating tickets.`,\\n});\\n\")), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"model\"), \" can be a provider string (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"'gpt-5.5'\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"'openai:gpt-5.5'\"), \") or a chat model instance from \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"@langchain/openai\"), \".\"), mdx(\"h3\", {\n    \"id\": \"invoke\"\n  }, \"Invoke\"), mdx(\"p\", null, \"Pass a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"messages\"), \" array and read the final answer from \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"result.messages\"), \":\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const result = await agent.invoke({\\n  messages: [\\n    {\\n      role: 'user',\\n      content: 'What is the status of invoice inv_8891? Reply in one sentence.',\\n    },\\n  ],\\n});\\n\\nconst lastAi = [...result.messages]\\n  .reverse()\\n  .find((message) => message.type === 'ai');\\n\\nconsole.log(lastAi?.content);\\n\")), mdx(\"p\", null, \"The last AI message is the agent's final reply after any tool calls complete.\"), mdx(\"h3\", {\n    \"id\": \"support-triage-scenario\"\n  }, \"Support triage scenario\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Example prompt:\")), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, \"Customer cus_1042 says they were charged twice for invoice inv_8891. What should we do?\")), mdx(\"p\", null, \"A realistic chain:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"get_customer\"), \" - plan tier, open ticket count\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"get_invoice\"), \" - amount, status, payment IDs\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"search_knowledge_base\"), \" - duplicate-charge and refund policy\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"create_support_ticket\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"escalate_to_human\"), \" - write action or escalation\")), mdx(\"p\", null, \"The demo uses in-memory fixtures (customers, invoices, knowledge-base articles) so scripts run without a database.\"), mdx(\"h3\", {\n    \"id\": \"multi-tool-agent\"\n  }, \"Multi-tool agent\"), mdx(\"p\", null, \"Register all triage tools on one agent:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"import { createAgent } from 'langchain';\\nimport {\\n  getCustomer,\\n  getInvoice,\\n  searchKnowledgeBase,\\n  createSupportTicket,\\n  escalateToHuman,\\n  TRIAGE_INSTRUCTIONS,\\n} from './tools/index.js';\\n\\nconst agent = createAgent({\\n  model: 'gpt-5.5',\\n  tools: [\\n    getCustomer,\\n    getInvoice,\\n    searchKnowledgeBase,\\n    createSupportTicket,\\n    escalateToHuman,\\n  ],\\n  systemPrompt: TRIAGE_INSTRUCTIONS,\\n});\\n\\nconst result = await agent.invoke({\\n  messages: [\\n    {\\n      role: 'user',\\n      content:\\n        'Customer cus_1042 says they were charged twice for invoice inv_8891. What should we do?',\\n    },\\n  ],\\n  recursionLimit: 15,\\n});\\n\\nconst answer = [...result.messages]\\n  .reverse()\\n  .find((message) => message.type === 'ai');\\n\\nconsole.log(answer?.content);\\n\")), mdx(\"p\", null, \"Inspect \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"result.messages\"), \" for the full trace: human input, AI tool-call messages, tool results, and the final AI reply.\"), mdx(\"h3\", {\n    \"id\": \"streaming\"\n  }, \"Streaming\"), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"agent.stream()\"), \" yields state updates as the graph runs. Use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"streamMode: 'values'\"), \" to receive the full message list after each step:\"), mdx(\"pre\", null, mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-js\"\n  }), \"const stream = await agent.stream(\\n  {\\n    messages: [\\n      {\\n        role: 'user',\\n        content:\\n          'Customer cus_1042 says they were charged twice for invoice inv_8891. What should we do?',\\n      },\\n    ],\\n  },\\n  { streamMode: 'values', recursionLimit: 15 },\\n);\\n\\nlet finalMessages = [];\\n\\nfor await (const state of stream) {\\n  if (state.messages) {\\n    finalMessages = state.messages;\\n  }\\n}\\n\\nconst answer = [...finalMessages]\\n  .reverse()\\n  .find((message) => message.type === 'ai');\\n\\nconsole.log(answer?.content);\\n\")), mdx(\"p\", null, \"For token-level streaming, use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"streamMode: 'messages'\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"streamEvents\"), \" (see \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://docs.langchain.com/oss/javascript/langgraph/streaming\"\n  }), \"LangGraph streaming\"), \").\"), mdx(\"h3\", {\n    \"id\": \"when-to-pick-langchain\"\n  }, \"When to pick LangChain\"), mdx(\"table\", null, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  })), mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"LangChain \", mdx(\"inlineCode\", {\n    parentName: \"th\"\n  }, \"createAgent\")), mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Vercel AI SDK\"), mdx(\"th\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"OpenAI Agents SDK\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"strong\", {\n    parentName: \"td\"\n  }, \"Best for\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"RAG + LCEL + agents in one stack\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"TypeScript apps already on AI SDK\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"OpenAI-first agent primitives\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"strong\", {\n    parentName: \"td\"\n  }, \"Tool definition\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"tool()\"), \" + Zod \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"schema\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"tool()\"), \" + \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"inputSchema\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"tool()\"), \" + Zod \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"parameters\"))), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"strong\", {\n    parentName: \"td\"\n  }, \"Run API\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"agent.invoke\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"agent.stream\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"generateText\"), \" + \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"stopWhen\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"run()\"), \" + \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"maxTurns\"))), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"strong\", {\n    parentName: \"td\"\n  }, \"Handoffs / guardrails\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Middleware (advanced)\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Limited\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Built-in\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), mdx(\"strong\", {\n    parentName: \"td\"\n  }, \"Memory\")), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"LangGraph checkpointers\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Bring your own\"), mdx(\"td\", _extends({\n    parentName: \"tr\"\n  }, {\n    \"align\": null\n  }), \"Session helpers\")))), mdx(\"p\", null, \"Pick LangChain when document loaders, retrievers, and agents should share one ecosystem. Pick Vercel AI SDK or OpenAI Agents SDK when you want a focused agent layer without the broader LangChain surface.\"), mdx(\"h3\", {\n    \"id\": \"demo\"\n  }, \"Demo\"), mdx(\"p\", null, \"See the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"https://github.com/delimitertech/demos/tree/main/ai/langchain-agents-nodejs-demo\"\n  }), \"langchain-agents-nodejs-demo\"), \" folder for runnable scripts: single-tool lookup, full triage, and streaming.\"));\n}\n;\nMDXContent.isMDXComponent = true;"}},"pageContext":{"id":"0ec1c25a-ce96-53c6-af57-223b43dae638"}},"staticQueryHashes":["1961101537","2542493696"]}