空を飛んでレバレジーズへ。アメリカから来た内定者インターンの歩み

江ノ島付近の青空

はじめに

こんにちは!26卒エンジニアで、2025年9月からレバレジーズで内定者インターンをしている谷口功樹です!

この記事を通して、内定者インターンとしてTQCチームで活躍してきた中で、僕がどのようにエンジニアとしての視点を広げていったのかを振り返ります。

突然ですが、皆さんは歩いている時、普段どこを見ていますか?

転ばないように地面を見ていますか? それとも、誰かとぶつからないように真っ直ぐ前を見ていますか?

僕は、意識的に空を見上げるようにしています。かつて下ばかり向いていた自分が、いかに小さな世界に閉じこもっていたかに気づいてしまったからです。

空を眺めていると、自分の可能性も無限にあるような、そんな気がしてきます。

…と、いきなりこんな抽象的なことを語ったのには理由が当然あります。

今回のインターンで僕が感じた、まさにそんな自分の意思での「視界と可能性の広がり」をお伝えできればと思います!

自己紹介

改めて自己紹介をさせていただきます。谷口功樹です。こんな普通の名前ですが、実はアメリカ生まれのアメリカ育ちです!日本生活歴は、留学と夏休みの旅行を含めて合計2年くらいです。

大学ではコンピューターサイエンスを専攻し、主にAIや統計学を学んでいました。同時に、日本語と日本文化の授業も頻繁に履修していました。その縁もあり、2024年の春には京都大学へ留学していました。

なぜ日本で就職?なぜレバレジーズ?

その京都での留学が、僕にとって大きな転換点となりました。実際に日本で生活してみた中、自分のライフスタイルは日本に合っていると確信し、卒業後は日本でキャリアを築きたいと考えるようになりました。

その上、就活を通して、アメリカと日本のソフトウェアエンジニア業界の違いを痛感したことも理由の一つです。現在のアメリカでは、AIの台頭もあって、新卒エンジニアの枠が爆速で縮まり、実際に僕もアメリカの企業から面接の案内をいただくことは一度もありませんでした。

アメリカの企業にとっての新卒は、将来への投資ではなく、単なる安価な労働力に過ぎなかったのではないかと、勝手ながらそんな風に感じてしまいました。一方で、日本の企業には、まだ若芽の可能性を信じて、ポテンシャルを育てようとする文化が残っているように見えました。

そんな中参加した2024年11月のBoston Career Forumで出会ったのがレバレジーズでした。

面接で一番印象に残ったのは、会社側が「僕がどれほどの価値を提供できるか」だけでなく、「会社が僕にどんな経験を提供できるか」を真剣に考えてくれたことです。一方的な採用ではなく、お互いの成長を模索するその姿勢に惹かれ、2025年5月に卒業した直後、内定をいただき即承諾、そして9月から内定者インターンとして参加することを決めました。

インターン中の配属はTQCチーム!てかTQCって何?

インターン開始前の面談で、こんな質問をされました。

「将来正社員になった時にやるような業務(つまりサービス開発)、それともあえてやらなさそうなこと、どっちを経験してみたい?」

思わぬ質問に数秒間迷いましたが、今回のインターンにおける僕の目標はすでに明確でした。

  • 日本での生活に慣れる
  • 日本のビジネスカルチャーを知る
  • とにかく新しいことを学ぶ

そしてやはり、僕は「やらなさそうなこと」を選択しました。そうして配属されたのが、テクノロジー戦略室のTQCチームでした。

「...でTQCって何?」

と思われるかもしれません。少なくとも僕は思いました。TQCはTotal Quality Controlの略で、開発されているサービスやアプリの品質管理を行っており、現在はセキュリティと負荷・パフォーマンス領域に注力しております。ただバグを見つけるだけでなく、開発工数削減や顧客の信頼獲得、そしてビジネス面での損失回避など、会社を影から支える重要な役割を担っています。

品質向上への道

レバレジーズの内定者インターンとは、インターンっていうより、ほぼ正社員である。

もちろん正式な立場は「インターン」ですが、任される業務は周りのエンジニアとあまり変わりません。TQCチームの一員として、主に以下の3つの実務に取り組みました。

ペネトレーションテスト

攻撃者の視点に立ち、社内サービスの脆弱性を探りました。具体的には、Burp Suiteを使ってHTTPリクエストを解析・改ざんしたり、Pythonやシェルスクリプトを書いてテストを自動化したりしました。おまけで、各サービスの技術スタックを横断的に知る良い機会にもなりました。

やってみて一番驚いたのは、大手企業の開発チームが作ったプロダクトでも、完全に脆弱性を無くすことはできないと言うことです。もちろんTQCチームの充実したテスト項目のマニュアルがあったからこそ見つけられた面もありますが、最初は「初心者の自分でもこんなに簡単に見つけてしまえるのか」と驚くと同時に、この作業の重要性を強く実感しました。

負荷試験

負荷試験は2回しか実施しませんでしたが、その2回だけでも色々知識は得られました。

詳しくは僕の上司が書いた記事に全てありますが、流れをざっくり説明すると、ブラウザ操作を.harファイルとして保存し、JavaScriptで試験シナリオを記述できる負荷試験ツールであるk6が読み込める形式にhar-to-k6というライブラリで変換して実行するというものです。監視にはGrafana、Prometheus、AWS CloudWatchを活用し、ダッシュボードを自作するためにPromQLを、負荷がスケーリングにどう影響するか理解するためにKubernetesも少し学習しました。

特定の脆弱性を突くペネトレーションテストとは違い、負荷試験はサービス全体を俯瞰して捉えることが重要だと学びました。

自作のGrafanaダッシュボード
自作のGrafanaダッシュボード

インフラ構築

「とにかく新しいことを学ぶ」ため、未経験だったクラウドインフラ、Terraform、GitHub Actions(CI/CD)をセットで扱える課題を上司に頼みました。

具体的には、GitHub ActionsとTerraformを連携させてAWS上にApacheサーバーを立ち上げ、任意のDockerコンテナを稼働できる環境を構築しました。そして運用性を考慮し、CloudWatch Logsで簡単にログを確認できる仕組みも併せて実装しました。

この構築作業はインフラの基礎を体系的に学ぶ良い機会となっただけでなく、後述するAIエージェントの検証環境としても、重要な役割を果たすことになりました。

いよいよ実践!ペネトレーションテスト自動化エージェントの開発

そして、今回のインターン期間の集大成は、PythonとGoogle ADK(Agent Development Kit)を駆使した、ペネトレーションテスト自動化エージェントの開発でした!

簡単にいうと、AIにぺネトレーションテストを自律的に行ってもらうツールなのですが、単にプロンプトを投げて暴れてもらうだけではありません。エージェントがただ闇雲に動くのではなく、論理的に動くための設計に、力を入れました。

大学でAIや統計学を履修していたとはいえ、AIの数学的な理論や基礎的なアルゴリズムの学習が中心だったので、LLMやエージェントの実装は、僕にとって全く新しい挑戦でした。開発に着手して真っ先に直面したのが実行基盤の選定で、Google Cloudの利用を前提としつつ、ネイティブな管理環境ながら10分でタイムアウトしてしまうVertex AI Agent Engineや、1時間制限のCloud Run Serviceでは長時間のスキャン要件を満たせないことが分かりました。最終的には、最大1週間の実行が可能なCloud Run Jobsを採用するという判断を経て、ようやくエージェント本体の開発へと進むことができました。

1. 有向二部グラフで構造化する

まず、エージェントの思考プロセスを、「タスク」と「発見」という2種類のノードで構成される有向二部グラフとして定義しました。

  • ToolAgent(実行役): 割り振られた「タスク」を実行し、その出力結果から脆弱性の手がかりとなる「発見」を抽出します。
  • PlanningAgent(計画役): 得られた「発見」を分析し、次に行うべき「タスク」を新しく生成します。

キューやスタックは実行順序を管理するための一時的なものですが、グラフは調査の論理そのものを蓄積するために存在します。木構造ではなくグラフを採用することで、複数の調査経路が同じ結論に辿り着いた際に情報を集約し、後続タスクの重複発生を抑えられるようになりました。さらに、ノードをタスクと発見に分ける二部グラフの制約を設けることで、実行と計画という役割を分離し、事実に基づかない計画を防いでいます。これらを有向の依存関係で結ぶことで、どの発見がどのタスクに起因したのかという因果関係を正確に記録し、診断の履歴を遡れる仕組みを整えました。

この「タスク → 発見 → タスク」という再帰的なサイクルをグラフ構造に落とし込むことで、複雑な攻撃ルートを論理的に切り開いていく仕組みを構築しました。

グラフ グラフ一項目

2. 評価関数で枝刈り

無限に広がる探索ルートを制御するため、評価関数を実装しました。

  • f(n) = h(n) - g(n)
  • h(n) = 目標とする脆弱性の深刻度
  • g(n) = (1 - 親発見のスコア) * 親の累積コスト + 当タスクのコスト

g(n)は、親ノードである「発見」の重要度を反映します。親の重要度が低いほどコストが跳ね上がる設計になっており、計算結果が閾値を下回ったタスクは実行価値なしとして破棄されます。

これにより、重要なルートのみを効率よく辿ることができます。

3. コールバック関数を用いたLLMのトークン管理

ペネトレーションテストの実行は数時間に及ぶことを想定していたため、情報の取捨選択をしなければ一回のセッションで消費される入力トークン数は数百万規模に膨れ上がり、コストの増大やコンテキストの上限超過を招くことを確認しました。

この課題を解決するために、Google ADKのコールバック関数を活用しました。 コールバック関数とは、LLMの推論やツールの実行の前後のタイミングで、あらかじめ指定しておいた独自のプログラムを自動的に実行させる仕組みのことです。 これを用いることで、LLMに送る情報やメタデータをプログラム側で編集できるだけでなく、出力される情報の検証や加工も可能になります。

まずモデルへリクエストを送る直前に、過去のタスクのメッセージ履歴を全て削除する処理を実装し、エージェントが外部の情報に惑わされず、現在の作業のみに集中できる環境を作りました。 また、ツールの呼び出し回数が上限に達した際には、モデルからツール定義自体を剥奪して強制的に結果報告へ移行させる制御も行っています。

出力側では、ツールから返ってくる実行結果を外部ストレージに保存し、LLMに先頭の2000文字のみを渡すことでトークン消費を大幅に抑制しました。 そして、例えば何もツールを使わずに回答しようとしたりした場合には、空のリストを強制的に返却させて実行を正常に終了させるガードレールも設けています。 こうした入出力管理が、エージェントを実用的なコストと精度で長時間稼働させるための鍵となりました。

トークン費用の比較
トークン費用の比較

4. フロントエンド

フロントエンドは、Pythonでwebアプリを構築できるフレームワークであるStreamlitを採用し、スキャン設定管理や進捗確認が可能な管理画面を構築しました。

上記で話したグラフを可視化するため、StreamlitのReactコンポーネントとしてD3.jsと React Flowを組み込み、エージェントの思考が広がっていく様子をリアルタイムで描画できるようにしました。

5. 動作確認

前章で構築したAWS環境に、わざと多数の脆弱性を含ませたセキュリティ学習用のデモアプリであるOWASP Juice Shopをデプロイし、エージェントを走らせました。可視化したグラフが広がっていく様子を眺めていて、インターン期間中に取り組んできたすべてが、この一つの完成したプロジェクトへと繋がっていて、すごい達成感を感じました。

終わりに

インターン開始時に挙げた3つの目標について、達成できたか振り返ってみます。

日本での生活には、この半年でかなり慣れました。 TQCチームでの業務を通して、**新しいことも存分に学びました。

では、日本のビジネスカルチャーについては…?

まあ、上司や同僚との接し方は学びましたが、完璧にこなせたかと言われると微妙かもしれません。でもその代わりに、レバレジーズのエンジニアは皆自由であるという、この会社ならではの最高の文化を肌で感じることができました。

よく他の記事でも語られていることですが、レバレジーズは本人が望みさえすれば、どこまでも成長できる場所です。

来月からは、いよいよ正社員としてのスタートです。さらに成長し続け、レバレジーズを盛り上げていく僕のこれからの活動に、ぜひ注目してください!

それではまたいつか!

We are hiring!

レバレジーズ株式会社では一緒にサービスを開発してくれる仲間を募集中です。 もしご興味を持っていただけたなら、以下のサイトからご応募ください。

HRMOS求人ページ

hrmos.co

会社説明資料

speakerdeck.com