{"id":8274,"date":"2023-11-30T06:44:19","date_gmt":"2023-11-30T14:44:19","guid":{"rendered":"https:\/\/live-cometml.pantheonsite.io\/?p=8274"},"modified":"2025-04-24T17:04:01","modified_gmt":"2025-04-24T17:04:01","slug":"enhancing-langchain-agents-with-custom-tools","status":"publish","type":"post","link":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/","title":{"rendered":"Enhancing LangChain Agents with Custom\u00a0Tools"},"content":{"rendered":"\n<section class=\"section section--body\">\n<div class=\"section-divider\"><\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<h2 class=\"graf graf--h4\">How to Create and Implement Custom Tools in LangChain<\/h2>\n<figure class=\"graf graf--figure\">\n<\/figure><\/div><\/div><\/section>\n\n\n\n<figure class=\"wp-block-image alignnone graf-image\"><img decoding=\"async\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1600\/0*uBapHA28HWAPK0Er\" alt=\"Enhancing LangChain Agents with Custom Tools, Comet + CometLLM\"\/><figcaption class=\"wp-element-caption\">Photo by <a href=\"https:\/\/unsplash.com\/@toddquackenbush?utm_source=medium&amp;utm_medium=referral\">Todd Quackenbush<\/a> on\u00a0<a href=\"http:\/\/Unsplash.com\">Unsplash<\/a><\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading graf graf--h4\">Preliminaries<\/h4>\n\n\n\n<pre class=\"wp-block-preformatted\"><span class=\"pre--content\">%%capture\n!pip install langchain openai duckduckgo-search youtube_search wikipedia\n\n<span class=\"hljs-keyword\">import<\/span> os\n<span class=\"hljs-keyword\">import<\/span> getpass\n\nos.environ[<span class=\"hljs-string\">\"OPENAI_API_KEY\"<\/span>] = getpass.<span class=\"hljs-built_in\">getpass<\/span>(<span class=\"hljs-string\">\"Enter Your OpenAI API Key:\"<\/span>)<\/span><\/pre>\n\n\n\n<h3 class=\"wp-block-heading graf graf--h3\">Tool Input&nbsp;Schema<\/h3>\n\n\n\n<p class=\"graf graf--p\">This is the pattern for loading tools in LangChain:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><span class=\"pre--content\"><span class=\"hljs-keyword\">from<\/span> langchain.agents <span class=\"hljs-keyword\">import<\/span> load_tools\n\ntool_names = [<span class=\"hljs-string\">'your'<\/span>, <span class=\"hljs-string\">'list'<\/span>, <span class=\"hljs-string\">'of'<\/span>, <span class=\"hljs-string\">'tools'<\/span>]\ntools = load_tools(tool_names)<\/span><\/pre>\n\n\n\n<p class=\"graf graf--p\">Some tools might require a base LLM to initialize them. You would change it to the following:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><span class=\"pre--content\"><span class=\"hljs-attr\">tools<\/span> = load_tools(tool_names, llm=llm)<\/span><\/pre>\n\n\n\n<h3 class=\"wp-block-heading graf graf--h3\">Defining Custom&nbsp;Tools<\/h3>\n\n\n\n<p class=\"graf graf--p\">Custom tools in LangChain are defined by the user to perform specific tasks or operations not provided by the native tools in the LangChain toolkit.<\/p>\n\n\n\n<p class=\"graf graf--p\">They allow users to extend the functionality of LangChain and tailor it to their specific needs. There are several reasons why you might need custom tools in LangChain:<\/p>\n\n\n\n<ul class=\"wp-block-list postList\">\n<li><strong class=\"markup--strong markup--li-strong\">Specific Use Cases:<\/strong> Custom tools allow you to address specific use cases or requirements not covered by the native tools. You can define tools that perform complex calculations, interact with external APIs, manipulate data uniquely, or integrate with other systems.<\/li>\n\n\n\n<li><strong class=\"markup--strong markup--li-strong\">Integration:<\/strong> Custom tools can integrate LangChain with other systems or tools. You can define tools that interact with external APIs, databases, or other software components to exchange data or perform actions.<\/li>\n\n\n\n<li><strong class=\"markup--strong markup--li-strong\">Automation:<\/strong> Custom tools enable you to automate repetitive tasks or workflows. By defining a custom tool, you can encapsulate a series of steps or operations into a single tool that can be easily reused and executed with different inputs.<\/li>\n\n\n\n<li><strong class=\"markup--strong markup--li-strong\">Domain-Specific Functionality:<\/strong> Custom tools allow you to incorporate domain-specific functionality into LangChain. For example, suppose you are working in the finance industry. In that case, you can define custom financial calculations or data analysis tools tailored to your needs.<\/li>\n<\/ul>\n\n\n\n<section class=\"section section--body\">\n<div class=\"section-divider\">\n<hr class=\"section-divider\">\n<\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<blockquote class=\"graf graf--pullquote\"><p>Want to learn how to build modern software with LLMs using the newest tools and techniques in the field? <a class=\"markup--anchor markup--pullquote-anchor\" href=\"https:\/\/www.comet.com\/production\/site\/llm-course\/?utm_source=Heartbeat&amp;utm_medium=referral&amp;utm_content=Medium&amp;utm_campaign=Heartbeat_LangChain_Series_HS\" target=\"_blank\" rel=\"noopener ugc nofollow\" data-href=\"https:\/\/www.comet.com\/production\/site\/llm-course\/?utm_source=Heartbeat&amp;utm_medium=referral&amp;utm_content=Medium&amp;utm_campaign=Heartbeat_LangChain_Series_HS\">Check out this free LLMOps course<\/a> from industry expert Elvis Saravia of&nbsp;DAIR.AI!<\/p><\/blockquote>\n<\/div>\n<\/div>\n<\/section>\n\n\n\n<section class=\"section section--body\">\n<div class=\"section-divider\">\n<hr class=\"section-divider\">\n<\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\">\n<h3 class=\"graf graf--h3\">Creating a custom tool in LangChain<\/h3>\n<p class=\"graf graf--p\">To define a custom tool in LangChain, you can use the <code class=\"markup--code markup--p-code\">Tool.from_function()<\/code> method or subclass the <code class=\"markup--code markup--p-code\">BaseTool<\/code> class.<\/p>\n<p class=\"graf graf--p\">The <code class=\"markup--code markup--p-code\">Tool.from_function()<\/code> method lets you quickly create a tool from a simple function. Subclassing the <code class=\"markup--code markup--p-code\">BaseTool<\/code> class provides more control over the tool&#8217;s behaviour and defines custom instance variables or propagates callbacks. Once defined, custom tools can be added to the LangChain agent using the <code class=\"markup--code markup--p-code\">initialize_agent()<\/code> method.<\/p>\n<p class=\"graf graf--p\">The agent can then execute the custom and native tools in a chain to perform complex workflows or tasks. Tool consists of several components:<\/p>\n<ul class=\"postList\">\n<li class=\"graf graf--li\"><code class=\"markup--code markup--li-code\">name<\/code> (str), is required and must be unique within a set of tools provided to an agent<\/li>\n<li class=\"graf graf--li\"><code class=\"markup--code markup--li-code\">description<\/code> (str), is optional but recommended, as an agent uses it to determine tool use<\/li>\n<li class=\"graf graf--li\"><code class=\"markup--code markup--li-code\">return_direct<\/code> (bool), defaults to False<\/li>\n<li class=\"graf graf--li\"><code class=\"markup--code markup--li-code\">args_schema<\/code> (Pydantic BaseModel), is optional but recommended and can be used to provide more information (e.g., few-shot examples) or validation for expected parameters.<\/li>\n<\/ul>\n<p class=\"graf graf--p\">Before we create a tool, let\u2019s set up our environment:<\/p>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"python\"><span class=\"pre--content\"><span class=\"hljs-keyword\">from<\/span> langchain <span class=\"hljs-keyword\">import<\/span> LLMMathChain\n<span class=\"hljs-keyword\">from<\/span> langchain.agents <span class=\"hljs-keyword\">import<\/span> AgentType, initialize_agent\n<span class=\"hljs-keyword\">from<\/span> langchain.chat_models <span class=\"hljs-keyword\">import<\/span> ChatOpenAI\n<span class=\"hljs-keyword\">from<\/span> langchain.tools <span class=\"hljs-keyword\">import<\/span> BaseTool, StructuredTool, Tool, tool, DuckDuckGoSearchRun\n\n<span class=\"hljs-keyword\">from<\/span> pydantic <span class=\"hljs-keyword\">import<\/span> BaseModel, Field\n\nllm = ChatOpenAI(temperature=<span class=\"hljs-number\">0<\/span>)<\/span><\/pre>\n<h3 class=\"graf graf--h3\">A simple&nbsp;tool<\/h3>\n<p class=\"graf graf--p\">The simplest tool is basically strings in, strings out. You pass in a query (text string), and you get a result (text string).<\/p>\n<p class=\"graf graf--p\">There are two ways you can do this:<\/p>\n<p class=\"graf graf--p\">1) Use the Tool dataclass<\/p>\n<p class=\"graf graf--p\">2) Subclass the BaseTool class<\/p>\n<h3 class=\"graf graf--h3\">Using the Tool dataclass<\/h3>\n<p class=\"graf graf--p\">This wraps functions that accept a single string input and return a string output.<\/p>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"python\"><span class=\"pre--content\">search = DuckDuckGoSearchRun()\n\nsearch_tool = Tool.from_function(\n    func=search.run,\n    name=<span class=\"hljs-string\">\"Search\"<\/span>,\n    description=<span class=\"hljs-string\">\"useful for when you need to search the internet for information\"<\/span>\n)\n\nllm_math_chain = LLMMathChain(llm=llm, verbose=<span class=\"hljs-literal\">True<\/span>)\n\nmath_tool = Tool.from_function(\n    func=llm_math_chain.run,\n    name=<span class=\"hljs-string\">\"Calculator\"<\/span>,\n    description=<span class=\"hljs-string\">\"Useful for when you are asked to perform math calculations\"<\/span>\n)\n\ntools = [search_tool, math_tool]\n\nagent = initialize_agent(\n    tools,\n    llm,\n    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n    verbose=<span class=\"hljs-literal\">True<\/span>\n)\n\nagent.run(<span class=\"hljs-string\">\"Search for the Sacramento Kings win-loss record for the entire 2022-2023 season. Add games won and games lost and multiply that result by 2\"<\/span>)<\/span><\/pre>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"plaintext\"><span class=\"pre--content\">&gt; Entering new AgentExecutor chain...\nI need to search for the Sacramento Kings win-loss record for the 2022-2023 season. Then I need to add the games won and games lost and multiply that result by 2.\nAction: Search\nAction Input: \"Sacramento Kings win-loss record 2022-2023 season\"\nObservation: Sacramento Kings 2022-2023 Schedule and Results All the scores of the games played by the Kings in the NBA 2022-23 Regular Season and the 2023 Playoffs, with teams, results, winning and losing streaks, partial and final records and evolution of the playoff series. Land Of Basketball.com Little did we know we'd be in for a historic night. With a 176-175 double-overtime win, the Kings set a new franchise single-game scoring record. The game also put both teams in the history books as the second-highest-scoring game in NBA history. 5\ufe0f\u20e3 Monk and Fox Take Over LA Schedule &amp; Results Transactions More 2022-23 Kings Pages Game Log Splits Lineups On\/Off Starting Lineups Depth Charts Referees On this page: Roster Assistant Coaches and Staff Team and Opponent Stats Team Misc Per Game Totals Per 36 Minutes Per 100 Poss Advanced Adjusted Shooting Sacramento Kings record 2022-23. Explore Sacramento Kings all-time NBA seasons record Splits including Home Games, Road Games, Last 10 Games and much more. Expected W-L: 47-35 (8th of 30) Preseason Odds: Championship +50000, Over-Under 34.5. Arena: Golden 1 Center Attendance: 715,491 (20th of 30) NBA 2023 Playoffs: Lost NBA Western Conference First Round (3-4) versus Golden State Warriors ( Series Stats) Pacific Div Champs. Kings Franchise Index. Roster &amp; Stats.\nThought:I found the Sacramento Kings' record for the 2022-2023 season, but I need to add the games won and games lost and multiply that result by 2.\nAction: Search\nAction Input: \"Sacramento Kings record 2022-2023 season\"\nObservation: Sacramento Kings 2022-2023 Schedule and Results All the scores of the games played by the Kings in the NBA 2022-23 Regular Season and the 2023 Playoffs, with teams, results, winning and losing streaks, partial and final records and evolution of the playoff series. Land Of Basketball.com 2022-23 season schedule Regular season 2022-23 game log Total: 48-34 (home: 23-18; road: 25-16) October: 2-4 (home: 1-3; road: 1-1) November : 9-5 (home: 6-1; road: 3-4) December: 8-6 (home: 4-3; road: 4-3) January : 9-6 (home: 5-4; road: 4-2) February : 8-4 (home: 2-1; road: 6-3) March : 11-5 (home: 5-4; road: 6-1) Schedule &amp; Results Transactions More 2022-23 Kings Pages Game Log Splits Lineups On\/Off Starting Lineups Depth Charts Referees An ad blocker has likely prevented this video content from loading. Please disable your ad blocker to view the video content. Regular Season Schedule Playoffs Schedule Regular Season Share &amp; Export Roster &amp; Stats Schedule &amp; Results Transactions More 2022-23 Kings Pages Game Log Splits Lineups On\/Off Starting Lineups Depth Charts Referees On this page: Roster Assistant Coaches and Staff Team and Opponent Stats Team Misc Per Game Totals Per 36 Minutes Per 100 Poss Advanced Adjusted Shooting And when the final buzzer sounded on the regular season, with 9,846 points, the team set a new single-season franchise record for points scored, surpassing the 1961-62 Cincinnati Royals by one point. Sacramento finishes Q1 at DEN with 43 points and has now scored 9,846 points this season.\nThought:I have found the Sacramento Kings' win-loss record for the 2022-2023 season. Now I need to add the games won and games lost and multiply that result by 2.\nAction: Calculator\nAction Input: 48 (games won) + 34 (games lost)\n\n&gt; Entering new LLMMathChain chain...\n48 (games won) + 34 (games lost)```text\n48 + 34\n```\n...numexpr.evaluate(\"48 + 34\")...\n\nAnswer: 82\n&gt; Finished chain.\n\nObservation: Answer: 82\nThought:I now know the final answer.\nFinal Answer: 82\n\n&gt; Finished chain.\n82<\/span><\/pre>\n<h3 class=\"graf graf--h3\">Subclassing from the BaseTool&nbsp;class<\/h3>\n<p class=\"graf graf--p\">When creating a custom tool in LangChain, you may subclass from the <code class=\"markup--code markup--p-code\">BaseTool<\/code> class when you need more control over the tool&#8217;s behaviour and want to define custom instance variables or propagate callbacks.<\/p>\n<p class=\"graf graf--p\">Subclassing from the <code class=\"markup--code markup--p-code\">BaseTool<\/code> class allows you to extend the tool&#8217;s functionality and customize its behaviour according to your requirements.<\/p>\n<p class=\"graf graf--p\">By subclassing, you can define additional methods, override existing methods, and add custom instance variables specific to your tool.<\/p>\n<p class=\"graf graf--p\">Subclassing from the BaseTool class enables you to propagate callback functions executed at specific points during the tool\u2019s execution.<\/p>\n<p class=\"graf graf--p\">Callbacks can perform additional actions or modify the tool\u2019s behaviour based on certain conditions.<\/p>\n<p class=\"graf graf--p\">See the <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/colab.research.google.com\/corgiredirector?site=https%3A%2F%2Fpython.langchain.com%2Fdocs%2Fmodules%2Fagents%2Ftools%2Fcustom_tools%23subclassing-the-basetool-class\" target=\"_blank\" rel=\"nofollow noopener\" data-href=\"https:\/\/colab.research.google.com\/corgiredirector?site=https%3A%2F%2Fpython.langchain.com%2Fdocs%2Fmodules%2Fagents%2Ftools%2Fcustom_tools%23subclassing-the-basetool-class\">documentation<\/a> for a code example.<\/p>\n<h3 class=\"graf graf--h3\">Using the <code class=\"markup--code markup--h3-code\">tool<\/code> decorator<\/h3>\n<p class=\"graf graf--p\">The <code class=\"markup--code markup--p-code\">@tool<\/code> decorator in LangChain creates a Custom Tool from a simple function.<\/p>\n<p class=\"graf graf--p\">Use the <code class=\"markup--code markup--p-code\">@tool<\/code> decorator to quickly create a Tool without needing advanced customization or defining custom instance variables. The <code class=\"markup--code markup--p-code\">@tool<\/code> decorator differs from the Tool dataclass in providing a more lightweight and function-based approach to creating a Tool. It allows you to define the Tool\u2019s functionality directly within the decorated function, making it easier to encapsulate specific tasks or operations.<\/p>\n<p class=\"graf graf--p\">To determine whether to use the <code class=\"markup--code markup--p-code\">@tool<\/code> decorator or the Tool data class, consider the level of customization and control you require for your Tool.<\/p>\n<p class=\"graf graf--p\">If you need advanced customization and want to define custom instance variables or propagate callbacks, then using the Tool dataclass and subclassing from the BaseTool class would be more suitable. However, using the decorator would be a good choice if you prefer a more straightforward and concise approach without extensive customization.<\/p>\n<p class=\"graf graf--p\">The <code class=\"markup--code markup--p-code\">@tool<\/code> decorator provides a quick and easy way to create a Custom Tool from a function. At the same time, the Tool dataclass offers more flexibility and control over the Tool&#8217;s behavior. The choice between the decorator and the Tool dataclass depends on the customization you need for your Tool.<\/p>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"python\"><span class=\"pre--content\"><span class=\"hljs-keyword\">from<\/span> langchain.tools <span class=\"hljs-keyword\">import<\/span> tool\n\n<span class=\"hljs-meta\">@tool(<span class=\"hljs-params\"><span class=\"hljs-string\">\"lower_case\"<\/span>, return_direct=<span class=\"hljs-literal\">True<\/span><\/span>)<\/span>\n<span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title function_\">to_lower_case<\/span>(<span class=\"hljs-params\"><span class=\"hljs-built_in\">input<\/span>:<span class=\"hljs-built_in\">str<\/span><\/span>) -&gt; <span class=\"hljs-built_in\">str<\/span>:\n  <span class=\"hljs-string\">\"\"\"Returns the input as all lower case.\"\"\"<\/span>\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-built_in\">input<\/span>.lower()<\/span><\/pre>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"plaintext\"><span class=\"pre--content\">StructuredTool(name='lower_case', description='lower_case(input: str) -&gt; str - Returns the input as all lower case.', args_schema=&lt;class 'pydantic.v1.main.lower_caseSchemaSchema'&gt;, return_direct=True, verbose=False, callbacks=None, callback_manager=None, tags=None, metadata=None, handle_tool_error=False, func=&lt;function to_lower_case at 0x7dd2a05f2710&gt;, coroutine=None)<\/span><\/pre>\n<p class=\"graf graf--p\">Let\u2019s add this tool to our existing list, which was defined above:<\/p>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"python\"><span class=\"pre--content\">tools.append(to_lower_case)\n\nagent = initialize_agent(\n    tools,\n    llm,\n    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n    verbose=<span class=\"hljs-literal\">True<\/span>\n)\n\nagent.run(<span class=\"hljs-string\">\"What is the Apple TV show Foundation about? Return the answer in all lower case\"<\/span>)<\/span><\/pre>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"plaintext\"><span class=\"pre--content\">&gt; Entering new AgentExecutor chain...\nI need to search for information about the Apple TV show Foundation and then return the answer in all lower case.\nAction: Search\nAction Input: \"Apple TV show Foundation\"\nObservation: Foundation season 2 will debut on Apple TV Plus on Friday, July 14. Its release date was revealed alongside the series' first official trailer, and came four months after Apple confirmed a... Foundation Episodes &amp; Images Cast &amp; Crew Trailers &amp; Videos Watch on Apple TV+ Episodes &amp; Images S2, E8 \u2022 September 1, 2023 The Last Empress Enjoiner Rue confides in Dusk about her distrust of Demerzel. Hober Mallow pulls a daring move. Day sets course for Terminus and the Foundation. published 5 September 2023 This is a high-stakes dogfight we can get behind Get ready for an explosive ninth episode of Foundation season 2 (Image credit: Apple TV Plus) Foundation season 2... published 13 July 2023 Exclusive: 'I don't know who started that rumour' 'Brother Day, there are rumors we're getting a third season. Is it true?' (Image credit: Apple TV Plus) Has Apple... Features Foundation Recap: What Happened in Season 1? Need a refresher regarding what happened in Foundation season 1? We've got a year-by-year recap of events before you jump into season 2! By...\nThought:I need to extract the relevant information about the Apple TV show Foundation from the search results.\nAction: Search\nAction Input: \"Apple TV show Foundation\"\nObservation: Foundation season 2 will debut on Apple TV Plus on Friday, July 14. Its release date was revealed alongside the series' first official trailer, and came four months after Apple confirmed a... Foundation Episodes &amp; Images Cast &amp; Crew Trailers &amp; Videos Watch on Apple TV+ Episodes &amp; Images S2, E8 \u2022 September 1, 2023 The Last Empress Enjoiner Rue confides in Dusk about her distrust of Demerzel. Hober Mallow pulls a daring move. Day sets course for Terminus and the Foundation. published 5 September 2023 This is a high-stakes dogfight we can get behind Get ready for an explosive ninth episode of Foundation season 2 (Image credit: Apple TV Plus) Foundation season 2... \"Foundation: The Official Podcast,\" a companion podcast to the drama series, is hosted by Jason Concepcion and Goyer, and produced by Pineapple Street Studios with Max Linsky, Jenna Weiss-Berman and Bari Finkel serving as executive producers. The entire first season is available now on Apple Podcasts. This is the ambitious scope of Foundation, the Apple TV Plus show adapted from the Isaac Asimov series of the same name covering centuries of in-universe history, spanning years and...\nThought:I have extracted the relevant information about the Apple TV show Foundation. Now I need to return the answer in all lower case.\nAction: lower_case\nAction Input: \"Foundation season 2 will debut on Apple TV Plus on Friday, July 14.\"\nObservation: foundation season 2 will debut on apple tv plus on friday, july 14.\n\n\n&gt; Finished chain.\nfoundation season 2 will debut on apple tv plus on friday, july 14.<\/span><\/pre>\n<h3 class=\"graf graf--h3\">Modifying existing&nbsp;tools<\/h3>\n<p class=\"graf graf--p\">You can find the available native tools in LangChain <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/github.com\/langchain-ai\/langchain\/blob\/ccb9e3ee2d4ffde1bb33c6c0df0db87aff3341bf\/libs\/langchain\/langchain\/agents\/load_tools.py#L409\" target=\"_blank\" rel=\"nofollow noopener\" data-href=\"https:\/\/github.com\/langchain-ai\/langchain\/blob\/ccb9e3ee2d4ffde1bb33c6c0df0db87aff3341bf\/libs\/langchain\/langchain\/agents\/load_tools.py#L409\">here<\/a> and look at the dictionary <code class=\"markup--code markup--p-code\">_EXTRA_OPTIONAL_TOOLS<\/code> for the key of the tool.<\/p>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"1\" data-code-block-lang=\"java\"><span class=\"pre--content\">from langchain.agents <span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-type\">load_tools<\/span>\n<span class=\"hljs-variable\">tools<\/span> <span class=\"hljs-operator\">=<\/span> load_tools([<span class=\"hljs-string\">\"wikipedia\"<\/span>], llm=llm)\n\ntools[<span class=\"hljs-number\">0<\/span>]<\/span><\/pre>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"plaintext\"><span class=\"pre--content\">WikipediaQueryRun(name='Wikipedia', description='A wrapper around Wikipedia. Useful for when you need to answer general questions about people, places, companies, facts, historical events, or other subjects. Input should be a search query.', args_schema=None, return_direct=False, verbose=False, callbacks=None, callback_manager=None, tags=None, metadata=None, handle_tool_error=False, api_wrapper=WikipediaAPIWrapper(wiki_client=&lt;module 'wikipedia' from '\/usr\/local\/lib\/python3.10\/dist-packages\/wikipedia\/__init__.py'&gt;, top_k_results=3, lang='en', load_all_available_meta=False, doc_content_chars_max=4000))<\/span><\/pre>\n<p class=\"graf graf--p\">And you can modify the fields above. For example, let\u2019s change the description.<\/p>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"python\"><span class=\"pre--content\">tools[<span class=\"hljs-number\">0<\/span>].description<\/span><\/pre>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"1\" data-code-block-lang=\"css\"><span class=\"pre--content\"><span class=\"hljs-selector-tag\">A<\/span> wrapper around Wikipedia. Useful for when you need <span class=\"hljs-selector-tag\">to<\/span> answer general questions about people, places, companies, facts, historical events, or other subjects. <span class=\"hljs-selector-tag\">Input<\/span> should be <span class=\"hljs-selector-tag\">a<\/span> search query.<\/span><\/pre>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"1\" data-code-block-lang=\"bash\"><span class=\"pre--content\">tools[0].description = <span class=\"hljs-string\">\"Use this when you are asked to search for people, places, or things.\"<\/span><\/span><\/pre>\n<h3 class=\"graf graf--h3\">Prioritizing tools over other&nbsp;tools<\/h3>\n<p class=\"graf graf--p\">This is pretty easy. All you need to do is add a description like:<\/p>\n<p class=\"graf graf--p\"><code class=\"markup--code markup--p-code\">Use this tool more than regular search if you are asked factual information about a person, place, or thing<\/code><\/p>\n<p class=\"graf graf--p\">or<\/p>\n<p class=\"graf graf--p\"><code class=\"markup--code markup--p-code\">Use this tool more than the Wikipedia tool if you are asked about current events, recent information, or news<\/code><\/p>\n<h3 class=\"graf graf--h3\">Handling Errors<\/h3>\n<p class=\"graf graf--p\">The agent will stop executing when a tool encounters an error, and the exception is missed.<\/p>\n<p class=\"graf graf--p\">If you want the agent to continue execution, you can raise a <code class=\"markup--code markup--p-code\">ToolException<\/code> and set <code class=\"markup--code markup--p-code\">handle_tool_error<\/code> accordingly. When <code class=\"markup--code markup--p-code\">ToolException<\/code> is thrown, the agent will not stop working but will handle the exception according to the <code class=\"markup--code markup--p-code\">handle_tool_error<\/code> variable of the tool. The processing result will be returned to the agent as observation and printed in red.<\/p>\n<p class=\"graf graf--p\">You can set <code class=\"markup--code markup--p-code\">handle_tool_error<\/code> to <code class=\"markup--code markup--p-code\">True<\/code>, set it as a unified string value, or set it as a function.<\/p>\n<p class=\"graf graf--p\">If set as a function, it should take a <code class=\"markup--code markup--p-code\">ToolException<\/code> as a parameter and return a str value. Please note that only raising a <code class=\"markup--code markup--p-code\">ToolException<\/code> won&#8217;t be effective. You need to first set the <code class=\"markup--code markup--p-code\">handle_tool_error<\/code> of the tool because its default value is False.<\/p>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"python\"><span class=\"pre--content\"><span class=\"hljs-keyword\">from<\/span> langchain.tools.base <span class=\"hljs-keyword\">import<\/span> ToolException\n\n<span class=\"hljs-keyword\">from<\/span> langchain.tools <span class=\"hljs-keyword\">import<\/span> DuckDuckGoSearchRun\n<span class=\"hljs-keyword\">from<\/span> langchain.agents <span class=\"hljs-keyword\">import<\/span> AgentType, initialize_agent\n<span class=\"hljs-keyword\">from<\/span> langchain.chat_models <span class=\"hljs-keyword\">import<\/span> ChatOpenAI\n<span class=\"hljs-keyword\">from<\/span> langchain.tools <span class=\"hljs-keyword\">import<\/span> Tool\n\n<span class=\"hljs-keyword\">from<\/span> langchain.chat_models <span class=\"hljs-keyword\">import<\/span> ChatOpenAI\n\n\n<span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title function_\">_handle_error<\/span>(<span class=\"hljs-params\">error: ToolException<\/span>) -&gt; <span class=\"hljs-built_in\">str<\/span>:\n    <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"hljs-string\">\"The following errors occurred during tool execution:\"<\/span>\n        + error.args[<span class=\"hljs-number\">0<\/span>]\n        + <span class=\"hljs-string\">\"Please try another tool.\"<\/span>\n    )\n\n\n<span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title function_\">search_tool1<\/span>(<span class=\"hljs-params\">s: <span class=\"hljs-built_in\">str<\/span><\/span>):\n    <span class=\"hljs-keyword\">raise<\/span> ToolException(<span class=\"hljs-string\">\"The search tool1 is not available.\"<\/span>)\n\n\n<span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title function_\">search_tool2<\/span>(<span class=\"hljs-params\">s: <span class=\"hljs-built_in\">str<\/span><\/span>):\n    <span class=\"hljs-keyword\">raise<\/span> ToolException(<span class=\"hljs-string\">\"The search tool2 is not available.\"<\/span>)\n\n\nsearch_tool3 = DuckDuckGoSearchRun()\n\ndescription = <span class=\"hljs-string\">\"useful for when you need to answer questions about current events.You should give priority to using it.\"<\/span>\n\ntools = [\n    Tool.from_function(\n        func=search_tool1,\n        name=<span class=\"hljs-string\">\"Search_tool1\"<\/span>,\n        description=description,\n        handle_tool_error=<span class=\"hljs-literal\">True<\/span>,\n    ),\n    Tool.from_function(\n        func=search_tool2,\n        name=<span class=\"hljs-string\">\"Search_tool2\"<\/span>,\n        description=description,\n        handle_tool_error=_handle_error,\n    ),\n    Tool.from_function(\n        func=search_tool3.run,\n        name=<span class=\"hljs-string\">\"Search_tool3\"<\/span>,\n        description=<span class=\"hljs-string\">\"useful for when you need to answer questions about current events\"<\/span>,\n    ),\n]\n\nagent = initialize_agent(\n    tools,\n    ChatOpenAI(temperature=<span class=\"hljs-number\">0<\/span>),\n    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n    verbose=<span class=\"hljs-literal\">True<\/span>,\n)\n\nagent.run(<span class=\"hljs-string\">\"What is the Capital of Manitoba?\"<\/span>)<\/span><\/pre>\n<pre class=\"graf graf--pre graf--preV2\" spellcheck=\"false\" data-code-block-mode=\"2\" data-code-block-lang=\"plaintext\"><span class=\"pre--content\">&gt; Entering new AgentExecutor chain...\nI should use a search tool to find the answer to this question.\nAction: Search_tool1\nAction Input: \"Capital of Manitoba\"\nObservation: The search tool1 is not available.\nThought:I should try using another search tool to find the answer.\nAction: Search_tool2\nAction Input: \"Capital of Manitoba\"\nObservation: The following errors occurred during tool execution:The search tool2 is not available.Please try another tool.\nThought:I should try using the last search tool to find the answer.\nAction: Search_tool3\nAction Input: \"Capital of Manitoba\"\nObservation: Capital: Winnipeg Population: (2021) 1,342,153 Date Of Admission: 1870 Provincial Motto: \"Glorious and Free\" Manitoba's capital and largest city is Winnipeg, the seventh most populous municipality in Canada. Winnipeg is the seat of government, home to the Legislative Assembly of Manitoba and the Provincial Court. Winnipeg, city, capital (1870) of Manitoba, Canada. It lies at the confluence of the Red and Assiniboine rivers, 40 miles (65 km) southwest of Lake Winnipeg and 60 miles (95 km) north of the U.S. state of Minnesota. Winnipeg is the economic and cultural centre of Manitoba and is at the heart of the most populous metropolitan area in central Canada. The capital of Manitoba is Winnipeg. Geographic and Economic Importance . Winnipeg is the capital of Manitoba which is the fifth most populous province of Canada. Winnipeg is situated near the longitudinal center of North America. Since it is in the middle of Canada's land mass, all rail and road traffic between Canada's East and West ... Key Facts Manitoba, a central Canadian province, boasts a diverse and fascinating geography that warrants further exploration. This comprehensive analysis delves into the province's major geographical features, including its location, climate, landforms, bodies of water, and natural resources.\nThought:I now know the final answer.\nFinal Answer: The capital of Manitoba is Winnipeg.\n\n&gt; Finished chain.\nThe capital of Manitoba is Winnipeg.<\/span><\/pre>\n<h3 class=\"graf graf--h3\">Conclusion<\/h3>\n<p class=\"graf graf--p\">In closing, the post has navigated through the sophisticated features of LangChain, showcasing how custom tools and memory elevate an agent\u2019s capabilities.<\/p>\n<p class=\"graf graf--p\">From expanding functionality with specific use cases to seamless integration and automation, LangChain agents are reshaping how we interact with AI systems. With a focus on practical implementation, the blog provides a step-by-step guide to leveraging these tools, ensuring that your AI agents are more efficient and intelligent in processing and decision-making tasks.<\/p>\n<p class=\"graf graf--p\">Whether for personal use or scaling enterprise solutions, LangChain\u2019s flexible framework offers a powerful ally in the evolving landscape of AI technology.<\/p>\n<\/div>\n<\/div>\n<\/section>\n\n\n\n<section class=\"section section--body\">\n<div class=\"section-divider\">\n<hr class=\"section-divider\">\n<\/div>\n<div class=\"section-content\">\n<div class=\"section-inner sectionLayout--insetColumn\"><\/div>\n<\/div>\n<\/section>\n","protected":false},"excerpt":{"rendered":"<p>How to Create and Implement Custom Tools in LangChain Preliminaries %%capture !pip install langchain openai duckduckgo-search youtube_search wikipedia import os import getpass os.environ[&#8220;OPENAI_API_KEY&#8221;] = getpass.getpass(&#8220;Enter Your OpenAI API Key:&#8221;) Tool Input&nbsp;Schema This is the pattern for loading tools in LangChain: from langchain.agents import load_tools tool_names = [&#8216;your&#8217;, &#8216;list&#8217;, &#8216;of&#8217;, &#8216;tools&#8217;] tools = load_tools(tool_names) Some tools [&hellip;]<\/p>\n","protected":false},"author":68,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"customer_name":"","customer_description":"","customer_industry":"","customer_technologies":"","customer_logo":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[65,7],"tags":[70,71,52,31,34],"coauthors":[166],"class_list":["post-8274","post","type-post","status-publish","format-standard","hentry","category-llmops","category-tutorials","tag-langchain","tag-language-models","tag-llm","tag-llmops","tag-prompt-engineering"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Enhancing LangChain Agents with Custom\u00a0Tools - Comet<\/title>\n<meta name=\"description\" content=\"LangChain Custom tools are defined by the user to perform specific tasks or operations not provided by the native LangChain toolkit.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Enhancing LangChain Agents with Custom\u00a0Tools\" \/>\n<meta property=\"og:description\" content=\"LangChain Custom tools are defined by the user to perform specific tasks or operations not provided by the native LangChain toolkit.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/\" \/>\n<meta property=\"og:site_name\" content=\"Comet\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/cometdotml\" \/>\n<meta property=\"article:published_time\" content=\"2023-11-30T14:44:19+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-24T17:04:01+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn-images-1.medium.com\/max\/1600\/0*uBapHA28HWAPK0Er\" \/>\n<meta name=\"author\" content=\"Harpreet Sahota\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@Cometml\" \/>\n<meta name=\"twitter:site\" content=\"@Cometml\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Harpreet Sahota\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Enhancing LangChain Agents with Custom\u00a0Tools - Comet","description":"LangChain Custom tools are defined by the user to perform specific tasks or operations not provided by the native LangChain toolkit.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/","og_locale":"en_US","og_type":"article","og_title":"Enhancing LangChain Agents with Custom\u00a0Tools","og_description":"LangChain Custom tools are defined by the user to perform specific tasks or operations not provided by the native LangChain toolkit.","og_url":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/","og_site_name":"Comet","article_publisher":"https:\/\/www.facebook.com\/cometdotml","article_published_time":"2023-11-30T14:44:19+00:00","article_modified_time":"2025-04-24T17:04:01+00:00","og_image":[{"url":"https:\/\/cdn-images-1.medium.com\/max\/1600\/0*uBapHA28HWAPK0Er","type":"","width":"","height":""}],"author":"Harpreet Sahota","twitter_card":"summary_large_image","twitter_creator":"@Cometml","twitter_site":"@Cometml","twitter_misc":{"Written by":"Harpreet Sahota","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/#article","isPartOf":{"@id":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/"},"author":{"name":"Harpreet Sahota","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/46036ab474aa916e2873daece26a28d6"},"headline":"Enhancing LangChain Agents with Custom\u00a0Tools","datePublished":"2023-11-30T14:44:19+00:00","dateModified":"2025-04-24T17:04:01+00:00","mainEntityOfPage":{"@id":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/"},"wordCount":1133,"publisher":{"@id":"https:\/\/www.comet.com\/site\/#organization"},"image":{"@id":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/#primaryimage"},"thumbnailUrl":"https:\/\/cdn-images-1.medium.com\/max\/1600\/0*uBapHA28HWAPK0Er","keywords":["LangChain","Language Models","LLM","LLMOps","Prompt Engineering"],"articleSection":["LLMOps","Tutorials"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/","url":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/","name":"Enhancing LangChain Agents with Custom\u00a0Tools - Comet","isPartOf":{"@id":"https:\/\/www.comet.com\/site\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/#primaryimage"},"image":{"@id":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/#primaryimage"},"thumbnailUrl":"https:\/\/cdn-images-1.medium.com\/max\/1600\/0*uBapHA28HWAPK0Er","datePublished":"2023-11-30T14:44:19+00:00","dateModified":"2025-04-24T17:04:01+00:00","description":"LangChain Custom tools are defined by the user to perform specific tasks or operations not provided by the native LangChain toolkit.","breadcrumb":{"@id":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/#primaryimage","url":"https:\/\/cdn-images-1.medium.com\/max\/1600\/0*uBapHA28HWAPK0Er","contentUrl":"https:\/\/cdn-images-1.medium.com\/max\/1600\/0*uBapHA28HWAPK0Er"},{"@type":"BreadcrumbList","@id":"https:\/\/www.comet.com\/site\/blog\/enhancing-langchain-agents-with-custom-tools\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.comet.com\/site\/"},{"@type":"ListItem","position":2,"name":"Enhancing LangChain Agents with Custom\u00a0Tools"}]},{"@type":"WebSite","@id":"https:\/\/www.comet.com\/site\/#website","url":"https:\/\/www.comet.com\/site\/","name":"Comet","description":"Build Better Models Faster","publisher":{"@id":"https:\/\/www.comet.com\/site\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.comet.com\/site\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.comet.com\/site\/#organization","name":"Comet ML, Inc.","alternateName":"Comet","url":"https:\/\/www.comet.com\/site\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/#\/schema\/logo\/image\/","url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2025\/01\/logo_comet_square.png","contentUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2025\/01\/logo_comet_square.png","width":310,"height":310,"caption":"Comet ML, Inc."},"image":{"@id":"https:\/\/www.comet.com\/site\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/cometdotml","https:\/\/x.com\/Cometml","https:\/\/www.youtube.com\/channel\/UCmN63HKvfXSCS-UwVwmK8Hw"]},{"@type":"Person","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/46036ab474aa916e2873daece26a28d6","name":"Harpreet Sahota","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/image\/2d21512be19ba7e19a71a803309e2a88","url":"https:\/\/secure.gravatar.com\/avatar\/a6ca5a533fc9f143a0a7428037ff652aa0633d66bf27e76ae89b955ae72a0f2d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a6ca5a533fc9f143a0a7428037ff652aa0633d66bf27e76ae89b955ae72a0f2d?s=96&d=mm&r=g","caption":"Harpreet Sahota"},"url":"https:\/\/www.comet.com\/site\/blog\/author\/theartistsofdatasciencegmail-com\/"}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/8274","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/users\/68"}],"replies":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/comments?post=8274"}],"version-history":[{"count":1,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/8274\/revisions"}],"predecessor-version":[{"id":15429,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/8274\/revisions\/15429"}],"wp:attachment":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/media?parent=8274"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/categories?post=8274"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/tags?post=8274"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/coauthors?post=8274"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}