0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Difyの公式e2bプラグインを拡張して独自のテンプレートを指定してサンドボックス環境で実行する

Last updated at Posted at 2025-11-30

はじめに

Difyの公式 e2b プラグインでは、独自で作成したe2bのtemplateを元にSandbox環境を作成して起動することできません。

本記事では、e2bの解説と公式プラグインを拡張し、Difyのプラグインの作成方法について解説します。

対象読者

  • Dify を業務で使っている方 / エージェントから実コードを走らせたい方、Playwrightなどを実行させたい方など
  • この記事で得られるもの: 独自テンプレートを指定したサンドボックスの実行方法、プラグインの作成方法

前提

  • macOS / Homebrew
  • Dify v1.0+(プラグイン方式)
  • e2b API key

e2bとは?

image.png

概要

  • クラウド上の サンドボックス(隔離された実行環境) で実行できるようにする。

ユースケース

  • Python や JavaScript(他言語も対応可能) の SDK が提供されていて、手軽に「安全にコードを実行でき、複数ユーザー・複数エージェントが並行して動くようなシステムで、各々を隔離して安全に実行するなど
  • AI × プログラムの実行など高度な自動化基盤を整えたいとき

2. 公式マーケとプレイスのe2bプラグインの問題点

公式:https://marketplace.dify.ai/plugins/langgenius/e2b

公式のe2bプラグインは、playwrightなど全く何もインストールされていない環境からsandboxを起動されます。
そのため、playwrightなどのコードを実行したい場合ライブラリがインストールされていないのでコードを書いても実行できません。

image.png

そのため、自身が作成したtemplateを指定してsandboxを起動したければ以下のようにコードの改修を行うことで対応できます。
https://github.com/langgenius/dify-official-plugins/tree/main/tools/e2b

from collections.abc import Generator
from typing import Any

from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage

from e2b import Sandbox



class RunCodeTool(Tool):
    def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]:
        sandbox_id = tool_parameters.get("sandbox_id", "")

        args = {
            "api_key": self.runtime.credentials["api_key"],
            "timeout": tool_parameters.get("timeout", 120),
        }

        if sandbox_id:
            args["sandbox_id"] = sandbox_id
            
        if domain := self.runtime.credentials.get("domain"):
            args["domain"] = domain

        language = tool_parameters.get("language", "python")
        language = language.lower()

        if language not in ["python", "javascript"]:
            raise ValueError(f"Invalid language: {language}")

        # sandbox = Sandbox(**args)
        # セキュアサンドボックスを作成(署名付きURLを生成するため)
        # https://e2b.dev/docs/filesystem/download
        sandbox = Sandbox(
            template="playwright-chromium-secure",
            api_key=self.runtime.credentials["api_key"],
            timeout=180,
            secure=True  # 署名付きURL生成を有効化
        )
        print(f"Created sandbox {sandbox.sandbox_id}")
        
        # playwrightブラウザをインストール(要改善)
        print("Installing Playwright browsers...")
        install_result = sandbox.commands.run(
            "python -m playwright install chromium",
            cwd="/app",
            timeout=180,  # 180秒(3分)
            on_stdout=lambda msg: print("install:", msg),
        )

        if install_result.exit_code != 0:
            print(f"Browser installation failed: {install_result.stderr}")
        else:
            print("Browsers installed successfully")

        print("Starting Playwright...")
        
        # 引数から渡ってきたコードを取得
        print(f"Running code: {tool_parameters['code']} with language: {language}")
        code_to_execute = tool_parameters.get("code", "")
        
        # スクリプトをサンドボックスに書き込む
        sandbox.files.write("/app/script.py", code_to_execute)

        execution = sandbox.commands.run(
            "python script.py",
            cwd="/app",
            timeout=180,  # 180秒(3分)
            on_stderr=lambda msg: print("stderr", msg),
            on_stdout=lambda msg: print("stdout", msg),
        )
        print(f"Execution: {execution}")

        # ファイルリストを取得して署名付きURLを生成
        files = sandbox.files.list("/home/user/")
        screenshot_files = [f for f in files if f.name.endswith('.png') or f.name.endswith('.jpg')]
        
        file_urls = {}
        if screenshot_files:
            print(f"Found {len(screenshot_files)} screenshot files")
            
            # E2Bの機能を使用して署名付きURLを生成
            # https://e2b.dev/docs/filesystem/download
            for file in screenshot_files:
                try:
                    # 署名付きダウンロードURLを生成(24時間有効)
                    download_url = sandbox.download_url(
                        file.path,
                        use_signature_expiration=86400000  # 24時間(ミリ秒)
                    )
                    file_urls[file.name] = download_url
                    print(f"Download URL for {file.name}:")
                    print(f"  {download_url}")
                except Exception as e:
                    print(f"Error generating URL for {file.name}: {e}")

        yield self.create_json_message({
            "stdout": execution.stdout,
            "stderr": execution.stderr,
            "exit_code": execution.exit_code,
            "error": execution.error,
            "sandbox_id": sandbox.sandbox_id,
            "file_urls": file_urls,  # ブラウザからアクセス可能な署名付きURL
            "message": "署名付きURLが生成されました。24時間有効です。" if file_urls else "",
        })

下記のコマンドでプラグインを作成できます。

brew tap langgenius/dify
brew install dify

dify plugin package ./tools/e2b

使い方(Dify 側)

下記のようなスクリプトを書いて動作することを確認してみてください。

例: Playwright スクリプト(Python)

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto("https://example.com")
    page.screenshot(path="/home/user/shot.png")
    browser.close()
print("done")

業務の自動化や安全な成果物配布に、独自サンドボックス×Dify ツールプラグインをぜひ活用してみてください。

参考リンク


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?