Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions examples/src/provider/anthropic/memory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { ChatAnthropic, tools, StateFileSystem } from "@langchain/anthropic";

import { createAgent } from "langchain";

const model = new ChatAnthropic({
model: "claude-sonnet-4-5-20250929",
temperature: 0,
clientOptions: {
defaultHeaders: {
"anthropic-beta": "context-management-2025-06-27",
},
},
});

const files = {
"/memories/weather_in_tokyo.txt": {
content: JSON.stringify({
weather: "sunny",
temperature: 20,
humidity: 50,
wind_speed: 10,
wind_direction: "N",
wind_gust: 15,
wind_gust_direction: "N",
wind_gust_speed: 20,
time: new Date().toISOString(),
}),
created_at: new Date().toISOString(),
modified_at: new Date().toISOString(),
},
};
const filesystem = new StateFileSystem(files, [], (files) => {
Object.assign(files, files);
});

const agent = createAgent({
model,
tools: [tools.memory({ filesystem })],
});

const result = await agent.invoke({
messages: "What is the weather in Tokyo?",
});

console.log(result);
2 changes: 1 addition & 1 deletion libs/providers/langchain-anthropic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,4 @@
"README.md",
"LICENSE"
]
}
}
5 changes: 5 additions & 0 deletions libs/providers/langchain-anthropic/src/chat_models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,11 @@ export class ChatAnthropicMessages<
return undefined;
}
return tools.map((tool) => {
// @ts-expect-error - tool.metadata is not typed
if (isLangChainTool(tool) && tool.metadata?.providerToolDefinition) {
// @ts-expect-error - tool.metadata is not typed
return tool.metadata.providerToolDefinition;
}
if (isBuiltinTool(tool)) {
return tool;
}
Expand Down
1 change: 1 addition & 0 deletions libs/providers/langchain-anthropic/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./chat_models.js";
export { convertPromptToAnthropic } from "./utils/prompts.js";
export { type ChatAnthropicContentBlock } from "./types.js";
export * from "./tools/index.js";
9 changes: 9 additions & 0 deletions libs/providers/langchain-anthropic/src/tools/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { memory, memory_20250818 } from "./memory.js";

export type { FileSystem } from "./utils/FileSystem.js";
export { StateFileSystem } from "./utils/StateFileSystem.js";

export const tools = {
memory_20250818,
memory,
};
106 changes: 106 additions & 0 deletions libs/providers/langchain-anthropic/src/tools/memory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { tool } from "@langchain/core/tools";
import type { DynamicStructuredTool, ToolRuntime } from "@langchain/core/tools";

import { StateFileSystem } from "./utils/StateFileSystem.js";
import { CommandHandler } from "./utils/CommandHandler.js";
import { handleMemoryCommand } from "./utils/index.js";
import type { FileData } from "./utils/FileData.js";
import type { FileSystem } from "./utils/FileSystem.js";
import type { MemoryTool20250818Options } from "./types.js";

/**
* Creates an Anthropic memory tool that can be used with ChatAnthropic.
*
* The memory tool enables Claude to store and retrieve information across conversations
* through a memory file directory. Claude can create, read, update, and delete files that
* persist between sessions, allowing it to build knowledge over time without keeping
* everything in the context window.
*
* @example
* ```typescript
* import { ChatAnthropic, memory_20250818 } from "@langchain/anthropic";
*
* const llm = new ChatAnthropic({
* model: "claude-sonnet-4-5-20250929",
* clientOptions: {
* defaultHeaders: {
* "anthropic-beta": "context-management-2025-06-27",
* },
* },
* });
*
* const memory = memory_20250818();
* const llmWithMemory = llm.bindTools([memory]);
*
* const response = await llmWithMemory.invoke("Remember that I like Python");
* ```
*
* @param options - Optional configuration for the memory tool (currently unused)
* @returns The memory tool object that can be passed to `bindTools`
*
* @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/memory-tool
*/
export function memory_20250818(
options?: MemoryTool20250818Options
): DynamicStructuredTool {
const memoryTool = tool(
options?.execute as (
input: unknown,
runtime: ToolRuntime<unknown, unknown>
) => string | Promise<string>,
{
name: "memory",
description: "Memory tool",
schema: {
type: "object",
properties: {
command: {
type: "string",
enum: [
"view",
"create",
"str_replace",
"insert",
"delete",
"rename",
],
},
},
required: ["command"],
},
}
);

memoryTool.metadata = {
providerToolDefinition: {
type: "memory_20250818",
name: "memory",
},
};

return memoryTool;
}

interface MemoryToolOptions {
allowedPrefixes?: string[];
filesystem?: FileSystem;
}

/**
* useful implementation
*/
export function memory(options?: MemoryToolOptions): DynamicStructuredTool {
const filesystem: Record<string, FileData> = {};
return memory_20250818({
execute: async (args) => {
const updates: Record<string, FileData | null> = {};
const fileSystem =
options?.filesystem ??
new StateFileSystem(filesystem, options?.allowedPrefixes, (files) => {
Object.assign(updates, files);
});
const commandHandler = new CommandHandler(fileSystem);
return await handleMemoryCommand(commandHandler, args);
},
});
}
46 changes: 46 additions & 0 deletions libs/providers/langchain-anthropic/src/tools/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import Anthropic from "@anthropic-ai/sdk";

/**
* Memory tool command types as defined by Anthropic's memory tool API.
* @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/memory-tool
*/
export type MemoryCommand =
| MemoryViewCommand
| MemoryCreateCommand
| MemoryStrReplaceCommand
| MemoryInsertCommand
| MemoryDeleteCommand
| MemoryRenameCommand;

export type MemoryViewCommand =
Anthropic.Beta.BetaMemoryTool20250818ViewCommand;
export type MemoryCreateCommand =
Anthropic.Beta.BetaMemoryTool20250818CreateCommand;
export type MemoryStrReplaceCommand =
Anthropic.Beta.BetaMemoryTool20250818StrReplaceCommand;
export type MemoryInsertCommand =
Anthropic.Beta.BetaMemoryTool20250818InsertCommand;
export type MemoryDeleteCommand =
Anthropic.Beta.BetaMemoryTool20250818DeleteCommand;
export type MemoryRenameCommand =
Anthropic.Beta.BetaMemoryTool20250818RenameCommand;

/**
* Options for creating a memory tool.
*/
export interface MemoryTool20250818Options {
/**
* Optional execute function that handles memory command execution.
* In LangChain, this is typically handled separately when processing tool calls,
* but this option is provided for compatibility with the AI SDK pattern.
* Note: This option is currently unused but reserved for future use.
*/
execute?: (
action: Anthropic.Beta.BetaMemoryTool20250818Command
) => Promise<string> | string;
}

/**
* Memory tool type definition.
*/
export type MemoryTool = Anthropic.Beta.BetaMemoryTool20250818;
Loading
Loading