> For the complete documentation index, see [llms.txt](https://docs.frayme.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.frayme.ai/agent-frameworks/langchain.md).

# LangChain.js

Give a LangChain agent the ability to generate live, interactive UI by registering Frayme's compose tool — one definition, mapped onto LangChain's `schema` field.

## The one tool definition

`@frayme/api/tools` exports a framework-neutral definition whose schema is Zod v4 (Standard Schema). LangChain's `tool()` helper accepts it as `schema` directly.

```bash
npm i @frayme/api @frayme/runtime @langchain/core @langchain/langgraph
```

```ts
// src/tools/frayme.ts
import { tool } from '@langchain/core/tools';
import Frayme from '@frayme/api';
import { createComposeTool } from '@frayme/api/tools';

const frayme = new Frayme({ apiKey: process.env.FRAYME_API_KEY });
const compose = createComposeTool(frayme);

export const fraymeCompose = tool(
  async (input) => {
    const result = await compose.execute(input);

    // Deliver the spec to your front-end OUT-OF-BAND (websocket, SSE, DB row —
    // whatever your app uses). Never return it as model-visible text: the
    // model doesn't need it, and it would waste the context window.
    await deliverSpecToClient(result.spec, result.generation_id);

    // LangChain tool results are strings — return the correlation handle only.
    return JSON.stringify({
      generation_id: result.generation_id,
      model: result.model,
      rendered: true,
    });
  },
  {
    name: compose.name, // 'frayme_compose'
    description: compose.description,
    schema: compose.inputSchema,
  },
);
```

The definition carries the full compose contract — `prompt`, `data`, `actions`, `ui_type`, the 8-verb interaction vocabulary, and three worked call examples — in its `description` and schema. No prompt engineering on your side.

## A minimal agent

```ts
// src/agent.ts
import { createReactAgent } from '@langchain/langgraph/prebuilt';
import { fraymeCompose } from './tools/frayme';

const agent = createReactAgent({
  llm, // any chat model LangChain supports — your choice
  tools: [fraymeCompose],
  prompt:
    'When an interface serves the user better than prose, call frayme_compose. ' +
    'Pass every fact the UI must show in `data`. Never print the spec as text.',
});

const result = await agent.invoke({
  messages: [
    {
      role: 'user',
      content: 'Show me this quarter\'s revenue by product line as a dashboard.',
    },
  ],
});
```

## Rendering the returned spec

On the client, render whatever spec your delivery channel hands you:

```tsx
'use client';
import { FraymeRenderer } from '@frayme/runtime/react';
import '@frayme/runtime/styles.css';

<FraymeRenderer
  spec={spec}
  skipValidation // the API already validated before billing
  onDynamicAction={(e) => {
    // { action, event, params, state, generation_id } — send it to your agent.
  }}
/>;
```

Sorting, filtering, tabs, and typing over data you supplied resolve locally in the renderer. Only the actions you declared in the compose call round-trip to your agent.

## Closing the loop

Register `frayme_action` too, so user interactions recompose the UI in context:

```ts
import { createActionTool } from '@frayme/api/tools';

const action = createActionTool(frayme);

export const fraymeAction = tool(
  async (input) => {
    const result = await action.execute(input);
    await deliverSpecToClient(result.spec, result.generation_id);
    return JSON.stringify({ generation_id: result.generation_id, rendered: true });
  },
  {
    name: action.name, // 'frayme_action'
    description: action.description,
    schema: action.inputSchema,
  },
);
```

When `onDynamicAction` fires on the client, forward the event to your agent verbatim — `{ action, event, params, state, generation_id }`. The agent calls `frayme_action` with those fields and receives a new validated spec that preserves what the user already entered.

{% hint style="info" %}
For live streaming into a LangGraph front-end, the [AG-UI adapter](/agent-frameworks/ag-ui.md) carries specs as `frayme:spec` custom events — LangGraph is on the AG-UI integrations matrix.
{% endhint %}

## Next steps

* [@frayme/api reference](/sdk-reference/api.md) — streaming, retries, typed errors
* [@frayme/runtime reference](/sdk-reference/runtime.md) — full renderer props
* [AG-UI](/agent-frameworks/ag-ui.md) — streaming transport conventions


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.frayme.ai/agent-frameworks/langchain.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
