2025.04.08
OpenHands Cloudで、とりあえず50ドルぐらいLLM Agent開発を回す
はじめに
こんにちは。グループ研究開発本部、AI研究開発室のY.Tです。
巷で話題のコード開発エージェントDevinのオープン実装である、OpenHandsというプロジェクトがあります。このOpenHandsのクラウドサービス版がリリースされたので、今回はOpenHands Cloudを触ってみた記録を残そうと思います。
なんと今だけ?登録すると50USDのクレジットがプレゼントされるので、この機会に皆さんも登録して自分のGitのリポジトリにPRを投げましょう!
OpenHandsとは?
まずは、OpenHandsについて簡単な説明をしようと思います。正直なところ、公開されている論文や公式ドキュメントを読んでいただいた方が良い話ではあるのですが一応、ということで。
OpenHandsはコード開発のためのLLMアプリケーションの一つであり、中でも、人間の作業を代替することを目指すエージェントといわれるタイプのアプリケーションです。コードの生成・修正、シェルコマンドの実行、ウェブブラウジングによる情報収集、API呼び出しなど、開発のために必要な行動を人間と自然言語で対話しながら実行することができます。
また、実装がオープンであり、安全のためにDockerを使ったサンドボックス環境で実行されるため、gitからコードを持ってきてDockerで環境を作ればローカルで動作します。LLMは基本的にはAPIが提供されている高性能なモデルを使うのが主流だと思いますが、llama.cppみたいなローカルで動作可能なサイズのモデルを使えば、完全にローカルに閉じて動作させられます。流行りのDeepSeekのパラメータが比較的小さいモデルを完全ローカルで動かしてみたりできるわけです。すごい!
他に機能としての特筆すべきものは、GitHubとの連携です。リポジトリを連携して指示を与えると、どんどんPRやissueを作成してくれます。Mergeみたいな処理もやってくれるのは少し怖いですが、「ジュニアエンジニアがコード開発に参加しているイメージ」という例えがしっくりくる感覚ですね。
エージェントの仕組み
さて、OpenHandsはどのようにこのような動作を実現しているのでしょうか?
一言でいうと、「計画(Plan)→ 実行(Act)→ 観察(Observe) の一連の流れをループしてタスクを進める」です。よくわかりませんね。一つずつ見ていきましょう。
Planは起こすべき行動の推論パートです。User Interfaceからの入力やその他の事前情報から起こすべき行動を推論します。LLMのシンプルな使い方ですね。繰り返し推論させることで精度を向上させるChain-of-Thoughtのような仕組みや、コードエージェントとしての出力に寄せるように練られたシステムプロンプトがポイントです。
Actの部分は、ユーザへの回答あるいは、コードの編集やGitの操作などを行うパートです。実際の作業が必要な場合は、CodeActというアプローチに基づいていて実行可能なコードをアクションとして生成します。従来のLLMエージェントは、固定フォーマットのJSONや単純なテキスト指示でアクションを生成するため柔軟性が低く、都度出力が返ってくるだけなので実際の環境のエラーなどの反応を踏まえた動的な修正が行いにくい欠点がありますが、その問題を解決しています。
OpenHandsでは、コードの編集などを行う関数がOpenHandsのコードベースに定義されており、それを呼び出すようなスクリプトを生成するようなモデルやプロンプトの調整をすることで、実行可能なコードをアクションとして生成することを実現しています。
Observeは、実行環境の状態をエージェントに返す部分です。openHandsでは、すべての入出力や環境とのやりとりがイベントストリームとして記録・管理されます。このイベントストリームをエージェントにフィードバックして次のPlanに反映します。これにより、過去の実行結果やエラーメッセージを踏まえて自己改善するような挙動が実現されています。イベントストリームはループを重ねるごとに肥大化するのでコンテキスト長に収まらない問題が発生してきますが、その辺りは適宜要約を挟んでいるようです。(この仕組みは、Openhandsではコンデンサ、と呼ばれています。)

AI SOFTWARE DEVELOPERS AS GENERALIST AGENTSより、Figure 2
OpenHands LM
OpenHands自前のオープンソースコーディングモデルが公開されています。Hugging Faceから利用することができ、ドキュメンによれば、3090GPU1台ぐらいであれば動くようです。
Qwen/Qwen2.5-Coder-32B-Instructがベースにトレーニングされたモデルのようです。
トレーニングには世の中のOSSのissueを学習データにして、その解決を報酬とするような強化学習的な手法を用いたそうです。
OpenHands Cloudの裏ではこのモデルが動いているようで、会話する分にはなかなか賢い印象を受けました。
OpenHands Cloudを使っていこう
お待ちかね、OpenHands Cloudを使っていきましょう。色々説明するより見たほうが早いです。なんならやってみるほうが早い。
OpenHands Cloudは、ブラウザとgithubアカウントさえあれば使えます。
フローに従って登録を進め、クレカを登録すると、50USDのクレジットが初回限定で付与されます。

足りなくなったらカードで決済して予算を追加する方式で、勝手にヤバい請求が来ることはないので安心を。
初期画面からGitのリポジトリを連携してみましょう。コードそのものをアップロードして開始することはできますが、Gitのリポジトリを連携したほうが楽しいと思います。デフォルトでは全部のリポジトリが見れる権限な気がします。とりあえず作業するリポジトリの権限だけ与えておくと良いでしょう。

コードが展開されました。左のチャット欄から指示を入力すると作業が始まります。

OpenHands Cloud
さあ、環境が用意されたので、何かアプリケーションを開発したいところです。
何か面白いものを作りたいところですが、難しいことをやらせすぎると50USDはすぐだということは予想がつきます。
ちょっと50USDは考えますね。最近1USD高いし。
ということで、ファイル整理スクリプトを書いてもらって、私のとっ散らかったダウンロードフォルダをなんとかしてもらうことにしました。
雛形は作ってあげましょう。main.pyに以下のようなスクリプトを書きました。
%%configure -f { import os import shutil EXTENSION_MAP = { 'images': ['.jpg', '.png', '.gif'], 'docs': ['.pdf', '.docx', '.txt'], 'scripts': ['.py', '.js', '.sh'], } def classify_file(filename): _, ext = os.path.splitext(filename) for folder, exts in EXTENSION_MAP.items(): if ext in exts: return folder return None def gnome_sort(): files = os.listdir('.') for file in files: if os.path.isfile(file): target_folder = classify_file(file) if target_folder: # NOTE: バグ: フォルダを作成していない場合がある shutil.move(file, os.path.join(target_folder, file)) if __name__ == "__main__": gnome_sort() }
はい、わざとバグ入れてます。(実際の入力ではコメントも削除)
とりあえず、このバグを直してもらって、改善してもらいましょう。

まあ、当たり前のように直りますね。

PRもちゃんと提出。入社してすぐの自分よりえらいかもしれません。

じゃあissueを優先度考えて解決していってもらえます?できたらPR出しといてくれたら後で見てmergeしときますので👋

やるやん

ちなみに、OpenHands Cloudからのコミットは、OpenHandsのgitアカウントによるものとして表示されます。コメントやPRなどは連携したアカウントの権限でCLIを叩くので、そのアカウントのものとしての表示です。
こういう面倒で簡単な作業を全部AIがやってくれたら嬉しいですね。

調子に乗って色々とお願いしてたらconflictしました。
conflictの解消をお願いしたらマージできるようになりましたが、毎回うまくいくような予感はないですね。

この後、isuueを生成させてみたり、さらにそれを解決させてみたり、2時間ほど遊んでいたら50USDを使い切りました。

予算を使い切ると入力にエラーが返ってきます。

今回はここまでにしておきます。せっかくなのでOpenHands Cloudでやりましたが、OpenHands LMをローカルで動かせるなら、それでもいいのではって気がしますね。ちょっと試したいところ。
今回は非常に短いコードだったのでうまくいっていますが、一般アプリケーション並みのコードベースだったら体感でどんな感じかも気になります。
今回試さなかった機能
今回はほとんどエディタ寄りのところでやっていしまいましたが、OpenHands Cloudならではの機能があります。
一つ目は、GithubのコメントでOpenHandsを呼び出す機能。OpenHandsの提出したPRなどに、@openhands に続けてコメントを追加すると、OpenHandsが動いて回答が返ってきます。新たなコミットが積まれることもあるでしょう。
二つ目は、エージェントの並行稼働。UI上でエージェントが動いている時に新しい会話を始めることができるのですが、その間に前の会話ではエージェントが動いています。このように複数の会話上でエージェントを実行することができ、それらのエージェントは協調して動くと公式ドキュメントで説明されています。イベントストリームの共有とかをしているのでしょうか。当然時間あたりのコストも上がっていきますので、ご利用は計画的にすると良いと思います。今回試していない理由は予算の都合です。
うまくいかなかったところ
conflictの問題はどうするか、ですね。並行稼働などをすると、より増えてくると思います。AIのコードのレビューは大変です。
conflictの解消は自動でできないこともないですが、conflictの解消はとくべき問題を考えるとコンテキストが長くなりそうなので、コストが増えそうですね。公式のドキュメント Prompting Best Practices には、できるだけ狭い範囲で行数などもなるべく指定してタスクを行わせると良いとしています。複数ファイルでconflictを起こすと厳しそうな予感、、、
まとめ
今回はOpenHands Cloudについて紹介しました。まだまだな部分やコストの問題はあるものの、将来性は非常に感じるものでした。
現段階では、「散々プロンプトで言い含めたのにmainにプッシュした」とか「テストを通して、と指示したらテストを消した」とか言った報告が上がっているので油断はできないですが、READMEの編集とか、リファクタ的なところあたりから任せてみたいですね。
作らせたREADMEの最後をよくみたら、勝手にMITにされてたけど。

参考
OpenHands 公式ドキュメント
OpenHands: An Open Platform for AI Software Developers as Generalist Agents
all-hands/openhands-lm-32b-v0.1
Executable Code Actions Elicit Better LLM Agents
OpenHandsのGit
Qwen/Qwen2.5-Coder-32B-Instruct
Introducing the OpenHands Cloud
宣伝
グループ研究開発本部 AI研究開発室では、データサイエンティスト/機械学習エンジニアを募集しています。ビッグデータの解析業務などAI研究開発室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いします。皆さんのご応募をお待ちしています。
グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。
Follow @GMO_RD