> ## Documentation Index
> Fetch the complete documentation index at: https://docs.refile.co/llms.txt
> Use this file to discover all available pages before exploring further.

# LangChainJS

> Use refile with LangChain

This guide explains how to integrate Refile's PDF generation capabilities with [LangChain.js](https://js.langchain.com/) in just a few lines of code. This integration allows LLMs to generate PDFs directly from markdown content as part of their response flow.

## Prerequisites

* A refile API key (available from your [refile dashboard](https://refile.co/dashboard))
* Node.js project with LangChain.js installed
* Basic familiarity with LangChain.js usage patterns

## Quick Start

1. Install the dependencies:

```bash theme={null}
npm install @langchain/openai @langchain/core zod
```

2. Copy the refile tool code and use it with LangChain:

<CodeGroup>
  ```javascript index.js theme={null}
  import { createRefileTool } from "./refileTool.js";
  import { ChatOpenAI } from "@langchain/openai";
  import { HumanMessage } from "@langchain/core/messages";

  // Initialize the OpenAI chat model
  const model = new ChatOpenAI({
  	temperature: 0,
  	modelName: "gpt-4o", // You can change to a different model as needed
  	openAIApiKey: "<token>",
  });

  // Create the refile tool
  const refileTool = createRefileTool("<token>");

  // Bind the tool to the model
  const llmWithTool = model.bindTools([refileTool]);

  // Create a messages array to track conversation
  const messages = [
  	new HumanMessage(
  		"Create a research report on the rainforests of the Amazon as a PDF. Include sections on biodiversity, conservation efforts, and threats. Reply with the URL."
  	),
  ];

  // Get the initial response from the model
  const aiMessage = await llmWithTool.invoke(messages);
  console.log("Initial AI response:", aiMessage);

  // Add the AI's response to the messages
  messages.push(aiMessage);

  // Check if there are tool calls to execute
  if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {
  	// Process each tool call
  	for (const toolCall of aiMessage.tool_calls) {
  		console.log(`Executing tool call: ${toolCall.name}`);

  		// Execute the tool with the tool call
  		const toolMessage = await refileTool.invoke(toolCall);

  		// Add the tool result to the messages
  		messages.push(toolMessage);
  	}

  	// Get the final response with the tool results
  	const finalResponse = await llmWithTool.invoke(messages);
  	console.log("Final response:", finalResponse);
  } else {
  	// No tool calls were made
  	console.log("No tool calls were made.");
  }
  ```

  ```javascript refileTool.js theme={null}
  import { DynamicStructuredTool } from "@langchain/core/tools";
  import { z } from "zod";

  /**
   * Creates a LangChain tool for generating PDFs from markdown text using the Refile API
   *
   * @param {string} refileApiKey - Your Refile API key
   * @param {string} [theme="modern"] - PDF theme (e.g., "modern", "minimal", "academic")
   * @param {string} [pageNumeration="center"] - Page number position ("center", "right", "none")
   * @param {string} [pageSize="A4"] - Page size (e.g., "A4", "Letter", "Legal")
   * @param {string} [refileApiBaseUrl="https://www.refile.co/api/v1"] - Refile API base URL
   * @returns {DynamicStructuredTool} - LangChain compatible tool for PDF generation
   */
  export function createRefileTool(
  	refileApiKey,
  	theme = "modern",
  	pageNumeration = "center",
  	pageSize = "A4",
  	refileApiBaseUrl = "https://www.refile.co/api/v1"
  ) {
  	return new DynamicStructuredTool({
  		name: "generatePdf",
  		description: "Generate a PDF document from markdown text",
  		schema: z.object({
  			markdown: z
  				.string()
  				.describe("The markdown content to convert into a PDF"),
  		}),
  		func: async ({ markdown }) => {
  			// Prepare request options
  			const options = {
  				method: "POST",
  				headers: {
  					"Content-Type": "application/json",
  					Authorization: `Bearer ${refileApiKey}`,
  				},
  				body: JSON.stringify({
  					markdown: markdown,
  					theme: theme,
  					pageNumeration: pageNumeration,
  					pageSize: pageSize,
  					output: "url",
  				}),
  			};

  			try {
  				// Make the API call
  				const response = await fetch(
  					`${refileApiBaseUrl}/pdf/markdown`,
  					options
  				);

  				if (!response.ok) {
  					const errorData = await response.json().catch(() => null);
  					throw new Error(
  						`Failed to generate PDF: ${response.status} ${response.statusText}${
  							errorData ? ` - ${JSON.stringify(errorData)}` : ""
  						}`
  					);
  				}

  				// Parse and return the response
  				const data = await response.json();
  				return JSON.stringify({
  					url: data.url,
  					success: true,
  					message: "PDF generated successfully",
  				});
  			} catch (error) {
  				console.error("Error generating PDF:", error);
  				return JSON.stringify({
  					success: false,
  					error: error.message,
  					message: "Failed to generate PDF",
  				});
  			}
  		},
  	});
  }
  ```
</CodeGroup>

3. Replace `<token>` with your refile API key and start generating PDFs!

## How It Works

The integration follows these steps:

1. **Create the tool**: The `createRefileTool` function creates a LangChain-compatible tool that connects to the Refile API
2. **Bind the tool to the model**: Use LangChain's `bindTools` method to give the model access to the PDF generation capability
3. **Process tool calls**: When the model decides to generate a PDF, it makes a tool call which your code executes
4. **Return results**: The final result includes the URL of the generated PDF

### Customization Options

Want a different look? Just change these parameters when calling `createRefileTool()`:

```javascript theme={null}
createRefileTool(
	"your-api-key",
	"basic", // theme: "modern", "basic"
	"right", // page numbers: "center", "right", "left", "none"
	"Letter" // page size: "A4", "Letter", "Legal", etc.
);
```

Remember to keep your API key safe by using environment variables in production and never exposing your key in client side code!

For a detailed explanation of the API and all configuration options, visit the [API reference](/api-reference).
