deep-agents-memory について
deep-agents-memoryは、Deep Agentsのファイルおよびメモリ用バックエンドの設定を解説します。スレッド内の一時ファイル、セッションをまたぐ保存、ローカルファイルへのアクセスを選ぶための情報を、パス振り分けやアクセス制限とともに提供します。
主な機能
- 01StateBackendによるスレッド単位のファイル保存
- 02StoreBackendによるセッション横断メモリ
- 03CompositeBackendによるパス振り分け
- 04ファイル操作ツールの提供
- 05仮想モードによるパスアクセス制限
活用シーン
- 01単一スレッド内で一時ファイルを保持
- 02Agentセッション間でメモリを共有
- 03特定のパスを永続ストレージに振り分け
- 04ローカル開発でファイル変更を人が確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ langchain-ai/ langchain-skills --skill deep-agents-memoryインストール後、Claude Code で/deep-agents-memoryを入力して読み込まれたか確認します。
詳細
Deep Agents は、ファイル操作とメモリにプラグイン可能なバックエンドを使用します。
デフォルトの StateBackend は、スレッド内でファイルを一時的に保存します。
短期(StateBackend):単一スレッド内で保持され、スレッド終了時に失われます 長期(StoreBackend):スレッドやセッションをまたいで保持されます ハイブリッド(CompositeBackend):異なるパスを異なるバックエンドに振り分けます
FilesystemMiddleware は次のツールを提供します:ls、read_file、write_file、edit_file、glob、grep
| ユースケース | バックエンド | 理由 |
|---|---|---|
| 一時的な作業ファイル | StateBackend | デフォルトで、セットアップ不要 |
| ローカル開発用 CLI | FilesystemBackend | ディスクに直接アクセス |
| セッションをまたぐメモリ | StoreBackend | スレッドをまたいで保持 |
| ハイブリッドストレージ | CompositeBackend | 一時的なストレージと永続ストレージを組み合わせ |
from deepagents import create_deep_agent
agent = create_deep_agent() # Default: StateBackend
result = agent.invoke({
"messages": [{"role": "user", "content": "Write notes to /draft.txt"}]
}, config={"configurable": {"thread_id": "thread-1"}})
# /draft.txt is lost when thread ends
デフォルトの StateBackend は、スレッド内でファイルを一時的に保存します。
import { createDeepAgent } from "deepagents";
const agent = await createDeepAgent(); // Default: StateBackend
const result = await agent.invoke({
messages: [{ role: "user", content: "Write notes to /draft.txt" }]
}, { configurable: { thread_id: "thread-1" } });
// /draft.txt is lost when thread ends
CompositeBackend を設定し、パスを異なるストレージバックエンドに振り分けます。
from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
composite_backend = lambda rt: CompositeBackend(
default=StateBackend(rt),
routes={"/memories/": StoreBackend(rt)}
)
agent = create_deep_agent(backend=composite_backend, store=store)
# /draft.txt -> ephemeral (StateBackend)
# /memories/user-prefs.txt -> persistent (StoreBackend)
CompositeBackend を設定し、パスを異なるストレージバックエンドに振り分けます。
import { createDeepAgent, CompositeBackend, StateBackend, StoreBackend } from "deepagents";
import { InMemoryStore } from "@langchain/langgraph";
const store = new InMemoryStore();
const agent = await createDeepAgent({
backend: (config) => new CompositeBackend(
new StateBackend(config),
{ "/memories/": new StoreBackend(config) }
),
store
});
// /draft.txt -> ephemeral (StateBackend)
// /memories/user-prefs.txt -> persistent (StoreBackend)
/memories/ 内のファイルは、StoreBackend による振り分けを通じてスレッドをまたいで保持されます。
# Using CompositeBackend from previous example
config1 = {"configurable": {"thread_id": "thread-1"}}
agent.invoke({"messages": [{"role": "user", "content": "Save to /memories/style.txt"}]}, config=config1)
config2 = {"configurable": {"thread_id": "thread-2"}}
agent.invoke({"messages": [{"role": "user", "content": "Read /memories/style.txt"}]}, config=config2)
# Thread 2 can read file saved by Thread 1
/memories/ 内のファイルは、StoreBackend による振り分けを通じてスレッドをまたいで保持されます。
// Using CompositeBackend from previous example
const config1 = { configurable: { thread_id: "thread-1" } };
await agent.invoke({ messages: [{ role: "user", content: "Save to /memories/style.txt" }] }, config1);
const config2 = { configurable: { thread_id: "thread-2" } };
await agent.invoke({ messages: [{ role: "user", content: "Read /memories/style.txt" }] }, config2);
// Thread 2 can read file saved by Thread 1
実際のディスクアクセスと人間が介在するワークフローを利用したローカル開発には、FilesystemBackend を使用します。
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend
from langgraph.checkpoint.memory import MemorySaver
agent = create_deep_agent(
backend=FilesystemBackend(root_dir=".", virtual_mode=True), # Restrict access
interrupt_on={"write_file": True, "edit_file": True},
checkpointer=MemorySaver()
)
# Agent can read/write actual files on disk
実際のディスクアクセスと人間が介在するワークフローを利用したローカル開発には、FilesystemBackend を使用します。
import { createDeepAgent, FilesystemBackend } from "deepagents";
import { MemorySaver } from "@langchain/langgraph";
const agent = await createDeepAgent({
backend: new FilesystemBackend({ rootDir: ".", virtualMode: true }),
interruptOn: { write_file: true, edit_file: true },
checkpointer: new MemorySaver()
});
セキュリティ:ウェブサーバーでは FilesystemBackend を決して使用しないでください。代わりに StateBackend またはサンドボックスを使用してください。
長期メモリ操作のため、カスタムツールからストアに直接アクセスします。from langchain.tools import tool, ToolRuntime
from langchain.agents import create_agent
from langgraph.store.memory import InMemoryStore
@tool
def get_user_preference(key: str, runtime: ToolRuntime) -> str:
"""Get a user preference from long-term storage."""
store = runtime.store
result = store.get(("user_prefs",), key)
return str(result.value) if result else "Not found"
@tool
def save_user_preference(key: str, value: str, runtime: ToolRuntime) -> str:
"""Save a user preference to long-term storage."""
store = runtime.store
store.put(("user_prefs",), key, {"value": value})
return f"Saved {key}={value}"
store = InMemoryStore()
agent = create_agent(
model="gpt-4.1",
tools=[get_user_preference, save_user_preference],
store=store
)
### エージェントが設定できるもの
- バックエンドの種類と設定
- CompositeBackend の振り分けルール
- FilesystemBackend のルートディレクトリ
- ファイル操作で人間が介在するワークフロー
エージェントが設定できないもの
- ツール名(ls、read_file、write_file、edit_file、glob、grep)
- virtual_mode の制限外にあるファイルへのアクセス
- 適切なバックエンド設定なしでのスレッドをまたいだファイルアクセス
# WRONG
agent = create_deep_agent(backend=lambda rt: StoreBackend(rt))
# CORRECT
agent = create_deep_agent(backend=lambda rt: StoreBackend(rt), store=InMemoryStore())
StoreBackend にはストアのインスタンスが必要です。
// WRONG
const agent = await createDeepAgent({ backend: (c) => new StoreBackend(c) });
// CORRECT
const agent = await createDeepAgent({ backend: (c) => new StoreBackend(c), store: new InMemoryStore() });
StateBackend のファイルはスレッド単位です。スレッドをまたいでアクセスするには、同じ thread_id を使用するか、StoreBackend を使用してください。
# WRONG: thread-2 can't read file from thread-1
agent.invoke({"messages": [...]}, config={"configurable": {"thread_id": "thread-1"}}) # Write
agent.invoke({"messages": [...]}, config={"configurable": {"thread_id": "thread-2"}}) # File not found!
StateBackend のファイルはスレッド単位です。スレッドをまたいでアクセスするには、同じ thread_id を使用するか、StoreBackend を使用してください。
// WRONG: thread-2 can't read file from thread-1
await agent.invoke({ messages: [...] }, { configurable: { thread_id: "thread-1" } }); // Write
await agent.invoke({ messages: [...] }, { configurable: { thread_id: "thread-2" } }); // File not found!
永続化するには、パスが CompositeBackend のルートプレフィックスと一致する必要があります。
# With routes={"/memories/": StoreBackend(rt)}:
agent.invoke(...) # /prefs.txt -> ephemeral (no match)
agent.invoke(...) # /memories/prefs.txt -> persistent (matches route)
永続化するには、パスが CompositeBackend のルートプレフィックスと一致する必要があります。
// With routes: { "/memories/": StoreBackend }:
await agent.invoke(...); // /prefs.txt -> ephemeral (no match)
await agent.invoke(...); // /memories/prefs.txt -> persistent (matches route)
本番環境では PostgresStore を使用してください(InMemoryStore は再起動時に失われます)。
# WRONG # CORRECT
store = InMemoryStore() store = PostgresStore(connection_string="postgresql://...")
本番環境では PostgresStore を使用してください(InMemoryStore は再起動時に失われます)。
// WRONG // CORRECT
const store = new InMemoryStore(); const store = new PostgresStore({ connectionString: "..." });
virtual_mode=True を有効にして、パスアクセスを制限します(../ や ~/ による範囲外へのアクセスを防ぎます)。
backend = FilesystemBackend(root_dir="/project", virtual_mode=True) # Secure
CompositeBackend は、最長のプレフィックスを最初に照合します。
routes = {"/mem/": StoreBackend(rt), "/mem/temp/": StateBackend(rt)}
# /mem/file.txt -> StoreBackend, /mem/temp/file.txt -> StateBackend (longer match)
コメント
Markdown 対応