*   [](/v0.2/)
*   [How-to guides](/v0.2/docs/how_to/)
*   How to add ad-hoc tool calling capability to LLMs and Chat Models

On this page

How to add ad-hoc tool calling capability to LLMs and Chat Models
=================================================================

Prerequisites

This guide assumes familiarity with the following concepts:

*   [LangChain Expression Language (LCEL)](/v0.2/docs/concepts/#langchain-expression-language)
*   [Chaining runnables](/v0.2/docs/how_to/sequence/)
*   [Tool calling](/v0.2/docs/how_to/tool_calling/)

In this guide we’ll build a Chain that does not rely on any special model APIs (like tool calling, which we showed in the [Quickstart](/v0.2/docs/how_to/tool_calling)) and instead just prompts the model directly to invoke tools.

Setup[​](#setup "Direct link to Setup")
---------------------------------------

We’ll need to install the following packages:

*   npm
*   yarn
*   pnpm

    npm i @langchain/core zod

    yarn add @langchain/core zod

    pnpm add @langchain/core zod

#### Set environment variables[​](#set-environment-variables "Direct link to Set environment variables")

    # Optional, use LangSmith for best-in-class observabilityLANGSMITH_API_KEY=your-api-keyLANGCHAIN_TRACING_V2=true

Create a tool[​](#create-a-tool "Direct link to Create a tool")
---------------------------------------------------------------

First, we need to create a tool to call. For this example, we will create a custom tool from a function. For more information on all details related to creating custom tools, please see [this guide](/v0.2/docs/how_to/custom_tools).

    import { StructuredTool } from "@langchain/core/tools";import { z } from "zod";class Multiply extends StructuredTool {  schema = z.object({    first_int: z.number(),    second_int: z.number(),  });  name = "multiply";  description = "Multiply two integers together.";  async _call(input: z.infer<typeof this.schema>) {    return (input.first_int * input.second_int).toString();  }}const multiply = new Multiply();

    console.log(multiply.name);console.log(multiply.description);

    multiplyMultiply two integers together.

    await multiply.invoke({ first_int: 4, second_int: 5 });

    20

Creating our prompt[​](#creating-our-prompt "Direct link to Creating our prompt")
---------------------------------------------------------------------------------

We’ll want to write a prompt that specifies the tools the model has access to, the arguments to those tools, and the desired output format of the model. In this case we’ll instruct it to output a JSON blob of the form `{"name": "...", "arguments": {...}}`.

    import { renderTextDescription } from "langchain/tools/render";const renderedTools = renderTextDescription([multiply]);

    import { ChatPromptTemplate } from "@langchain/core/prompts";const systemPrompt = `You are an assistant that has access to the following set of tools. Here are the names and descriptions for each tool:{rendered_tools}Given the user input, return the name and input of the tool to use. Return your response as a JSON blob with 'name' and 'arguments' keys.`;const prompt = ChatPromptTemplate.fromMessages([  ["system", systemPrompt],  ["user", "{input}"],]);

Adding an output parser[​](#adding-an-output-parser "Direct link to Adding an output parser")
---------------------------------------------------------------------------------------------

We’ll use the `JsonOutputParser` for parsing our models output to JSON.

### Pick your chat model:

*   OpenAI
*   Anthropic
*   FireworksAI
*   MistralAI
*   Groq
*   VertexAI

#### Install dependencies

tip

See [this section for general instructions on installing integration packages](/docs/get_started/installation#installing-integration-packages).

*   npm
*   yarn
*   pnpm

    npm i @langchain/openai 

    yarn add @langchain/openai 

    pnpm add @langchain/openai 

#### Add environment variables

    OPENAI_API_KEY=your-api-key

#### Instantiate the model

    import { ChatOpenAI } from "@langchain/openai";const model = new ChatOpenAI({  model: "gpt-3.5-turbo",  temperature: 0});

#### Install dependencies

tip

See [this section for general instructions on installing integration packages](/docs/get_started/installation#installing-integration-packages).

*   npm
*   yarn
*   pnpm

    npm i @langchain/anthropic 

    yarn add @langchain/anthropic 

    pnpm add @langchain/anthropic 

#### Add environment variables

    ANTHROPIC_API_KEY=your-api-key

#### Instantiate the model

    import { ChatAnthropic } from "@langchain/anthropic";const model = new ChatAnthropic({  model: "claude-3-sonnet-20240229",  temperature: 0});

#### Install dependencies

tip

See [this section for general instructions on installing integration packages](/docs/get_started/installation#installing-integration-packages).

*   npm
*   yarn
*   pnpm

    npm i @langchain/community 

    yarn add @langchain/community 

    pnpm add @langchain/community 

#### Add environment variables

    FIREWORKS_API_KEY=your-api-key

#### Instantiate the model

    import { ChatFireworks } from "@langchain/community/chat_models/fireworks";const model = new ChatFireworks({  model: "accounts/fireworks/models/firefunction-v1",  temperature: 0});

#### Install dependencies

tip

See [this section for general instructions on installing integration packages](/docs/get_started/installation#installing-integration-packages).

*   npm
*   yarn
*   pnpm

    npm i @langchain/mistralai 

    yarn add @langchain/mistralai 

    pnpm add @langchain/mistralai 

#### Add environment variables

    MISTRAL_API_KEY=your-api-key

#### Instantiate the model

    import { ChatMistralAI } from "@langchain/mistralai";const model = new ChatMistralAI({  model: "mistral-large-latest",  temperature: 0});

#### Install dependencies

tip

See [this section for general instructions on installing integration packages](/docs/get_started/installation#installing-integration-packages).

*   npm
*   yarn
*   pnpm

    npm i @langchain/groq 

    yarn add @langchain/groq 

    pnpm add @langchain/groq 

#### Add environment variables

    GROQ_API_KEY=your-api-key

#### Instantiate the model

    import { ChatGroq } from "@langchain/groq";const model = new ChatGroq({  model: "mixtral-8x7b-32768",  temperature: 0});

#### Install dependencies

tip

See [this section for general instructions on installing integration packages](/docs/get_started/installation#installing-integration-packages).

*   npm
*   yarn
*   pnpm

    npm i @langchain/google-vertexai 

    yarn add @langchain/google-vertexai 

    pnpm add @langchain/google-vertexai 

#### Add environment variables

    GOOGLE_APPLICATION_CREDENTIALS=credentials.json

#### Instantiate the model

    import { ChatVertexAI } from "@langchain/google-vertexai";const model = new ChatVertexAI({  model: "gemini-1.5-pro",  temperature: 0});

    import { JsonOutputParser } from "@langchain/core/output_parsers";const chain = prompt.pipe(model).pipe(new JsonOutputParser());await chain.invoke({  input: "what's thirteen times 4",  rendered_tools: renderedTools,});

    { name: 'multiply', arguments: [ 13, 4 ] }

Invoking the tool[​](#invoking-the-tool "Direct link to Invoking the tool")
---------------------------------------------------------------------------

We can invoke the tool as part of the chain by passing along the model-generated “arguments” to it:

    import { RunnableLambda, RunnablePick } from "@langchain/core/runnables";const chain = prompt  .pipe(model)  .pipe(new JsonOutputParser())  .pipe(new RunnablePick("arguments"))  .pipe(    new RunnableLambda({      func: (input) =>        multiply.invoke({          first_int: input[0],          second_int: input[1],        }),    })  );await chain.invoke({  input: "what's thirteen times 4",  rendered_tools: renderedTools,});

    52

Choosing from multiple tools[​](#choosing-from-multiple-tools "Direct link to Choosing from multiple tools")
------------------------------------------------------------------------------------------------------------

Suppose we have multiple tools we want the chain to be able to choose from:

    class Add extends StructuredTool {  schema = z.object({    first_int: z.number(),    second_int: z.number(),  });  name = "add";  description = "Add two integers together.";  async _call(input: z.infer<typeof this.schema>) {    return (input.first_int + input.second_int).toString();  }}const add = new Add();class Exponentiate extends StructuredTool {  schema = z.object({    first_int: z.number(),    second_int: z.number(),  });  name = "exponentiate";  description = "Exponentiate the base to the exponent power.";  async _call(input: z.infer<typeof this.schema>) {    return Math.pow(input.first_int, input.second_int).toString();  }}const exponentiate = new Exponentiate();

With function calling, we can do this like so:

If we want to run the model selected tool, we can do so using a function that returns the tool based on the model output. Specifically, our function will action return it’s own subchain that gets the “arguments” part of the model output and passes it to the chosen tool:

    import { StructuredToolInterface } from "@langchain/core/tools";const tools = [add, exponentiate, multiply];const toolChain = (modelOutput) => {  const toolMap: Record<string, StructuredToolInterface> = Object.fromEntries(    tools.map((tool) => [tool.name, tool])  );  const chosenTool = toolMap[modelOutput.name];  return new RunnablePick("arguments").pipe(    new RunnableLambda({      func: (input) =>        chosenTool.invoke({          first_int: input[0],          second_int: input[1],        }),    })  );};const toolChainRunnable = new RunnableLambda({  func: toolChain,});const renderedTools = renderTextDescription(tools);const systemPrompt = `You are an assistant that has access to the following set of tools. Here are the names and descriptions for each tool:{rendered_tools}Given the user input, return the name and input of the tool to use. Return your response as a JSON blob with 'name' and 'arguments' keys.`;const prompt = ChatPromptTemplate.fromMessages([  ["system", systemPrompt],  ["user", "{input}"],]);const chain = prompt  .pipe(model)  .pipe(new JsonOutputParser())  .pipe(toolChainRunnable);await chain.invoke({  input: "what's 3 plus 1132",  rendered_tools: renderedTools,});

    1135

Returning tool inputs[​](#returning-tool-inputs "Direct link to Returning tool inputs")
---------------------------------------------------------------------------------------

It can be helpful to return not only tool outputs but also tool inputs. We can easily do this with LCEL by `RunnablePassthrough.assign`\-ing the tool output. This will take whatever the input is to the RunnablePassrthrough components (assumed to be a dictionary) and add a key to it while still passing through everything that’s currently in the input:

    import { RunnablePassthrough } from "@langchain/core/runnables";const chain = prompt  .pipe(model)  .pipe(new JsonOutputParser())  .pipe(RunnablePassthrough.assign({ output: toolChainRunnable }));await chain.invoke({  input: "what's 3 plus 1132",  rendered_tools: renderedTools,});

    { name: 'add', arguments: [ 3, 1132 ], output: '1135' }

What’s next?[​](#whats-next "Direct link to What’s next?")
----------------------------------------------------------

This how-to guide shows the “happy path” when the model correctly outputs all the required tool information.

In reality, if you’re using more complex tools, you will start encountering errors from the model, especially for models that have not been fine tuned for tool calling and for less capable models.

You will need to be prepared to add strategies to improve the output from the model; e.g.,

*   Provide few shot examples.
*   Add error handling (e.g., catch the exception and feed it back to the LLM to ask it to correct its previous output).

* * *

#### Was this page helpful?

  

#### You can also leave detailed feedback [on GitHub](https://github.com/langchain-ai/langchainjs/issues/new?assignees=&labels=03+-+Documentation&projects=&template=documentation.yml&title=DOC%3A+%3CPlease+write+a+comprehensive+title+after+the+%27DOC%3A+%27+prefix%3E).

[

Previous

How to return structured data from a model

](/v0.2/docs/how_to/structured_output)[

Next

How to create a custom chat model class

](/v0.2/docs/how_to/custom_chat)

*   [Setup](#setup)
*   [Create a tool](#create-a-tool)
*   [Creating our prompt](#creating-our-prompt)
*   [Adding an output parser](#adding-an-output-parser)
*   [Invoking the tool](#invoking-the-tool)
*   [Choosing from multiple tools](#choosing-from-multiple-tools)
*   [Returning tool inputs](#returning-tool-inputs)
*   [What’s next?](#whats-next)