
こちらは LayerX AI Agent ブログリレー 5 日目の記事です。
昨日は Tomoaki (@tapioca_pudd) さんによるAmazon Bedrock Knowledge Basesで実現する”元のリンクとセット”で検索できるRAGでした。
すべての経済活動をデジタル化するために、すべての業務活動をデジタル化したい、コーポレートエンジニアリング室の @yuya-takeyama です。
この大 AI 時代、Infrastructure as Code や Configuraiton as Code の価値が上がっていると感じませんか?
僕はコード化はそれ即ちデジタル化であると考えています。
既に Terraform のコードを Claude Code 等の Coding Agent に書いてもらったり、AWS CLI などを組み合わせることで既存のリソースを後からコード化している方もいるのではと思います。
AWS や Terraform やツールやドキュメント等のエコシステムがしっかりしているし、LLM にもかなり学習されているので、それほど工夫をしなくても Coding Agent がよろしくやってくれることも多いです。
今回は、社内独自のツールの設定ファイルを、コンテキストも与えつつ自動的に生成させる試みです。
解決したい問題: グループ管理ツールの設定ファイルの自動生成
対象となるツールは、以前にもブログで紹介した ABAC Generator というツールです:
Microsoft Entra ID 上のグループについて、メンバーを個別に指定するのではなく、所属部署・役職・雇用形態などといった属性情報で条件を指定することにより、合致するメンバーが自動的に更新されるという仕組みです。 (実際よりも項目を端折ってます)
{ id: "abac_managers", name: "マネージャー", mailNickname: "managers", memberConditions: [ { positionId: Positions.マネージャー, } ] }
このような設定ファイルを書いておくと、毎日 Terraform の tf ファイルを最新化する Pull Request が作成され、マージすることでメンバーが更新されます。
resource "azuread_group" "abac_managers" { display_name = "マネージャー" mail_nickname = "managers" members = [ "00000000-0000-0000-0000-000000000000", "11111111-1111-1111-1111-111111111111", "11111111-1111-1111-1111-111111111111", ] }
このツールも 1 年以上運用しており、今では 100 以上のグループが管理され、毎月の組織変更や日々の入社・退社に伴うグループのメンバー変更を担ってくれています。
次の段階としては、やはり設定ファイルの記述を簡単にしたくなってきます。
現在すでに、コーポレートエンジニアリング室内の私以外のメンバーも設定ファイルを書いて、新規のグループを追加したり、既存のグループの設定を変更したりはできています。
コーポレートエンジニアリング室には、私のようにプログラミングの実務経験を積んでいる人もいればそうでない人もいます。
そうでない人にとっては、TypeScript で複雑な設定を記述するのは、やや認知的負荷の高い仕事だと思われます。
また、そうでなくとも、グループのあるべき状態に対して、組織上の部署・役職・雇用形態を正しく把握して、正しい設定に落とし込むこと自体なかなか複雑で、「こういうグループを作りたい」という依頼に対して、組織図とにらめっこが発生することもしばしばあります。
依頼者である従業員の多くはそもそも、頭の中に正確な組織図を持っていることはほとんどないので、そこのコミュニケーションから始まることが多いです。
AI エージェント祭のハッカソンでのチャレンジ
実はこの課題には、先日社内で行われたAI エージェント祭のハッカソンの中でもチャレンジしていました。
その時は Amazon Bedrock AgentCore Runtime や Strands Agents を使って取り組んでいたのですが、その時は時間が限られていたこともあり、SmartHR API を通じた部署情報の取得は諦めて、手書きの JSON をプロンプトに埋め込んだ状態でデモ的な実装のプレゼンに留めました。 (それでも社内ではなかなかの好評をいただきました)
というわけで、今回はより課題に即した形で、実稼働に向けて別のアプローチにチャレンジしてみました。
Claude Code で Agentic Workflow を作る
ABAC Generator の設定ファイルは GitHub 上で管理されており、設定変更時は Pull Request ベースでレビューされ、日次での実行は GitHub Actions 上で行われています。
それであれば、設定ファイルの自動生成も GitHub 内でなんとかしたくなるものです。
とりあえず claude-code-action を検証して色々試行錯誤した結果、実際に動く状態になってきたので、そちらの詳しい手順について共有してみます。
claude-code-action と claude-code-base-action
Claude Code を GitHub Actions 上で利用する claude-code-action ですが、実は claude-code-base-action というものもあり、違いは大まかに以下のようになっています:
- claude-code-action: Pull Request やコメント等の特定のイベントに反応して、コメントを返したりしてくれる
- Claude Code の
/install-github-appでインストールしてくれるのはこちら
- Claude Code の
- claude-code-base-action: より基本的なコンポーネントとして、プロンプトに指定したことをやってくれるが、自動的にコメントを返したりはしてくれない
今回は、コードレビューのような claude-code-action が想定しているユースケースからは外れるため、後者の claude-code-base-action を利用します。
なお、claude-code-base-action のリポジトリは claude-code-action のリポジトリのサブディレクトリから自動でミラーリングされている、とのことではありますが、2025 年 9 月現在の直近ではタグの更新がされていないように見受けられます。
今回は、ドキュメント上で本来想定されている anthropics/claude-code-base-action@beta といった指定ではなく、以下のように利用します。
steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 - id: claude uses: anthropics/claude-code-action/base-action@a3ff61d47aa5118a43b33ae44c4087d9eb51111a with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} prompt: ${{ inputs.prompt }}
設計を考える (1): claude コマンドによる直列 Workflow
今回の課題の解決にあたって、当初は以下のようなイメージを考えていました。
- 関連する部署情報を取得する
- TypeScript で作られた、部署情報を改行区切りの JSON として丸ごと取ってくるだけのツールを使用する
- さらに、ユーザーからのプロンプトに応じて、いい感じにフィルタリングを行う
- ここはなんらかの検索技術でちゃんと作ることも考えられますが、今はコンテキストウィンドウに収まる程度のデータ量なので、実装をサボる意味で LLM 自体にいい感じにフィルタしてもらってます
- それを入力に設定を Claude Code に書かせる
- まずは 1 グループを表現する設定のオブジェクト単体
- それを既存の設定ファイルの中に組み込む
GitHub Actions でいうと、step としてコマンドを呼び出したり、その結果を prompt として与えつつ claude-code-base-action を多段に呼び出すイメージです。
部署情報としては以下のような改行区切りのJSON
これはこれで実現可能ですし、これでやっちゃっても良いぐらいでした。
試行錯誤の段階としてはシェルスクリプトで直接 claude コマンドを実行して、望ましい設定が出力されるか、といったことを確認したり、精度に問題があればより細かいタスクに分解したりして検証を重ねました。
具体的な作業としては異なるものの、先日の手触り感のある Context Engineeringと大まかには同じようなイメージだと思います。
設計を考える (2): Agentic Workflow のフレームワークとしての Claude Code Subagents
別のアプローチとして、Subagents を使ってみることを思いつきました。
第一段階としては以下のような Subagents を作りました:
しかし、これは試している過程で精度があまり出ませんでした。設定としては memberConditions は可変、ownerConditions は常に固定値で良い、としているはずなのに ownerConditions も色々と変えてきたり。
そこで、abac-config-generatorを以下の 2 つに分割しました
-
abac-config-member-conditions-generator: 部署情報をもとにmemberConditionsだけを生成する Subagent-
設定の以下の部分だけを生成する
[ { departmentCode: "1", employmentTypeId: EmploymentTypes.正社員, }, { departmentCode: "1", employmentTypeId: EmploymentTypes.契約社員, }, ]
-
-
abac-config-group-generator: 概ね元のままだが、memberConditionsの生成についてはabac-config-member-conditions-generatorに移譲-
このような設定を生成する
{ id: "abac_corporate_engineering", name: "コーポレートエンジニアリング室", mailNickname: "corporate-engineering", ownerConditions: commonOwnerConditions, memberConditions: [], // 一旦常に空で生成、後でマージさせる }
-
このようにすることで、望ましい設定が生成されるようになりました。
Subagent として作っておくと、今回作っている GitHub Actions だけではなく、これまでの手元で Claude Code を使って設定を書く場合においても同じ Subagent を使い回すことが可能になります。
また、Subagent の組み合わせによってあらゆる問題を解決できるようになるので、柔軟性としても高いと感じました。
例えば、今回は「新規にグループを作成する」というケースだけを対象にしていますが、実際には既存のグループの変更を行うことも多く、その場合は「既存の設定がどこにあるか (ファイル名・行数)」を取得する Subagent も作って、それと組み合わせることで対応ができるはずです。
このように、1つのことをうまくやるパーツを作って組み合わせることであらゆる問題に対処できるようになるのは、UNIX 哲学チックだなと感じます。
どちらのアプローチが良いか
claude コマンドや claude-code-base-action を多段で実行するのは Workflow 的なアプローチです。
処理の流れが決まっている分、カッチリしていて安心できるところもありますが、試行錯誤している段階ではもう少し柔らかく書ける方が嬉しいなも思いました。
一方、Subagents を組み合わせて実行するアプローチはより Agentic であると言えるでしょう。
Subagents はそれぞれで独立したコンテキストを持つエージェントなので、マルチエージェントと呼ぶこともできますが、見方を変えればメインのエージェントが、サブエージェントをツールと見立てて実行することで、全体として 1 つの問題を解決していくものとみなすこともできます。
Subagent の粒度を変えたりする過程の中では素早く試行錯誤できてやりやすかった反面、柔軟すぎるが故にエラーを起こす可能性もあることでしょう。
今回はそれでも安定した出力を生み出せていたので Subagents で問題ないと感じています。
その他 claude-code-base-action を使う上での tips
CLAUDE_WORKING_DIR でサブディレクトリを指定可能
コーポレートエンジニアリング室のリポジトリは monorepo なので、ディレクトリごとに様々な種類の様々なリソースが含まれています。
今回は ABAC Generator の設定ファイルがあるサブディレクトリ内で実行することによって、他のファイルに影響を及ぼす可能性がなくせますし、Subagents の定義もリポジトリ全体ではなく ABAC Generator 専用というのを明確にする意味で、サブディレクトリで起動できることは割と重要です。
全体としてはこのような Workflow になっています:
name: abac-generator-gen on: workflow_dispatch: inputs: prompt: description: Prompt for Claude Code required: true jobs: gen: runs-on: ubuntu-latest permissions: contents: write pull-requests: write id-token: write steps: - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 id: app-token with: app-id: ${{ vars.GH_APP_ID }} private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - uses: actions/checkout@v5.0.0 with: token: ${{ steps.app-token.outputs.token }} - id: claude uses: anthropics/claude-code-action/base-action@v1.0.6 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} prompt: ${{ inputs.prompt }} claude_args: '--allowed-tools "Bash(git checkout:*) Bash(git config user.email:*) Bash(git config user.name:*) Bash(git add:*) Bash(git commit:*) Bash(git push:*) Bash(gh pr create:*) Edit MultiEdit Write"' env: CLAUDE_WORKING_DIR: yuya GH_TOKEN: ${{ steps.app-token.outputs.token }} - run: cat "$CLAUDE_CODE_RESULT" | jq '.[] | select(.type == "result") | .result' -r env: CLAUDE_CODE_RESULT: ${{ steps.claude.outputs.execution_file }}
まとめ
社内のあらゆるリソースやフローの「あるべき姿」をコードとして定義できることは、それらの管理にかかる労力をコーディングエージェントに移譲できるという意味でとても重要な時代になってきました。
さらに、GitHub Actions や claude-code-base-action、そしてその中で複数の Subagents を組み合わせて問題を解決するというアプローチは、これまでの自動化とは違った便利さ・面白さがあります。
複数の自律的なエージェントやツールを組み合わせることで問題解決が加速できそうな予感もあり、とにかく手癖のように AI エージェントを作れるようになっておくこと、そんな AI エージェントが活躍できるように業務環境を整えておくことが重要だなと感じます。
LayerX AI Agentブログリレーはまだまだ続きます。
LayerX Tech公式Xを是非フォローして見逃さないようにお願いします!
これからも色々なアプローチを試して実践投入していきます!コーポレートエンジニア的には AI エージェントの実装だけでなく、業務への適用や組織への働きかけなど、さまざまなトピックがあると思うので、この辺興味ある人は是非お話ししましょう!
コメント