この記事はNTTドコモソリューションズ Advent Calendar 2025 17日目の記事です。
こんにちは、NTTドコモソリューションズの高鶴と申します。
技術革新本部という部署で、主にプログラムの設計やコーディング、ユニットテスト等の技術リサーチと社内普及をしています。
過去(2023アドカレ)にRustの記事を書いているので、そこも併せてお読みいただければうれしいです。
AIが盛り上がる昨今、Rust界隈では「AI時代こそプログラミング言語はRustがよいのでは?」と言われているそうな。
私としても、AIとRustを組み合わせて使うとき、概ね下記のようなメリットを相乗効果として得られるのではないかと想定しています。
- AIの不確実な出力を、Rustの厳格な型チェックがかなりカバーしてくれる
- Rustを学習する難しさを、AIがカバーしてくれる
本記事では、TauriでアプリケーションのPoCを作るためにGitHub Copilot Chat(Agent)を活用する形で、その効果のほどを体感してみました。
1. PoCのお題
昨今の当社内の重要テーマとして、「開発者エクスペリエンスの向上」が挙げられています。
長らく「マネジメント」や「ガバナンス」を重視してきた結果、エンジニアにとっての満足度が低下しているのでは、という課題意識があるためです。
そこで、 Tauriを使ったデスクトップのシステムトレイ常駐アプリ を作って、開発者個々の開発用PCに入れてもらい、下記のようなことをやるシナリオを想定してPoCを作ってみます。
- 開発環境の使い勝手に関するショートアンケート (←とりあえずPoCではここだけ)
- 作業を邪魔しにくい時間帯(朝イチや昼休み前後など)に右下の通知(Notification)を出して、短いアンケートに答えてもらう
- 作業ログやリソース情報(CPU、メモリなど)によるエクスペリエンス測定
2. 技術選定
最近はRustの良いライブラリが出揃って、デスクトップアプリが簡単に作れるようになってきてます。
今回は、Tauri + Yew でやってみることにしました。
「とにかくRustを使いたい」という歪んだ(?)動機からの技術選定ではありますが、仮に要件からの是々非々で技術選定をしても、まあまあ合理的な選択になっていそうで、大丈夫なのではと思います。
- Pros
- Windowsの他の方法で開発するよりも、簡単かつクロスプラットフォーム
- 類似品(Electron)よりもメモリへの圧迫が少ない
- YewだとReactで覚えたUIプログラムの考え方がそのまま使える
- 将来、Webやモバイルに展開したくなった時、同じ画面UIのコードが共有できる
- 必要なプラグインと導入ノウハウが公式にある
- システムトレイ常駐
- トーストによるデスクトップ通知
- Cons
- Electronにくらべ、OS標準ブラウザコンポーネントの影響を受けるため、画面の再現性の問題やアップデートの影響があるかもしれない
3. プログラム設計
単にRustさえ使っていれば何でもよくなるのかというと、そういうわけでもありません。型チェックがきちんと機能するようなプログラム設計上の工夫が必要です。(類似の型システムを持つ言語ならRust以外でも工夫すれば近い効果を得ることは可能と思います。)
Tauriのデスクトップアプリケーションは、フロントエンドとバックエンドの最低2プロセスで構成されます。これに加え、アンケートの収集先のサーバを用意する必要があるため、それを加えた計3つのプロセスを使い、その間で通信させる必要があります。
- WebViewを使ったフロントエンド (デスクトップ)
- ネイティブ(Rust)のバックエンド (デスクトップ)
- アンケート収集APIサービス (サーバ)
これらはそれぞれ別の言語で開発されることが多いと思いますが、今回は全部Rustで書きましょう。
言語を一つにする大きなメリットは、 同じ業務ロジックを言語の数だけ書かなくて済む ことです。さらにRustだと、業務ロジックの型定義と全プロセスの実行コードの整合性をコンパイル時にチェックできます。
3.1. 静的なプログラム構成図
さて、上記の目標を達成するため、業務ロジックの記述を1回で済ませるためのプログラム設計を考えます。
今回のPoCはアンケート機能(Survey)のみの実装に絞りますので、 survey-model クレートを作り、業務ロジック型の定義を集中管理しましょう。
SurveyService というアンケート項目の取得と回答状況アップロードのサービスをトレイトで定義しておき、各プロセス向けのコードは、それをuseやimplするようにします。
フロントエンドからサービスを叩いてもらって、それをバックエンド経由でAPIサーバまでそのままリレーするだけですので、インターフェイスとなるtraitは同じSurveyServiceを共用して良いでしょう。
こうすれば、survey-modelを変更した場合に各プロセス用のクレートで影響箇所をコンパイルエラーにすることができます。
下記がPlantUMLのクラス図を使った型定義の説明図です。
(PlantUMLで生成した図なので多少表示が汚いですがお許しを)
凡例:
- (P) プロトコル
- Rustではtraitにマッピングされます
- Javaのinterfaceと類似した使い方です
- (S) 構造体
- Rustではstructにマッピングされます
- JavaやOOPでいうValue ObjectやRecord型のように使います
3.2. 動的なオブジェクト配置図
上記の構成をコンパイルして実行したときには、このような配置になります。
ポイントは、単一の業務モデルのソースコード(survey-model)を各プロセス用にそれぞれコンパイルして使用している点です。
従来であれば各プロセスが別言語なので、別個に業務ロジックを実装しなければならないところでした。ElectronならフロントエンドとバックエンドはJavaScriptかTypeScriptで共有できそうではありますが、Rustほどの厳密さはないと思います。
下図はオブジェクト図と配置図を混ぜたような図で、UMLの専門家には怒られるかもしれませんが、どのノードのどのプロセスにコンパイルされた機能が配置されているかは表現できていると思います。
ちなみに、今回はPoCのため、Desktop内で動作するものしか作っておらず、バックエンドのSurveyServiceの実装はインメモリのスタブです。
4. エージェントで作っていく
GitHub Copilot Chat(Agent)、モデルはAutoでやっていきます。(いちいち言語モデルのメリデメを比較してこまめに選ぶようなコストはかけません!)
実行の履歴を見ると、GPT-5とClaude Sonnet 4.5を混ぜて使っていたようです。
以下はやったことのごく一部ではありますが、どんな感じかを見ていきます。
4.1. 事前準備: AGENTS.md
AGENTS.mdは、AIエージェントにとってのREADMEに当たるファイルです。
ここにエージェントに常に気にしてほしい指示を書きます。
とはいえ、大したことは書いていません。プログラムを修正したときに、どうやって確認すればよいかを書いているだけです。
# DevEx Console
## 設計情報
docs/src/design.md を参照し、プログラムの構成を確認すること。
## 修正時のコーディングルール
- 未実装部分を含む場合は、TODOコメントにすること。
## 修正時の確認
変更を行った際には、以下の点を確認してください。
1. `cargo clippy --all-targets --all-features -- -D warnings` がエラーなく通ること
2. `cargo fmt --all -- --check` がエラーなく通ること
3. `cargo test` が正常に動作すること
4. Tauriの場合、`cargo tauri build` が正常に動作すること
4.2. 事前準備: tauri-create-app
いくらAIだからといって、プロジェクトのテンプレがあるのにあえてスクラッチから作らせる意味はありません。
cargo create-tauri-appでプロジェクトのテンプレートを自動生成しておきます。
4.3. 指示1: 「タスクトレイに常駐するように改造」
チャット入力はこれだけ。
タスクトレイに常駐するように改造
言語モデルはGPT-5が自動選択された模様
さっそく調査を開始してくれました。
- crates.io でライブラリを調査
- TauriのREADMEを確認
- GitHub上から公式サンプルプログラムを取ってきた
- Cargo.tomlでライブラリ(必要なTauriプラグイン)を追加
- ソースコードの修正提案
コンパイルエラーがないかの確認を開始
-
cargo buildで文法チェックとネイティブビルド -
cargo tauri devでWASMのビルド(trunk)と、UIの表示
やったことをレポート
ほぼ完璧でした。
でも、ドンピシャの公式サンプルプログラムがWeb上にあるんだから、そりゃそうです。
4.4. 指示2: ちょっと複雑な指示
tauri+yewのサンプル画面(Greeting)の状態から、タブ化して「挨拶」タブと「アンケート」タブを作れるようにしたいと思います。その第一ステップとして、タブ化を指示。
やってはくれるのですが、AGENTS.mdに書いたチェックの指示はどうしたんだろう・・・?
checkと指示すると、書いた通りにしてくれました。
ClippyやRustfmtにかけて、タブ化したプログラムを正常に動かすことができました。
4.5. 指示3: 業務ロジック!
指示:「SurveyServiceトレイトを作成し、アンケートの一覧とすでに行った回答の一覧を得るAPIを作って」
改造とチェックはしてくれた模様ですが、AGENTS.mdに書いたものではなく、自分で判断したチェック内容になっています。ちゃんとやって・・・
4.6. 指示4: UIを作る
指示:「surveymamagerをtauri-backendに作成し、tauri-frontendのアンケートタブに一覧を表示できるようにする。未回答のものを選択すると、回答できるようにする。」
Copilotくん、だいぶやることを覚えてくれたかな?
ただし、出来上がったUIの見た目は本当にイケてない。
- DjangoなどのメジャーなWebフレームワークほどサンプルが豊富ではないので、小慣れてない
- 出来上がった画面をフィードバックする方法がない(Playwrightなどを入れていない)ので、うまくできたかをCopilot君が自分で確認できない
5. 使ってみた感想
5.1. よくあることをさせるのなら、概ね欲しいものが得られる
Web上にサンプルがあるようなものは、自分の学習内容かWebからの取得によって、ほぼ欲しいものが得られます。
どこに探しに行くかをエージェントが自分で考えてくれるところが、直近1~2年での大きな進化で、これは相当時短になります。
5.2. Rust⇔AIのフィードバックサイクルはうまく動いた
Rustとの組み合わせは、想定通りかなりうまく働きました。
コンパイルチェックや静的チェック(Clippy)を一通り実行し、そのエラーを修正して再度チェックを繰り返してくれるので、RustとAIエージェントに任せて、動く状態までは放置できます。
AIエージェントにフィードバックを与える非AIシステムを組み合わせる ことが、効率化に非常に有効だと感じました。
おそらく、Pythonだと型チェックが弱いため、ユニットテストがフィードバックの中心となり、人が悩む割合が多くなるのではと思います。Python×AIエージェントとの比較検証はやってみたいですね。
5.2. 無理な注文をすると、正しくない答えを頑張って返す
事前に調べた結果、おそらく不可能だと判明した課題を、エージェントに与えてみました。
AIはできないことをできないと言わず、頑張って間違った答えを返しがちです。頑張ろうという意気はうれしいのですが、さすがに見栄っ張りですね。
このPoCでも同じことが起きました。
その場合、人間側が「できないならできない根拠を調べて」と指示を与えて、不可能である根拠を示させるような使い方が良いでしょう。このように指示すると、できない情報を探してGitHubのIssueやその他のWebの情報を漁ってくれます。
ただし、できない前提で調査指示をすると、それはそれでできないことを何としても証明する方向の調査をしてしまうため、実はできたのに・・・ということも起こりえます。
良くも悪くも、指示の背景にある期待に沿おうとせんがために事実を歪める傾向にあるようです。
5.3. 警告を不正な方法で回避する
Rust×AIが手放しで素晴らしいかと言えば、罠もあります。
AIエージェントがコンパイル警告の解決方法をどうしても見いだせない場合、不正な方法で解決してしまうことがありました。
具体的には、#[allow(clippy::...)]のような、警告を回避するマーカーをつけられてしまって、警告されるような処理があるのに改修せず、警告があったことをなかったことにされてしまった、という例です。
本当は、警告が出ないようにすることが目的なのではなく、警告されるようなコードを修正してほしいということなんですが、切羽詰まると安易な方に逃げてしまうようです。
5.4. 事前に与えた指示はあんまり守ってくれない
AGENTS.mdの指示があまり通らない気がします。見てはくれているのですが、自主的にやってくれない感じです。
いちいち「確認して」とか「check」とか、そういった指示をすると、AGENTS.mdの通りにやってくれますが、ここは言わなくてもやってほしいところです。
これは書き方が悪いorエージェントが賢くなるのを待てば解決するのかもしれません。
5.5. UIを作るときには、フィードバックの仕組みが必要
RustコンパイラやClippyでソースコードの不具合はある程度対応できるのですが、今回はUIも作らせました。
この場合、UIの見た目がちゃんとできているかのフィードバック機構も欲しくなってきます。Copilot VisionやPlaywrightなどを使えば解決するのでしょうか・・・?
今回はそこまで手が出せなかったので、これからの課題です。
6. まとめ
本記事では、Rust×AIでソフトウェア開発するPoCの例を紹介しました。PythonやJavaScriptをAIで生成させるのも悪くはないのですが、『コンパイラとAIが協調してほぼちゃんと動くコードが自動的に出来上がる』という感覚は、Rustだからこそ強く感じることができるものだと思います。
AIエージェントがテキトーな提案を出してきて、それをRustコンパイラが「間違ってるぞ!」と指摘し、またAIが渋々テキトーに直す…というのを繰り返してソフトウェアを完成させていく光景は、なんだかかわいくもあります。
もし興味があれば、あなたも体験してみてはいかがでしょうか?
記載されている会社名、製品名、サービス名は、各社の商標または登録商標です。








