Skip to content

Commit 8ab0863

Browse files
feat(anthropic): implement Anthropic memory tool in provider package
1 parent 2265f1c commit 8ab0863

File tree

12 files changed

+610
-1
lines changed

12 files changed

+610
-1
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { ChatAnthropic, tools, StateFileSystem } from "@langchain/anthropic";
2+
3+
import { createAgent } from "langchain";
4+
5+
const model = new ChatAnthropic({
6+
model: "claude-sonnet-4-5-20250929",
7+
temperature: 0,
8+
clientOptions: {
9+
defaultHeaders: {
10+
"anthropic-beta": "context-management-2025-06-27",
11+
},
12+
},
13+
});
14+
15+
const files = {
16+
"/memories/weather_in_tokyo.txt": {
17+
content: JSON.stringify({
18+
weather: "sunny",
19+
temperature: 20,
20+
humidity: 50,
21+
wind_speed: 10,
22+
wind_direction: "N",
23+
wind_gust: 15,
24+
wind_gust_direction: "N",
25+
wind_gust_speed: 20,
26+
time: new Date().toISOString(),
27+
}),
28+
created_at: new Date().toISOString(),
29+
modified_at: new Date().toISOString(),
30+
},
31+
};
32+
const filesystem = new StateFileSystem(files, [], (files) => {
33+
Object.assign(files, files);
34+
});
35+
36+
const agent = createAgent({
37+
model,
38+
tools: [tools.memory({ filesystem })],
39+
});
40+
41+
const result = await agent.invoke({
42+
messages: "What is the weather in Tokyo?",
43+
});
44+
45+
console.log(result);

libs/providers/langchain-anthropic/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,4 @@
9595
"README.md",
9696
"LICENSE"
9797
]
98-
}
98+
}

libs/providers/langchain-anthropic/src/chat_models.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,11 @@ export class ChatAnthropicMessages<
798798
return undefined;
799799
}
800800
return tools.map((tool) => {
801+
// @ts-expect-error - tool.metadata is not typed
802+
if (isLangChainTool(tool) && tool.metadata?.providerToolDefinition) {
803+
// @ts-expect-error - tool.metadata is not typed
804+
return tool.metadata.providerToolDefinition;
805+
}
801806
if (isBuiltinTool(tool)) {
802807
return tool;
803808
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from "./chat_models.js";
22
export { convertPromptToAnthropic } from "./utils/prompts.js";
33
export { type ChatAnthropicContentBlock } from "./types.js";
4+
export * from "./tools/index.js";
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { memory, memory_20250818 } from "./memory.js";
2+
3+
export type { FileSystem } from "./utils/FileSystem.js";
4+
export { StateFileSystem } from "./utils/StateFileSystem.js";
5+
6+
export const tools = {
7+
memory_20250818,
8+
memory,
9+
};
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { tool } from "@langchain/core/tools";
2+
import type { DynamicStructuredTool, ToolRuntime } from "@langchain/core/tools";
3+
4+
import { StateFileSystem } from "./utils/StateFileSystem.js";
5+
import { CommandHandler } from "./utils/CommandHandler.js";
6+
import { handleMemoryCommand } from "./utils/index.js";
7+
import type { FileData } from "./utils/FileData.js";
8+
import type { FileSystem } from "./utils/FileSystem.js";
9+
import type { MemoryTool20250818Options } from "./types.js";
10+
11+
/**
12+
* Creates an Anthropic memory tool that can be used with ChatAnthropic.
13+
*
14+
* The memory tool enables Claude to store and retrieve information across conversations
15+
* through a memory file directory. Claude can create, read, update, and delete files that
16+
* persist between sessions, allowing it to build knowledge over time without keeping
17+
* everything in the context window.
18+
*
19+
* @example
20+
* ```typescript
21+
* import { ChatAnthropic, memory_20250818 } from "@langchain/anthropic";
22+
*
23+
* const llm = new ChatAnthropic({
24+
* model: "claude-sonnet-4-5-20250929",
25+
* clientOptions: {
26+
* defaultHeaders: {
27+
* "anthropic-beta": "context-management-2025-06-27",
28+
* },
29+
* },
30+
* });
31+
*
32+
* const memory = memory_20250818();
33+
* const llmWithMemory = llm.bindTools([memory]);
34+
*
35+
* const response = await llmWithMemory.invoke("Remember that I like Python");
36+
* ```
37+
*
38+
* @param options - Optional configuration for the memory tool (currently unused)
39+
* @returns The memory tool object that can be passed to `bindTools`
40+
*
41+
* @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/memory-tool
42+
*/
43+
export function memory_20250818(
44+
options?: MemoryTool20250818Options
45+
): DynamicStructuredTool {
46+
const memoryTool = tool(
47+
options?.execute as (
48+
input: unknown,
49+
runtime: ToolRuntime<unknown, unknown>
50+
) => string | Promise<string>,
51+
{
52+
name: "memory",
53+
description: "Memory tool",
54+
schema: {
55+
type: "object",
56+
properties: {
57+
command: {
58+
type: "string",
59+
enum: [
60+
"view",
61+
"create",
62+
"str_replace",
63+
"insert",
64+
"delete",
65+
"rename",
66+
],
67+
},
68+
},
69+
required: ["command"],
70+
},
71+
}
72+
);
73+
74+
memoryTool.metadata = {
75+
providerToolDefinition: {
76+
type: "memory_20250818",
77+
name: "memory",
78+
},
79+
};
80+
81+
return memoryTool;
82+
}
83+
84+
interface MemoryToolOptions {
85+
allowedPrefixes?: string[];
86+
filesystem?: FileSystem;
87+
}
88+
89+
/**
90+
* useful implementation
91+
*/
92+
export function memory(options?: MemoryToolOptions): DynamicStructuredTool {
93+
const filesystem: Record<string, FileData> = {};
94+
return memory_20250818({
95+
execute: async (args) => {
96+
const updates: Record<string, FileData | null> = {};
97+
const fileSystem =
98+
options?.filesystem ??
99+
new StateFileSystem(filesystem, options?.allowedPrefixes, (files) => {
100+
Object.assign(updates, files);
101+
});
102+
const commandHandler = new CommandHandler(fileSystem);
103+
return await handleMemoryCommand(commandHandler, args);
104+
},
105+
});
106+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import Anthropic from "@anthropic-ai/sdk";
2+
3+
/**
4+
* Memory tool command types as defined by Anthropic's memory tool API.
5+
* @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/memory-tool
6+
*/
7+
export type MemoryCommand =
8+
| MemoryViewCommand
9+
| MemoryCreateCommand
10+
| MemoryStrReplaceCommand
11+
| MemoryInsertCommand
12+
| MemoryDeleteCommand
13+
| MemoryRenameCommand;
14+
15+
export type MemoryViewCommand =
16+
Anthropic.Beta.BetaMemoryTool20250818ViewCommand;
17+
export type MemoryCreateCommand =
18+
Anthropic.Beta.BetaMemoryTool20250818CreateCommand;
19+
export type MemoryStrReplaceCommand =
20+
Anthropic.Beta.BetaMemoryTool20250818StrReplaceCommand;
21+
export type MemoryInsertCommand =
22+
Anthropic.Beta.BetaMemoryTool20250818InsertCommand;
23+
export type MemoryDeleteCommand =
24+
Anthropic.Beta.BetaMemoryTool20250818DeleteCommand;
25+
export type MemoryRenameCommand =
26+
Anthropic.Beta.BetaMemoryTool20250818RenameCommand;
27+
28+
/**
29+
* Options for creating a memory tool.
30+
*/
31+
export interface MemoryTool20250818Options {
32+
/**
33+
* Optional execute function that handles memory command execution.
34+
* In LangChain, this is typically handled separately when processing tool calls,
35+
* but this option is provided for compatibility with the AI SDK pattern.
36+
* Note: This option is currently unused but reserved for future use.
37+
*/
38+
execute?: (
39+
action: Anthropic.Beta.BetaMemoryTool20250818Command
40+
) => Promise<string> | string;
41+
}
42+
43+
/**
44+
* Memory tool type definition.
45+
*/
46+
export type MemoryTool = Anthropic.Beta.BetaMemoryTool20250818;

0 commit comments

Comments
 (0)