ローコードAIツールDifyをエンジニアが使ったら?コードブロックでハマった7つの落とし穴

こんにちは、AIテクノロジーグループの辻埜です。 本記事は Enigmo Advent Calendar 2025 の12日目の記事です。

普段はデータサイエンティストとして機械学習を用いたシステムの開発運用や、社内のAI活用推進を担当しています。

近年、生成AIの活用が進む中で、エニグモでも社内のAI活用を推進するため、Difyという生成AIアプリ開発ツールを活用した取り組みを行っています。Difyは非エンジニアでもAIを組み込んだワークフローを簡単に構築できるツールです。

dify.ai

社内での導入初期に、使い勝手はどうか?どんな場面で有用か?を調査するため自分でも使ってみたところ、いくつかの課題に直面しました。

この記事では、実際にDifyを使ってワークフローを構築するにあたって苦労した点についてご紹介します。Difyを導入検討している方や、すでに使用している方の参考になれば幸いです。

なお、記事内でDifyのセキュリティ機能の変更について触れていますが、今回の用途としては完全に社内の一部ユーザーに閉じた環境での使用だったため、変更内容に問題がないと判断した上で実施しています。 外部に公開する場合や、不特定多数の利用者によって使用される場合は、セキュリティには十分ご注意ください。

前提(使用した環境)

  • Difyのバージョン: 1.4.1
  • 利用形態: セルフホスト版
  • 実行環境: Compute Engine(GCP)

Difyでやったこと

今回構築したのは、スプレッドシートから情報を読み込んで、外部APIで取得した情報と結合して、新しいスプレッドシートに出力するというワークフローです。

Difyではブロックという単位で機能を繋げていき、ワークフローを構築していきます。ブロックには様々な種類があり、IF/ELSE処理やLLMの呼び出し、RAGの実装までGUI上で簡単に構築ができます。
最初はそれらのブロックを組み合わせてワークフローを構築していたのですが、データをあれこれ変換しようとするとだんだんと標準ブロックだけでは対応が難しくなっていきました。

そんな私のようなわがままなケースに対応するため、Difyでは「コードブロック」を使用することで、Pythonコードを実行して自由に処理をすることができます。普段コードを書いている身からすると、やりたいことをささっと記述して実現できるのでとても便利な機能でした。

コードブロックの落とし穴

少々複雑な処理もコードを使ってしまえば簡単にかけてしまうためとても便利なのですが、使っているとなかなか思うように使えず苦労するケースがいくつかでてきました。

1. エディタの機能が限定的

Difyのコードブロックは、ブラウザ上で動作する簡易的なエディタで、簡単なシンタックスハイライトはあるものの、近年のエディタに搭載されているような各種機能は搭載されていません。

そのため、普段使っているエディタのショートカット機能などが使えない他、最近流行りのAIエディタのようなコード補完機能も使うことができませんでした。 どうしてもAIの力を借りたい時にはローカルのエディタでコードを書いてから、Difyにコピー&ペーストするという手間が発生しました。

2. 外部ライブラリを使う方法が難しい

さらに使っていくと、外部ライブラリを使いたい時に簡単に導入することができないことに気づきました。 コードブロックではデフォルトでは実行環境に事前にインストールされているライブラリしか使用できず、使いたい外部ライブラリがある場合は自分で一手間加えて導入する必要があります。

ライブラリの指定

外部ライブラリを使うには、まずリポジトリ内の./docker/volumes/sandbox/dependenciesにあるpython-requirements.txtにライブラリの追加をする必要があります。 書き方は通常のPythonrequirements.txtと同じです。

pandas==2.3.3
gspread==6.2.1

システムコールの許可

python-requirements.txtの変更が完了したら、次にシステムコールを許可する設定を行う必要があります。 Difyではセキュリティのため、デフォルトでは使用できるシステムコールが制限されています。外部ライブラリを使おうとするとシステムコールが呼び出せずエラーが発生するケースがあり、その際に対応が必要になります。

許可するシステムコールは、docker/volumes/sandbox/conf/にあるconfig.yamlの中で設定が可能です。 以下のようにallowed_syscallsに許可するシステムコールを追加することで、システムコールを使用できるようになります。

allowed_syscalls: [0, 1, 2, 3, 4, 5, ..., 336]

外部ライブラリを使うハードルが想像以上に高く、この時点ですでに通常では想定されていない使い方をしてしまっているんだろうなと感じました。

3. コードブロックで外部へのAPIアクセスができない

上記の設定で外部ライブラリは使用できるようになったものの、次は外部APIを呼び出す処理でネットワークエラーが発生しました。

Difyでは、コードブロックが実行される際には、外部と隔離された専用のSandbox環境(実体はコンテナ)内で実行されるため、安全に開発を進めることができます。エラー発生の状況から原因はそこが怪しいと推測し、調査を進めました。

./docker/docker-compose.yamlをみてみると、サンドボックスコンテナがssrf_proxy_networkという名前の専用のネットワークを使用していることがわかりました。 また、プロキシの情報を環境変数HTTP_PROXYHTTPS_PROXY)で指定していることがわかりました。

# (一部抜粋)
  sandbox:
    environment:
      HTTP_PROXY: http://ssrf_proxy:3128
      HTTPS_PROXY: http://ssrf_proxy:3128
    networks:
      - ssrf_proxy_network

最終的に、他のコンテナで使われているdefaultというネットワークを追加し、プロキシが使われないようHTTP_PROXYHTTPS_PROXYコメントアウトすることで、外部APIを呼び出すことができるようになりました。

# (一部抜粋)
  sandbox:
    environment:
      # HTTP_PROXY: http://ssrf_proxy:3128
      # HTTPS_PROXY: http://ssrf_proxy:3128
    networks:
      - ssrf_proxy_network
      - default  # 追加

4. テストが書けない

通常のソフトウェア開発では、単体テストや統合テストを書くことで、コードの品質を担保し、リファクタリングや機能追加を安全に行うことができます。一方でDifyのワークフローは、GUI上でブロックを配置して接続する形で構築するため、テストコードを記述できず、テストフレームワークを使って自動テストを実行することができませんでした。

一応ブロック単位で実行する機能があるため、一部の処理はその機能を活用して入出力を確認しました。しかし、入力がリスト形式の場合はうまくデータが渡せなかったり(本当はやり方があるのかもしれません)、前のブロックの入力が複雑な場合はそれを用意するのも大変なため、なかなか思うようにテストができませんでした。

最終的には実際にワークフローを実行して結果を目視で確認するしかなく、本当に自分の想定する挙動が実現できているのか、バグが仕込まれていないか、いつも以上に気を張って開発する必要がありました。

5. デバッグが難しい

さらに苦しかったのが、エラーが出た時のデバッグの難しさです。

簡単なエラーであればエラーメッセージから問題の内容を読み取ることができすぐに解消できるのですが、使っているライブラリの中でエラーが出た場合や実行環境の問題でエラーが出た場合などは、エラーメッセージからは原因が読み取れず、printデバッグ等もできなかったため、原因を特定するのにとても時間がかかりました。

具体的には、ワークフローがtimeoutで止まってしまうケースなどがありました。最終的にはロードバランサータイムアウト設定が原因だったのですが、コードのどこで止まっているのか、なぜ止まっているのかもわからず、ログにも何も出力されないので、結局根本原因の特定までに1ヶ月近くを要しました。

6. ブロック間でのデータ受け渡しが難しい

Difyのワークフローではブロック間でデータを受け渡すことができますが、データの受け渡し方法が独特でした。

コードブロックの出力としてはいくつか型を指定することができ、StringNumberArray[Number]など基本的な型は使用できるようになっています。しかし、複雑な型を扱いたい場合には、Objectという型を指定して、Pythonの辞書型に変換して受け渡す必要があります。

私の場合はPandasのDataFrameをコードブロック間で受け渡したかったのですが、これをObjectとして受け渡す必要があり、毎回DataFrame型からdict型に変換しては戻すという余分な処理を入れなければいけませんでした。

さらに、ブロック間で受け渡しができるデータサイズや文字数、オブジェクトのネストの深さなどにも制約があり、これらを超える場合はエラーが発生してしまいます。
一部については上述のdocker-compose.yamlファイルや./docker/.envファイルなどをいじることで対応できるものもありますが、設定方法についてはドキュメントにも記載がなく、ソースコードを読んだりリポジトリのissueをあさって調べる必要がありました。

7. バージョン管理ができない

通常のソフトウェア開発では、Gitなどのバージョン管理システムを使用して、コードの変更履歴を管理します。

しかし、Difyのワークフローは、GUI上で構築されるため、Gitで直接管理することができませんでした。 Difyにも変更履歴機能があるのですが、一度セッションが切れてしまうと履歴が失われてしまうため、変更履歴をきちんと管理するには不十分でした。

対応策として、ワークフローのエクスポート機能を活用しました。定義したワークフローはDSL形式で出力できるため、出力されたファイルをGitで管理することで擬似的にGitでのバージョン管理を実現しました。 毎回手動で行う必要があったり履歴の確認や復元に手間がかかるため、完全な再現とまでは行きませんが、少なくとも変更履歴を管理できたので大きく困ることはありませんでした。

さいごに

この記事では、エンジニアの視点からDifyを使用した際に苦しんだ点についてご紹介しました。

データを加工するなどある程度複雑な処理を行う場合には、純粋にコードを書いてシステムとして構築する方が良いと感じました。 おそらく本来はコードブロックを多用するような使い方ではなく、基本的にはすでに用意されているブロックを組み合わせて使うような使い方を想定されているため、情報が少なかったり設定がしづらかったりするのだと思います。

一方で、社内では非エンジニアの方がDifyを使いこなしてチャットボットを作り込んでいる事例もあり、GUIで簡単に生成AIを組み込んだワークフローが構築できるという点では非常に革新的なツールだと感じています。

利用者のニーズや用途に合わせて適切な場面で活用していきたいですね。

明日の記事の担当はエンジニアの小松さんです。お楽しみに!

参考文献


株式会社エニグモ すべての求人一覧 hrmos.co