CrewAIエージェントによる重複タスクの実行を停止する方法:実践的な重複排除ガイド
タスクの所有権、依存関係、委任、再試行、フローのトリガー、状態の永続性、キャッシュ、冪等性を修正することで、CrewAIエージェントが作業を繰り返すのを防ぎます。
LangChainエージェントが長期会話中に詳細を忘れる場合、モデルのコンテキストウィンドウを増やす前にアーキテクチャを修正してください。現在のLangChain v1スタイルのエージェントでは、会話の連続性は2つの別々のレイヤーから構築されます。短期の、スレッドスコープの状態のためのチェックポインターと、スレッド間で存続しなければならない長期情報のためのストアです。長期会話にはさらに第3の懸念事項が必要です。それはコンテキスト管理であり、通常、古いメッセージがモデルを圧倒する前にそれらをトリミングまたは要約することです。
このガイドは、2026年9月11日に確認したLangChainの公式ドキュメントに従っています。現在のドキュメントでは、新しいエージェントにはlangchain.agents.create_agentを推奨しており、LangGraphの永続性を基盤となるメモリシステムとして説明しています。ConversationChain、ConversationBufferMemory、またはinitialize_agentに基づく古い例はレガシー資料にまだ現れる可能性がありますが、LangChainのv1移行ガイドでは、レガシーチェーンおよびその他の非推奨機能をlangchain-classicに移行しました。公式LangChain v1移行ガイドを参照してください。

コードを変更する前に、ユーザーの視点からは同じように見える3つの問題を分離してください。
| 症状 | 考えられる原因 | 修正すべき正しいレイヤー |
|---|---|---|
| サーバー再起動後にエージェントが忘れる | 状態がプロセスメモリ内にのみ保存されていた | 永続的なチェックポインターまたはストア |
| 同じチャット内の2つのリクエストの間でエージェントが忘れる | チェックポインターがない、または異なるthread_idが使用された | スレッド永続性 |
| エージェントはストレージ内の初期ターンを記憶しているが、非常に長いチャットではそれらを使用しなくなる | モデルのコンテキストが大きすぎるかノイズが多くなった | 要約、トリミング、検索 |
| エージェントはあるチャットでは好みを記憶しているが、新しいチャットでは記憶していない | その事実がスレッド状態内にのみ存在する | 長期ストア |
LangChainの短期メモリドキュメントは、短期メモリを単一のスレッド内の状態として定義しています。その長期メモリドキュメントは、長期メモリを異なる会話やセッションをまたいで永続化する情報として定義しています。

現在のLangChain/LangGraphアプリケーション、モデル統合、および状態を永続化するための場所が必要です。ローカルでの実験には、InMemorySaverで十分です。本番環境では、データベースバックエンドのチェックポインターを使用してください。LangChainの公式ドキュメントでは、別のパッケージlanggraph-checkpoint-postgresを介したPostgreSQLを示しています。
4つの識別子を明確に保ってください:
thread_id:1つのスレッドの状態を再開するために使用されるLangGraph永続性キー。これらは自動的に同じ値であってはなりません。1人のユーザーは多くのスレッドを持つことができ、1つのスレッドには多くの事実が含まれる可能性があります。
可能な限り最小限のテストから始めてください。エージェントに一意の詳細を記憶させ、再度呼び出してその詳細を尋ねます。永続性が破綻していても、単一のinvoke()呼び出しではモデルがその1つのリクエスト内のすべてを見ることができるため、メモリを単一の呼び出しでテストしないでください。
config = {"configurable": {"thread_id": "debug-thread-001"}}
agent.invoke(
{"messages": [{"role": "user", "content": "Remember that my project codename is Juniper."}]},
config,
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "What is my project codename?"}]},
config,
)
2番目のリクエストが「Juniper」を忘れる場合、プロンプトを変更する前に、チェックポインターの設定と実際のthread_idを確認してください。
チェックポインターは、エージェントのグラフ状態のスナップショットを永続化します。LangGraphは、短期メモリ、中断からの回復、人間参加型フロー、および耐障害性のためにこれを使用します。現在の永続性ガイドでは、チェックポインターはスレッドスコープであり、アプリケーションはthread_idを渡すことで状態にアクセスすると説明しています。公式LangGraph永続性ガイドを参照してください。
from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver
checkpointer = InMemorySaver()
agent = create_agent(
model="your-provider:your-model",
tools=[],
checkpointer=checkpointer,
)
config = {"configurable": {"thread_id": "customer-42:case-7"}}
InMemorySaverは、スレッドの接続が機能していることを確認するのに優れていますが、チェックポイントをRAMに保存します。LangGraphは、MemorySaver/InMemorySaverがプロセス再起動をまたいで永続化されないことを明確に警告しています。
最も一般的なアプリケーションレベルのバグは、すべてのHTTPリクエストで新しいthread_idを作成することです。データベースは完全に機能しているかもしれませんが、すべてのリクエストが異なるLangGraphスレッドを開始しています。
例えば、フロントエンドにチャットID chat_8bf4があるとします。その値をLangGraphスレッドに決定論的にマッピングし、そのチャットのすべてのターンで再利用してください。新しいチャットには新しいスレッドIDを割り当てるべきです。

同じユーザーに属するすべてのチャットに対して1つの永久的なthread_idを使用しないでください。これは無関係な会話を1つの状態ストリームに統合してしまいます。PostgreSQLを使用する場合、LangGraphの現在のトラブルシューティングガイダンスでは、thread_idは255文字未満に保つべきだと述べています。UUIDまたは決定論的ハッシュは、巨大なシリアライズされたオブジェクトよりも安全です。
2リクエストテストがパスしたら、プロセス再起動をテストしてください。事実を保存し、アプリケーションを停止し、再度開始し、同じスレッドIDで事実を尋ねます。まだInMemorySaverを使用している場合、忘れることは期待される動作です。
公式の短期メモリドキュメントでは、PostgresSaverを使用したPostgreSQLバックエンドの本番環境セットアップを示しています:
from langchain.agents import create_agent
from langgraph.checkpoint.postgres import PostgresSaver
DB_URI = "postgresql://user:password@db-host/app"
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
checkpointer.setup()
agent = create_agent(
model="your-provider:your-model",
tools=[],
checkpointer=checkpointer,
)
LangChainによって現在ドキュメント化されているパッケージセットアップについては、短期メモリを参照してください。実際のデータベース認証情報をソースコードに直接置かないでください。通常のシークレット管理システムを使用してください。

コンテキストウィンドウは、モデルが1回のモデル呼び出しで処理できる入力および出力コンテキストの量です。チェックポインティングはストレージに非常に長い会話を保存できますが、すべての履歴メッセージを永久にモデルに送信すべきであることを意味するわけではありません。
LangChainの短期メモリガイドは、長い履歴がモデルのコンテキストウィンドウを超える可能性があり、完全な履歴を受け入れることができるモデルであっても、古いまたはオフトピックの内容によって注意が散漫になり、レイテンシとコストが高くなる可能性があることを述べています。ドキュメント化された戦略は、トリミング、削除、要約、またはカスタムポリシーの適用です。
SummarizationMiddlewareは、最近のメッセージを保持しながら、古い履歴をコンパクトな要約に置き換えるための現在の組み込みオプションです。そのトリガーは、トークン数、メッセージ数、またはモデルコンテキストの割合に基づいて設定できます。
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware
agent = create_agent(
model="your-provider:your-model",
tools=[],
checkpointer=checkpointer,
middleware=[
SummarizationMiddleware(
model="your-provider:summary-model",
trigger=("fraction", 0.8),
keep=("fraction", 0.3),
)
],
)
上記の数字はポリシーの例であり、普遍的な設定ではありません。独自の prompts、ツール出力、モデルコンテキスト制限、レイテンシ、および要約品質を測定した後に閾値を選択してください。現在サポートされているトリガーと保持オプションについては、LangChainの組み込みミドルウェアドキュメントを参照してください。

カスタムの削除またはトリミングを実装する場合は、有効なメッセージシーケンスを保持してください。LangChainは、多くのプロバイダーがツール呼び出しを含むアシスタントメッセージの後に、対応するツール結果メッセージが続くことを要求すると警告しています。そのペアの片方を削除すると、プロバイダーエラーや混乱を招くモデル動作が発生する可能性があります。
ストアは、1つのスレッドのグラフ状態の外にあるアプリケーション定義データのLangGraph永続性レイヤーです。現在のLangChainドキュメントでは、ユーザー設定、事実、または共有アプリケーション知識など、会話をまたいで利用可能であるべき情報のためにストアを使用しています。
長期ストア項目は、名前空間とキーによって整理されたJSONドキュメントです。実用的な名前空間には、通常、ユーザーまたは組織の識別子が含まれます:
namespace = ("users", user_id, "preferences")
store.put(
namespace,
"response_style",
{"value": "concise", "source": "explicit_user_request"},
)
これはトランスクリプト全体を保存することとは異なります。製品が意図的に永続的とみなす情報を保存してください。事実がプライベートまたは規制対象である場合、「エージェントメモリ」がそれらから免除されていると仮定するのではなく、通常の保持、認可、暗号化、および削除ポリシーを適用してください。

公式の長期メモリガイドは、InMemoryStoreとPostgresStoreの両方を示しており、インメモリ実装は本番環境ではデータベースバックエンドのストアに置き換えるべきであると明確に述べています。また、PostgreSQL以外のストア統合もリストしています。「メモリ」という単語が含まれているからといってベクトルデータベースを選択するのではなく、デプロイメントと運用要件に合ったバックエンドを使用してください。
LangGraphストアは、store.search()がセマンティック類似性によって項目を取得できるようにインデックスを設定できます。これは、多くのメモリがあり、正確なキーがわからない場合に有用です。構造化された設定の小さなセットに対しては、直接の名前空間/キー検索の方が一般的にシンプルで決定論的です。
長期項目を永続化しても、エージェントがそれを使用する保証はありません。アプリケーションには依然として検索パスが必要です。現在のLangChainエージェントでは、ツールがToolRuntimeを介して提供されたストアにアクセスできます。
from dataclasses import dataclass
from langchain.tools import tool, ToolRuntime
@dataclass
class Context:
user_id: str
@tool
def get_response_style(runtime: ToolRuntime[Context]) -> str:
store = runtime.store
if store is None:
return "No memory store configured"
namespace = ("users", runtime.context.user_id, "preferences")
item = store.get(namespace, "response_style")
return item.value["value"] if item else "default"
モデル呼び出しの前に状態と永続メモリを読み取る動的プロンプトやミドルウェアを構築することもできます。重要な設計ルールは、検索パスが観察可能でテスト可能であるべきということです。「情報がデータベースのどこかに存在する」だけでは不十分です。

信頼できるメモリテストスイートは、「モデルが一度私の名前を覚えた」以上のものをカバーすべきです。少なくともこれらの4つのケースを使用してください:
| テスト | 期待される結果 |
|---|---|
| 同じスレッドIDでの2回の呼び出し | スレッドスコープの情報が利用可能 |
| 異なるスレッドIDでの2回の呼び出し | 短期スレッド履歴が漏洩しない |
| 永続的なチェックポインターでの同じスレッドIDでのアプリケーション再起動 | スレッド状態を再開できる |
| 長期ストアでの同じユーザーの新しいスレッド | 意図的に保存された永続的な事実のみが想起できる |
その後、要約閾値を超える長期会話テストを追加してください。重要な永続的な事実が生き残り、最近のツール呼び出しシーケンスが有効なままであり、プロンプトサイズが目標予算内に収まることをアサートしてください。

多くのエージェントアプリケーションにとって、堅牢な設計は次のようになります:
user_id、conversation_id、および新しいユーザーメッセージを受け取ります。conversation_idを安定したLangGraph thread_idにマッピングします。LangGraph Agent Serverを介してデプロイする場合、現在の永続性ガイドは、サーバーが永続性インフラストラクチャを自動的に処理すると述べているため、デプロイメントモデルを確認せずにそのレイヤーを重複させないでください。
これはすべてのターンで新しい会話状態を作成します。アプリケーションチャットIDの横にスレッドIDをログに記録し、再利用を確認してください。
RAMローカル状態はプロセスとともに消え、ワーカー間で共有されない可能性があります。本番環境の連続性のために永続的なバックエンドを使用してください。
チェックポインターは状態を保持しますが、増え続けるトランスクリプトがモデルにとって有用であることは保証しません。明示的なコンテキスト管理ポリシーを追加してください。
より多くのコンテキストは、自動的に優れたコンテキストになるわけではありません。現在のターンに関連する情報を取得し、最近の会話の連続性を別々に保持してください。
要約は、圧縮されたモデル生成の表現です。事実が正確でなければならない場合(アカウント識別子、契約上の制約、ユーザー承認済みの設定、またはワークフロー状態)、繰り返しの要約で生き残ることを期待するのではなく、構造化データとして保存してください。
スレッド履歴は、サイレントにグローバルなユーザープロファイルになるべきではありません。逆に、チャットをまたいでユーザーに従うべきユーザー設定は、1つのスレッド内にのみ存在すべきではありません。
例がレガシーチェーンや古いメモリクラスから始まる場合、新しいアプリケーションで使用するために、現在のv1移行およびメモリドキュメントと比較してください。
thread_idをログに記録し、比較してください。InMemorySaverを永続的なチェックポインターに置き換えてください。LangChainエージェントのメモリ喪失は、より大きなコンテキストウィンドウによって解決されることはめったにありません。まず、チェックポインターと安定したthread_idを使用してスレッド状態を永続化してください。次に、トリミングまたはSummarizationMiddlewareで長い履歴を制御してください。最後に、会話をまたいで存続しなければならない事実を名前空間化された長期ストアに配置し、意図的にそれらを取得してください。
その分離により、「メモリ」よりはるかに有用なものが得られます。ユーザーが「なぜエージェントが忘れたのですか?」と尋ねたときに、再起動、スケーリング、テスト、監査、および推論できるシステムです。
タスクの所有権、依存関係、委任、再試行、フローのトリガー、状態の永続性、キャッシュ、冪等性を修正することで、CrewAIエージェントが作業を繰り返すのを防ぎます。
米国フリーランス業務向けの個人事業主経費トラッカーを作成します。IRS対応のカテゴリー、領収書記録、2026年のマイル単価、税務レビューフラグを含みます。
労働時間計算機能、深夜シフト用数式、週次合計、品質チェック、明確な制限事項を備えた、Excelで無料の従業員シフト表を作成する方法。
テーブル、ドロップダウン、フォローアップアラート、シンプルなパイプラインサマリーを活用した実用的なExcelリードトラッカーの構築方法と、CRMへ移行すべきタイミングの明確なサインについて解説します。
サービス履歴、期限、ダウンタイム、コスト、検査記録、明確な安全基準を含む、ワークショップ資産のための実用的なエクセル設備保守記録を作成します。
Compare HubSpot Free CRM and Zoho CRM Free for solo real estate agents, including contact limits, pipelines, email, automation, mobile tools, and upgrade tradeoffs.
LM Studioを使ってWindows 11でDeepSeekをローカル実行する方法。通常のPCに最適なモデルの選び方、ダウンロードと読み込み手順、オフライン動作の確認、よくある問題の解決策を解説します。
4つの実践的なプロンプト圧縮技術、キャッシュに優しいレイアウト、構造化出力、品質を維持する評価計画を用いて、LLM APIのコストを削減します。
セルフホスト型のn8nとClaudeを使用して、構造化出力、レビューゲート、現実的なAPIコストガイダンスを備えた、ホスティング無料のAIコンテンツ再利用パイプラインを構築します。
タイムライン、ベンダー管理、見積もりと実際の費用比較、支払い、当日のタスクを含む、Word用の実用的な印刷可能なイベント企画チェックリストと予算テンプレートを活用しましょう。