Open HandsをGitHub Actionsから動かしてみた
AIコーディング系ツールやサービスが増加中。GitHub Actionsを使ったDevinやOSS版のOpenHandsに注目。GitHub Actionsをセットアップし、IssueやPull Requestに反応してAIコーディングを実現。準備が整ったらOpenHandsを試す。Issueで作業を要求すると、AIが作業を開始。Next.jsのアップデートを指示し、アプリコードの変更を支援。Rate Limitにも注意が必要。Devin導入の機会も。Personal Access Tokenの設定でIssueレポーター変更も可能。
目次
AIコーディング系のツールやサービスが増えてきました。その中でも、GitHub Actionsを使ってIssueやPull Requestに反応して調査や開発を行うことができる(らしい)DevinやそのOSS版であるOpenHandsなどが最近気になっています。
Devinは初期コストが高めなため、まずはOSS版のOpenHandsを試してみました。
OpenHandsとは?
OpenHandsは元々OpenDevinという名前で公開されていたOSSです。その名の通り、DevinのようなAIコーディングを実現させるOSSということです。どこかfirabseに対するSupabase(登場時)のような雰囲気を感じますね。

Devinのように、GitHub Actionsから実行できるらしいということがドキュメントからわかりましたので、早速試してみます。
GitHubリポジトリの権限設定を更新する
GitHub Actionsを実行する権限を更新しておきます。pull requestが作れるように、チェックボックスもオンにしておきましょう。このあたりは、チームのセキュリティポリシーとの兼ね合いになる部分もあるとは思いますので、Privateリポジトリに絞るなどの運用も検討する必要が出てくるかもしれません。

[ Optional? ] Personal Access Tokenも発行しておく
続いてOrganizationsの設定ページで、Personal access tokensの設定を有効化しておきましょう。

自分のアカウント設定ページからPersonal Access tokensに移動し、トークンを作成します。この際ownerを対象のorgとしておきましょう。

Docsに従って権限を設定します。

ここまでやっておくと、準備が完了です。ただ、Personal Access Tokenはもしかすると必須ではない・・・かもしれない予感がしています。
ClaudeのAPIキーを設定する
続いて生成AIのAPIキーを取得します。OpenAIかClaudeあたりを使うのが無難っぽいので、ここではClaudeのAPIキーを作っておきます。

取得したAPIキーは、リポジトリのActions secretsに追加しましょう。この際、Name
はLLM_API_KEY
にする必要がありますのでご注意ください。

Actionsを追加する
生成AIを呼び出す準備もできましたので、ワークフローを作ります。幸いWorkflowのサンプルがリポジトリにありましたので、リポジトリへ持っていきます。

このファイルをメインブランチにコミットしておけば、これで準備は完了です。
Open HandsをGitHub Actionsから実行する
準備ができたので、早速触ってみましょう。
リポジトリにIssueをつくる
今回のワークフローは、Issueでラベルまたはメンションを設定することがトリガーです。そのため、まずはタスク内容をざっくりまとめたIssueを作りましょう。

OpenHandsへメンションする
作成したIssueへの作業を依頼するには、@openhands-agent
へのメンションを行います。

メンション後、Actionsの様子を見ると、ワークフローが走り出していました。

ログをチェックしてみます。OpenHandsのインストールなどが終わると、作業が始まる様子でした。

初手のプロンプトらしきものを見つけました。Issueのコメントに加えて、いくつかの追加指示が入る様子です。
CONTENT: Please fix the following issue for the repository in /workspace.
An environment has been set up for you to start working. You may assume all necessary tools are installed.
# Problem Statement
Upgrade nextjs and related packages
This application uses several outdated packages. So we need to upgrade it.
At the starting point, we need to update Next.js.
Issue Thread Comments:
@openhands-agent
IMPORTANT: You should ONLY interact with the environment provided to you AND NEVER ASK FOR HUMAN HELP.
You SHOULD INCLUDE PROPER INDENTATION in your edit commands.
For all changes to actual application code (e.g. in Python or Javascript), add an appropriate test to the testing directory to make sure that the issue has been fixed.
Run the tests, and if they pass you are done!
You do NOT need to write new tests if there are only changes to documentation or configuration files.
When you think you have fixed the issue through code changes, please call the finish action to end the interaction.
生成AI APIのRate Limitに注意
作業途中でAnthropicのAPIエラーによるループが始まっていました。ログを見ると分当たりのRate Limitに引っかかったとのことです。エージェントの性質上、トークン消費が激しいのは間違いないので、ドキュメントに従ってLLM_RETRY_MIN_WAIT
を1分以上したり、トークン数の上限が高いモデルを選択するなどの準備が必要になりそうです。

OpenHandsがやろうとしていた変更を調べてみる
pull requestまで辿り着くことはできませんでしたが、いくつかの作業に挑戦している様子が伺えました。せっかくなので、Actionsのログをみて何をしようとしていたかをみてみましょう。
Next.jsとReactを最新版にする
IssueではNext.jsの更新を依頼していました。指示の通りにpackage.json
の中身を読み、そこからアップデートを試みています。
THOUGHT: I see that the project is using Next.js version 11.1.2, which is quite outdated. The latest stable version of Next.js is 14.x. Let's upgrade Next.js and its related dependencies. Since this is a major version upgrade, we need to be careful with the changes.
First, let's upgrade the core packages:
COMMAND:
yarn add next@latest react@latest react-dom@latest
ちなみにyarn
コマンドを使っていますが、コマンドがないのでダウンロードするというステップがしれっと追加されています。
! Corepack is about to download https://registry.yarnpkg.com/yarn/-/yarn-1.22.22.tgz
? Do you want to continue? [Y/n]
依存するライブラリを更新する
Next.js / Reactの更新後、型定義やESLintも更新していました。prettier
やtypescript
はなぜか漏れているので、ライブラリ選定の判断基準はちょっと気になるところです。
THOUGHT: Now let's upgrade the development dependencies:
COMMAND:
yarn add -D @types/react@latest @types/react-dom@latest eslint@latest eslint-config-next@latest typescript@latest
Next.js最新版への対応作業
続いてNext.jsのアプリケーションコードを読み始めています。ただライブラリを更新するだけでなく、ディレクトリ構造やファイルについてもみてくれるのは、AIエージェントに期待しているものらしくみえますね。
THOUGHT: Now that we've upgraded the core packages, we need to make some necessary changes to support Next.js 14+. Let's check the project structure and make required updates:
1. First, let's check the app structure:
確認と調査は次のステップで行われていました。
- アプリケーションルートのファイル構造を確認
pages/_app.tsx
があるかを確認pages/_app.tsx
の中身を確認next.config.js
の設定を確認
調査後にアクションを決定しています。
Thought: We need to make a few updates to support Next.js 14+:
1. Update next.config.js to remove deprecated options
2. Update _app.tsx to use newer Link API
3. Update tsconfig.json to include newer settings
tsconfig.json
の中身は見ていないはずなのですが、この辺は経験知的なものなのでしょうか。
next.config.jsを更新する
Next.jsの設定を変更し始めました。Netlifyへデプロイしているのでtarget: 'serverless'
を指定しているのですが、これをいきなり消しています。これはIssue内のコメントやREADME.mdなどに明示されていないため、Vercelにデプロイするつもりでやったと思われます。あとさりげなくStandalone Modeでのビルドを指示しています。これはキャッチアップできていない機能でしたので、手作業だと行わなかった対応に思えます。
Old String: ```
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
target: "serverless",
};
```
New String: ```
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
output: 'standalone',
};
```
トークンの消費量や金額をチェックしてみる
今回の途中まで実行したタスクで187896トークンでした。

数字だけ見るとびっくりするのですが、金額で見ると0.18 USDなので全然ですね。

試してみた感想
生成AI APIのRate Limitさえクリアできれば・・・という印象です。分単位のRate Limitですので、Rate Limitのエラーが出た時は60秒待機させるような提案を行っても良いかもしれません。
粒度を小さくするか、Rate Limitを乗り越えるかの戦いになる予感がしますが、ここにかける時間が多くなってくると、いよいよDevinを導入すべき時になりそうです。
とはいえ、小さなタスクの依頼に十分使えそうな様子であれば、小さなライブラリの保守などを任せてみるのも良さそうかなと思います。
小ネタ: Personal Access Tokenを設定すると、レポーターが変わる
GITHUB_TOKEN
とGIT_USERNAME
をリポジトリのシークレットへ設定すると、Issueのレポーターが変わります。

ガバナンス方面などでこのワークフローを作った人を特定する意図で使うのはいいかもしれません。