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

# LangChain Adapter

> Gate LangChain model access to subscribers

## Install

```bash theme={null}
npm install @stellartools/langchain-adapter @langchain/core
```

## Usage

```ts theme={null}
import { HumanMessage } from "@langchain/core/messages";
import { ChatOpenAI } from "@langchain/openai";
import { shield } from "@stellartools/langchain-adapter";

const model = shield(new ChatOpenAI({ model: "gpt-4o" }), {
  apiKey: process.env.STELLAR_TOOLS_API_KEY!,
  customerId: "cus_xxx",
  productId: "prod_xxx",
});

const result = await model.invoke([new HumanMessage("Hello")]);
```

Because `shield` returns a standard `Runnable`, it composes naturally with LCEL chains:

```ts theme={null}
import { StringOutputParser } from "@langchain/core/output_parsers";
import { ChatPromptTemplate } from "@langchain/core/prompts";

const chain = ChatPromptTemplate.fromMessages([["human", "{question}"]])
  .pipe(
    shield(new ChatOpenAI(), {
      apiKey: process.env.STELLAR_TOOLS_API_KEY!,
      customerId: "cus_xxx",
      productId: "prod_xxx",
    })
  )
  .pipe(new StringOutputParser());

const answer = await chain.invoke({ question: "What is Stellar?" });
```

## Error handling

If the customer has no active subscription for the product, `shield` throws a `ShieldError` before the model is called.

```ts theme={null}
import { ShieldError, shield } from "@stellartools/langchain-adapter";

try {
  const result = await model.invoke([new HumanMessage("Hello")]);
} catch (err) {
  if (err instanceof ShieldError) {
    return res.status(403).json({ error: err.message });
  }
  throw err;
}
```

## Config

<ParamField body="apiKey" type="string" required>
  Your StellarTools API key.
</ParamField>

<ParamField body="customerId" type="string" required>
  The StellarTools customer ID to check.
</ParamField>

<ParamField body="productId" type="string" required>
  The product the customer must have an active subscription to.
</ParamField>
