AIエージェントがより自律的で有能になるにつれて、彼らの役割は受動的なアシスタントからプロアクティブなアクターへと移行している。今日の大規模言語モデル(LLMs)はテキストを生成するだけでなく、タスクを実行し、APIにアクセスし、データベースを変更し、インフラを制御する。 AIエージェントは、会議の予定、サービスの展開、または機密文書へのアクセスを問わず、かつては厳密に人間のユーザーに限定された行動をとっている。 で、 単一の幻覚的なコマンド、誤解されたプロンプト、または過剰に広範囲な許可は、データ漏洩、コンプライアンス違反、または故障したシステムを引き起こす可能性があります。 When agents operate without guardrails they can inadvertently make harmful or unauthorized decisions だからこそ、統合 ワークフローは、エージェントの安全性と責任の確保に不可欠です。 human-in-the-loop (HITL) これは、AIエージェントが能力を持つように設計されたフレームワークです。 敏感な行動をとりながら、 . Permit.io’s Access Request MCP request humans to remain the final decision-makers Permit.ioのアクセスリクエスト MCP 建てられた 一般的なエージェントフレームワークに組み込まれており、 そして このシステムでは、承認ワークフローをLLMで動作するアプリケーションに直接挿入できます。 許可 LangChain LangGraph このチュートリアルでは、あなたは学びます: なぜ人間に敏感な許可を委任することは、信頼できるAIにとって重要なことなのか。 Permit.io の モデル コンテキスト プロトコル (MCP) がアクセス リクエスト ワークフローを可能にする方法 人間の監督とLLMのインテリジェンスを組み合わせた現実世界のシステムを構築する方法 - LangGraphのinterrupt()機能を使用します。 デモアプリケーションと実装のステップに浸透する前に、AI権限を人間に委任する重要性を短く議論しましょう。 なぜAIライセンスを人間に委任することは重要なのか AIエージェントは強力ですが、私たちが知っているように、彼らは間違いのないものではありません。 彼らは指示に従いますが、人間のように文脈を理解しません。彼らは反応を生成しますが、彼らは結果を判断できません。そして、これらのエージェントが実際のシステムに統合されるとき - 銀行ツール、内部ダッシュボード、インフラコントロール - それは危険なギャップです。 この文脈では、間違える可能性のあるすべてが非常に明確です: 過度に許容可能なエージェント:LLMは、設計または偶然に触れないべきツールへのアクセスを与えられる可能性があります。 幻想的なツール呼び出し:エージェントは、存在しないコマンド、論点、またはIDを製造することができます。 監査能力の欠如:人間のチェックポイントがなければ、誰が何を承認したのか、またはなぜそれを承認したのかの明確な記録はありません。 Delegation is the solution. エージェントに無制限のパワーを与える代わりに、我々は彼らにプロトコルを与える: 「問うことはできるが、人間は決める」 導入することによって 重要な決定ポイントでの承認、あなたは得ます: human-in-the-loop (HITL) 安全性: 起こる前に不可逆的な行動を防ぐ。 責任:高い投資のための明示的な人間のサインアウトが必要です。 コントロール: 誰が承認できるか、何が承認できるか、そしていつ承認できるかというルールを定めること。 エージェントとの違い 何かとエージェント 何かをすること。 やる 要請 そしてそれはまさに何 アクセスリクエスト MCP が可能になります。 許可 Permit.ioのアクセスリクエスト MCP 核心の一部である。 モデル・コンテキスト・プロトコル(MCP) - AI エージェントにツールやリソースへの安全でポリシー意識のあるアクセスを提供する仕様。 The Access Request MCP 許可 それを橋として考える。 そして . LLMs that want to act humans who need control 何がする Permit's Access Request MCP により、AI エージェントは: 制限されたリソースへのアクセスを要求する(例えば、「このレストランにアクセスできますか?」)。 敏感な操作を行うための承認を要求する(例えば、「この制限された皿を注文できますか?」)。 進む前に人間の入力を待つ―LangGraphのinterrupt() メカニズムを通じて 監査およびコンプライアンスに関する要求および決定のログ 舞台の裏で、使われている ’s 認可能力は、以下をサポートするために構築されています: 許可 ReBAC(Relationship-Based Access Control)とその他のFine-grained Authorization(FGA)ポリシー。 ワークフローの承認 UI、API、およびLLMコンテキストを介して動作するポリシーをサポートする要素 リバック Fine-grained Authorization(FGA)について ワークフローの承認 政策支えの要素 Plug-and-play with LangChain and LangGraph Permit の MCP は、直接に Permit に統合されます。 そして 生態系: LangChain MCP Adapter LangGraph Permit Elements を LangGraph 対応ツールとして公開できます。 敏感なアクションが発生したときに、interrupt() でエージェントを停止できます。 実際の人間の意思決定に基づいて執行を再開することができます。 最も簡単な方法は、 コードバックアップは必要ありません。 inject human judgment into AI behavior 実装とその利点を理解すると、デモアプリケーションに入ります。 What We'll Build - Demo Application Overview(デモアプリケーションの概要) このチュートリアルでは、A あるいは, 彼ら real-time approval workflow AI agent can request access or perform sensitive actions, but only a human can approve シナリオ:ファミリー食品注文システム Permit の MCP がユーザー アプリケーションで HITL ワークフローを有効にするのに役立つ方法を見るには、モデル化します。 ある家族のために: food ordering system 親は、すべてのレストランや料理にアクセスし、管理することができます。 子供は公共の物件を見ることができますが、制限されたレストランや高価な料理へのアクセスを要求する必要があります。 子供が要求を提出した場合、親はそれを検討するために受け取り、行動を進める前に明示的に承認または拒否しなければなりません。 この使用例は、共通のパターンを反映しています: 「エージェントは助けられるが、人間は決める」 テクノロジ Stack この HITL 対応エージェントを、以下を使用して構築します。 Permit.io - 権限、役割、ポリシー、および承認を扱う Permit MCP Server - Exposes エージェントが使用できるツールとしてワークフローを許可 LangChain MCP Adapters - Bridges Permit's MCP Tools into LangGraph & LangChain (LangChain MCP アダプター) LangGraph - interrupt() サポートでエージェントのワークフローをオーケストラ化 Gemini 2.0 Flash - エージェントの推論エンジンとして使用される軽量で多様なLLM Python - The glue holding it all together(ピートン) エージェントが人間と協力して安全で意図的な行動を確保できる作業システムで、リアルなポリシー、リアルなツール、リアルタイムの承認を使用します。 A repository with the full code for this application is available here. このアプリケーションの完全なコードを含むリポジトリはここで入手できます。 Step-by-Step チュートリアル このセクションでは、完全に機能するヒューマン・イン・ザ・ロック・エージェント・システムをどのように実装するかについて説明します。 ラングラフ 許可 私たちはカバーします: モデルライセンス with Permit Permit MCP Server の設定 LangGraph + LangChain MCP クライアントの作成 Human-in-the-Loop with interrupt() を追加する フルワークフローを実行する Let’s get into it - モデルライセンス with Permit まずは、システム内のアクセスルールを定義することから始めます。 これにより、ユーザーが何をできますか、および何のアクションが承認フローを引き起こすべきかをモデル化できます。 Permit.io ダッシュボード Create a ReBAC Resource Navigate to the サイドバーのページから、次のように: Policy Resources tab をクリック Click Create a Resource (リソースを作成) リソース名:レストラン Under , define two roles: ReBAC Options parent child-can-order クリック Save さて、今度は、The タブと許可の割り当て: Policy Editor parent: full access (create, read, update, delete) (作成、読む、更新、削除) : child-can-order read Set Up Permit Elements GO TO THE tab from the sidebar. In the セクション、クリック . Elements User Management Create Element Configure the element as follows: : Restaurant Requests Name : ReBAC Resource Roles Configure elements based on : restaurants Resource Type Role permission levels Level 1 – Workspace Owner: parent Assignable Roles: child-can-order CLICK 作成 新しく作成された要素カードで Get Code をクリックし、config ID: restaurant-requests を参照してください. We will use this later in the .env file. Add Operation Approval Elements Create a new element: Operation Approval : Dish Approval Name : restaurants Resource Type CLICK 作成 Then create an element: Approval Management : Dish Requests Name Get Code をクリックし、config ID: dish-requests をコピーします。 Add Test Users & Resource Instances Navigate to Directory > インスタンス Click Add Instance : restaurants Resource Type : Instance Key pizza-palace : Default Tenant (or your working tenant) Tenant ユーザータブに切り替える Click Add User : Key joe : Instance Access restaurants:pizza-palace#parent Click Save Create another user with the key henry Don’t assign a role Permit が設定されると、MCP サーバをクローン化し、ポリシーを作業エージェントに接続できます。 Permit MCP Server の設定 許可ダッシュボードでモデル化されたポリシーで、ライセンスを設定することによってそれらを生かす時が来ました。 あなたのアクセスリクエストと承認フローをAIエージェントが使用できるツールとして露出するローカルサービス。 Permit MCP server Clone and Install the MCP Server まずは、MCPサーバリポジトリをクローン化し、仮想環境を設定します。 git clone <https://github.com/permitio/permit-mcp> cd permit-mcp # Create virtual environment, activate it and install dependencies uv venv source .venv/bin/activate # For Windows: .venv\\Scripts\\activate uv pip install -e . Add Environment Configuration Create a file at the root of the project based on the provided , and fill it with the correct values from your Permit setup: あなたの許可設定から正しい値を満たす: .env .env.example bash CopyEdit RESOURCE_KEY=restaurants ACCESS_ELEMENTS_CONFIG_ID=restaurant-requests OPERATION_ELEMENTS_CONFIG_ID=dish-requests TENANT= # e.g. default LOCAL_PDP_URL= PERMIT_API_KEY= PROJECT_ID= ENV_ID= 以下のリソースを使用してこれらの値を取得できます: You can retrieve these values using the following resources: ローカル_PDP_URL PERMIT_API キー プロジェクトID ENV_ID ️注:使用中です。 このチュートリアルでは、ReBAC評価と低遅延、オフラインテストをサポートします。 ローカルPDP(Policy Decision Point) Start the Server すべての場所で、MCP サーバをローカルに実行できます: uv run -m src.permit_mcp サーバーが起動すると、エージェントがMCPプロトコルを通じて呼び出せるツールとして、設定された Permit Elements(アクセスリクエスト、承認管理など)を露出します。 LangGraph + LangChain MCP クライアントの作成 Permit MCP サーバが起動して実行されているので、AI エージェント クライアントを構築し、そのクライアントと相互作用できるようになります。 Gemini-powered LLMを使用して、どのようなアクションを取るかを決定するDynamically invoke MCP tools such as request_access, approve_operation_approval, etc. 完全に LangGraph ワークフロー内で実行 Pause for human review using interrupt() (in the next section) ポイントを繋げていきましょう。 Install Required Dependencies あなたの MCP プロジェクト ディレクトリ内で、必要なパッケージをインストールします: uv add langchain-mcp-adapters langgraph langchain-google-genai これはあなたに与える: langchain-mcp-adapters: Permit MCP ツールを LangGraph 対応ツールに自動変換 langgraph: グラフベースのワークフローをオーケストラ化するための langchain-google-genai: For interacting with Gemini 2.0 Flash より Add Google API Key あなたは API キーが必要になります。 双子の使い方 Google AI スタジオ あなたの鍵を追加する ファイル: .env GOOGLE_API_KEY=your-key-here Build the MCP Client 名前のファイルを作成する あなたのプロジェクトのルート client.py このファイルを論理的なブロックに分割します: Imports and Setup Start by importing dependencies and loading environment variables: import os from typing_extensions import TypedDict, Literal, Annotated from dotenv import load_dotenv from langchain_google_genai import ChatGoogleGenerativeAI from langgraph.graph import StateGraph, START, END from langgraph.types import Command, interrupt from langgraph.checkpoint.memory import MemorySaver from langgraph.prebuilt import ToolNode from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from langchain_mcp_adapters.tools import load_mcp_tools import asyncio from langgraph.graph.message import add_messages Then, load the environment and set up your Gemini LLM: load_dotenv() global_llm_with_tools = None llm = ChatGoogleGenerativeAI( model="gemini-2.0-flash", google_api_key=os.getenv('GOOGLE_API_KEY') ) Tell LangGraph how to communicate with the running MCP server: Configure MCP Server Parameters server_params = StdioServerParameters( command="python", args=["src/permit_mcp/server.py"], ) 共有エージェントの状態を定義する: class State(TypedDict): messages: Annotated[list, add_messages] and the : Define Workflow Nodes graph builder Here’s the logic to route between calling the LLM and invoking tools: async def call_llm(state): response = await global_llm_with_tools.ainvoke(state["messages"]) return {"messages": [response]} def route_after_llm(state) -> Literal[END, "run_tool"]: return END if len(state["messages"][-1].tool_calls) == 0 else "run_tool" async def setup_graph(tools): builder = StateGraph(State) run_tool = ToolNode(tools) builder.add_node(call_llm) builder.add_node('run_tool', run_tool) builder.add_edge(START, "call_llm") builder.add_conditional_edges("call_llm", route_after_llm) builder.add_edge("run_tool", "call_llm") memory = MemorySaver() return builder.compile(checkpointer=memory) 上記のコードでは、LLMノードとその条件付きエッジを定義しました。 ステータスのメッセージにツール呼び出しがある場合、またはグラフを終了する場合のノード. We have also defined a function to set up and compile the graph with an in-memory checkpointer. run_tool 次に、グラフから応答をストリーミングするために次のコードラインを追加し、インタラクティブなチャットループを追加し、明示的に終了するまで実行します。 and an : Stream Output and Handle Chat Input, infinite loop for user interaction async def stream_responses(graph, config, invokeWith): async for event in graph.astream(invokeWith, config, stream_mode='updates'): for key, value in event.items(): if key == 'call_llm': content = value["messages"][-1].content if content: print('\\n' + ", ".join(content) if isinstance(content, list) else content) async def chat_loop(graph): while True: try: user_input = input("\\nQuery: ").strip() if user_input in ["quit", "exit", "q"]: print("Goodbye!") break sys_m = """ Always provide the resource instance key during tool calls, as the ReBAC authorization model is being used. To obtain the resource instance key, use the list_resource_instances tool to view available resource instances. Always parse the provided data before displaying it. If the user has initially provided their ID, use that for subsequent tool calls without asking them again. """ invokeWith = {"messages": [ {"role": "user", "content": sys_m + '\\n\\n' + user_input}]} config = {"configurable": {"thread_id": "1"}} await stream_responses(graph, config, invokeWith) except Exception as e: print(f"Error: {e}") Final Assembly Add the main entry point where we will convert the Permit MCP server tool to LangGraph-compatible tools, bind our LLM to the resulting tools, set up the graph, draw it to a file, and fire up the chat loop: python CopyEdit async def main(): async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools = await load_mcp_tools(session) llm_with_tools = llm.bind_tools(tools) graph = await setup_graph(tools) global global_llm_with_tools global_llm_with_tools = llm_with_tools with open("workflow_graph.png", "wb") as f: f.write(graph.get_graph().draw_mermaid_png()) await chat_loop(graph) if __name__ == "__main__": asyncio.run(main()) Lastly, Run the Client すべてを保存すると、クライアントを開始します: uv run client.py 実行後、新しい画像ファイルが グラフが示すように作成されます。 workflow_graph.png すべてが設定されているので、今度はこのようなクエリを指定できます: Query: My user id is henry, request access to pizza palace with the reason: I am now 18, and the role child-can-order Query: My user id is joe, list all access requests Your agent is now able to call MCP tools dynamically! Human-in-the-Loop を追加する interrupt() LangGraph で動作する MCP クライアントが起動し、許可ツールが自動的に呼び出されます。 制限されたリソースへのアクセスを許可するか、高リスクの操作を承認するかのように。 sensitive, そこで、LangGraphの 役に立つようになる。 interrupt() 今度はAを追加します。 エージェントが以下のような重要なツールを呼び出そうとするたびに、ワークフローを遮断し、停止する。 human approval node 認可_アクセス_リクエスト オペレーション=承認 人間は求められるだろう。 エージェントが進む前にツールを呼び出す。 manually approve or deny Define the Human Review Node あなたの頂上に ファイル(以前) )に次の機能を追加します。 client.py setup_graph async def human_review_node(state) -> Command[Literal["call_llm", "run_tool"]]: """Handle human review process.""" last_message = state["messages"][-1] tool_call = last_message.tool_calls[-1] high_risk_tools = ['approve_access_request', 'approve_operation_approval'] if tool_call["name"] not in high_risk_tools: return Command(goto="run_tool") human_review = interrupt({ "question": "Do you approve this tool call? (yes/no)", "tool_call": tool_call, }) review_action = human_review["action"] if review_action == "yes": return Command(goto="run_tool") return Command(goto="call_llm", update={"messages": [{ "role": "tool", "content": f"The user declined your request to execute the {tool_call.get('name', 'Unknown')} tool, with arguments {tool_call.get('args', 'N/A')}", "name": tool_call["name"], "tool_call_id": tool_call["id"], }]}) このノードは、呼ばれるツールが「高いリスク」とみなされているかどうかをチェックします。 Update Graph Routing 修正 The ツールが直ちに実行する代わりに、人間のレビューノードへのルートを呼び出すように機能します。 route_after_llm def route_after_llm(state) -> Literal[END, "human_review_node"]: """Route logic after LLM processing.""" return END if len(state["messages"][-1].tool_calls) == 0 else "human_review_node" Wire in the HITL Node UPDATE THE 機能を追加する グラフのノードとして: as a node in the graph: setup_graph human_review_node async def setup_graph(tools): builder = StateGraph(State) run_tool = ToolNode(tools) builder.add_node(call_llm) builder.add_node('run_tool', run_tool) builder.add_node(human_review_node) # Add the interrupt node here builder.add_edge(START, "call_llm") builder.add_conditional_edges("call_llm", route_after_llm) builder.add_edge("run_tool", "call_llm") memory = MemorySaver() return builder.compile(checkpointer=memory) Handle Human Input During Runtime 最後に、あなたの強化を グラフが中断されたときを検出し、決定を促し、人間の入力を使用して再開する機能 . stream_responses Command(resume={"action": user_input}) クライアントを実行した後、グラフは以下のようには見えないはずです。 クライアントを起動すると、グラフグラフ( )は、LLMとツール実行段階の間のヒューマンレビューノードを含みます: workflow_graph.png これにより、 エージェントが許可を変更するか、制限を回避する可能性のある決定を下そうとするたびに。 you remain in control これにより、AIエージェントに人間の監視を成功に追加し、ツールやバックエンドの論理を書き換えることなく。 結論 このチュートリアルでは、AIエージェントを使用してセキュアで人間の意識を構築しました。 . Permit.io’s Access Request MCP で、 ラングラフ そして、 LangChain MCP アダプター Permit.ioのアクセスリクエスト MCP ラングラフ LangChain MCP アダプター エージェントがコントロールされずに操作する代わりに、我々はそれに権限を与えた。 アクセスおよび 責任あるチームのメンバーがそうする。 request defer critical decisions to human users, We covered: Permit Elements と ReBAC を使用して許可および承認フローをモデル化する方法 Permit MCP Server を介してこれらのフローを暴露する方法 自然にこれらのツールを呼び出すLangGraph駆動クライアントを構築する方法 and how to insert real-time human-in-the-loop (HITL) checks using interrupt() アクションのデモをご覧になりませんか?チェック . GitHub リポ Further Reading - Secure AI Collaboration Through a Permissions Gateway(ライセンスゲートウェイ) MCP GitHub Repo をインストール LangChain MCP アダプター ReBAC ポリシーの許可 LangGraph interrupt(参照)