
GitHub
イベント
マガジン
技術ブログ
はじめに こんにちは。メルカリのAI Securityエンジニアの @hi120ki です。 メルカリでは、AI Agentサービス Devin を社内の複数チームに展開しています。Devinは自律的にコードの調査・作成・PR提出までをこなせるサービスですが、組織として運用するうえでは管理上の課題がいくつかあります。 本記事では AI Securityチーム がAI Agent Platformチームと協力し、Devin Enterprise APIを活用したカスタムTerraformプロバイダーと自動管理ツール群を自作しました。これにより、メンバーと権限の管理・シークレットローテーション・APIキーのライフサイクル管理・監査の仕組みを構築した取り組みについて紹介します。 Enterprise運用の課題 メルカリではDevinのEnterpriseプランを採用しています。Remote環境で動作するAI Agentを組織的に運用するためにOktaによるSSO、監査ログ、権限の管理、チームごとの環境分離が必須要件であり、これらを満たすために選定しました。 Devin EnterpriseではCoreプランやTeamプランのように1つのOrganizationを共有するのではなく、Enterpriseという管理基盤から複数のOrganizationを一元管理します。メルカリには複数のビジネス領域にまたがる多数のチームがあり、各チームが扱う情報を分離して保護する必要があります。そのためチームや目的に応じてOrganizationを割り当てています。 ただし、10以上のOrganizationと多数の利用者を抱える環境では、次の課題が生じます。 権限管理の課題 メンバーのOrganizationへのアサインが手動操作に依存 「誰がどのOrganizationに所属しているか」の状態管理が困難 シークレット管理の課題 各Organizationにサードパーティサービスごとの認証情報を個別に設定する必要 シークレットを手動で一斉ローテーションする手間 アクセス権の課題 Devin APIキーの有効期限管理が標準機能として提供されておらず、各Organization内に長期間未ローテーションのAPIキーが残存するリスク Devinの活用が広がるほど管理するOrganizationも増え、これらの課題の負担は拡大します。以前はWeb UIでの手作業に頼っていましたが、2025年末以降DevinがEnterprise向けAPIを v2 から v3 へ拡充したことで、ほとんどの管理操作をAPI経由で自動化できるようになりました。これを受け、Go言語とGitHub Actionsを用いた管理基盤を内製しています。 Devin APIの概要 Devinは v3 として 最新のEnterprise管理向けAPI を提供しています。Enterprise・Organization単位のMember・Role管理や、各OrganizationのSecret・Knowledgeを操作できます。v3 APIで以下の自動管理機能を実現しました。 カスタムTerraformプロバイダー シークレットの一斉ローテーション Google Cloudサービスアカウントキーのローテーション セキュリティ管理基盤との連携 APIキー管理のみ v2 API を使用しています。v2 APIでは複数OrganizationにまたがるAPIキーの作成・取得・削除が可能で、以下を実施しています。 利用者が発行したAPIキーの定期無効化 社内AgentのDevin Wiki利用向けAPIキー管理 これらのAPI仕様はREST形式のAPIとしてDevinの公式ドキュメントにリクエストおよびレスポンスの詳細な仕様とともにドキュメント化されており、一般的なREST APIクライアントを実装することでそれぞれの機能を呼び出すことができます。今回これらのREST APIクライアントは、メルカリ社内で広く用いられているGo言語を用いてそれぞれのAPIが関数に対応するように実装し再利用しやすいように整備しました。 以下の章からそれぞれの管理機能の詳細を紹介します。 1. カスタムTerraformプロバイダー 管理基盤の中核は、 Terraform Plugin Framework で構築したカスタムTerraformプロバイダーによるOrganizationおよびメンバー管理です。 メルカリではGoogle Cloudをはじめリソース管理にTerraformを広く利用しており、エンジニアが日常的に扱っている点から採用しました。DevinをInfrastructure as Codeで管理すると、メンバー追加や権限変更にPRレビューを挟める・Organizationやメンバーの状態をコードで把握できるようになります。公式のTerraformプロバイダーは現時点で提供されていないため自作しました。 利用者や管理者は各チーム用のOrganizationをTerraformで定義します。ACU(Agent Compute Unit)上限もここで設定し、チームごとの利用量を制御します。 max_cycle_acu_limit はOrganization全体のACU上限、 max_session_acu_limit は1セッションあたりの上限で、想定外のコスト超過を防ぎます。 resource "devin_organization" "mercari_example_team" { name = "mercari-example-team" max_cycle_acu_limit = 500 max_session_acu_limit = 250 } またメンバーのOrganizationへのアサインもTerraformで宣言的に管理します。 # メンバー定義(メールアドレスで参照) data "devin_member" "mercari_example_team" { for_each = toset([ "user-1@example.com", "user-2@example.com", "user-3@example.com", ]) email = each.value } # Organizationへのアサイン resource "devin_organization_member" "mercari_example_team" { for_each = data.devin_member.mercari_example_team user_id = each.value.user_id org_id = devin_organization.mercari_example_team.org_id org_role_id = "mercari_org_member" } Organizationの追加やACU上限の変更、メンバーの追加・削除は、Terraformコードの変更→PRレビュー→マージという通常の開発フローで行います。 terraform plan の出力で「誰がどのOrganizationに追加/削除されるか」が明確にわかり、意図しない権限変更を防げます。 このTerraformプロバイダーではDevin Knowledgeも管理できます。KnowledgeはDevinにおけるAgent Skillのような存在です。メルカリのDevin環境では各チームが別々のOrganizationに分かれており、互いの利用状況を閲覧できません。セキュリティ面では望ましい分離ですが、活用ノウハウの共有が難しくなります。Knowledgeをプロバイダーで管理できるようにし、チーム間での活用ノウハウの配布を可能にしました。 2. シークレットの一斉ローテーション DevinはSessionごとに独立した仮想マシンを起動するため、初期状態ではGitHub等ソースコード管理サービスへの権限しか持ちません。クラウド環境やチケット管理サービスなどへ接続するには、APIキー等の認証情報を個別に設定する必要があります。 一方、DevinはAI Agentとして与えられたAPIキーを自由に扱えるうえ、Organization内のメンバーはSession内部のファイルシステムやシェルにアクセスできるため認証情報の取り扱いには注意が必要です。そこでメルカリでは、Devinに設定するAPIキー群を管理者が一元管理し、短い間隔で定期ローテーションすることで、長期間有効な認証情報がDevin上に残らないようにしています。 ただし手動でのローテーションは負担が大きく、以前は多数のOrganizationの複数Secretをローテーションするだけでかなりの時間を要していました。しかしDevinが 2026年1月にSecret管理機能をv3 APIへ追加 したことで、これらの操作を自動化できるようになりました。現在のローテーション手順は以下のとおりです。 Devin管理者がそれぞれのサービスで認証情報をローテーションする 新しい認証情報を事前に作成済みのGoogle Cloud Secret Managerに追加する 自動化をGitHub Actions経由で起動する ローテーションが実行され、Secret Managerから各Organizationに配布される これにより、最小限の作業で10以上のOrganizationのシークレットを一斉ローテーションできるようになりました。 3. Google Cloudサービスアカウントキーのローテーション メルカリでは主にGoogle Cloudを利用しておりライブラリの取得やテスト環境との接続にはGoogle Cloudの権限をDevinに付与する必要があります。しかしDevinは現在 Workload Identity Federation に対応できるようなOIDCトークン発行機能がないため、サービスアカウントキーを用いる必要があります。 しかし前提として、メルカリでは Google Cloud公式のベストプラクティス に従い、Organization Policyでサービスアカウントキーの発行を一律禁止しています。このためDevin専用のGoogle Cloud Projectを設け、さらに iam.serviceAccountKeyExpiryHours を追加のOrganization Policyとして設定しました。これにより、自動化が停止した場合でもサービスアカウントキーは一定期間で無効化されます。 この仕組みのうえで、Organizationごとに個別のサービスアカウントキーを定期ローテーションしながら付与しています。 4. セキュリティ管理基盤との連携 Devin Enterprise採用の要件の一つに監査ログがあります。メルカリではAI Security および Threat Detection and Response チームのAnnaがDevin v3 APIを通じて 内製セキュリティ監視プラットフォーム との連携を構築しました。 この連携では、Admin権限を持つEnterprise Service Userと Enterprise Audit Logs エンドポイントを利用しています。これはv2 APIにおけるエンドポイントとは異なりページネーションがあるため、すべての監査ログを正確に取得することができます。これによりGoogle CloudのCloud Run Job を使って5分おきにAPIを取得し、前回取り込んだ最後の監査ログのタイムスタンプ以降の新規監査ログをすべて取得したうえでGoogle CloudのPubSubトピックへと転送しています。そして転送された監査ログはセキュリティ調査のためのBigQueryに保存されます。 5. 利用者が発行したAPIキーの定期無効化 Enterprise全体のAPIキーを全件取得し、作成から一定期間が経過したキーを自動で無効化します。Devinの標準機能にはないセキュリティポリシーを、APIで独自に実装しました。 これらのAPIキーは主に Devin MCP の接続に用いられます。APIキー経由で間接的にソースコードを取得できるため、厳格な管理が求められます。AI Agentを複数利用する開発環境では、使わなくなったAgentの設定ファイルに認証情報が残る・個人のAPIキーを複数人が利用する自作Agentに設定して社内公開してしまう、といった事態が起こりえます。 一定期間経過したAPIキーを自動無効化することで、利用中のAgentだけがAPIキーを保持する状態を維持し、複数人で共有するAgentには、次章で紹介するGoogle Cloud Secret Manager経由のAPIキーを利用させることで、Agentが持つ権限の可視化も実現しました。 6. 社内AgentのDevin Wiki利用向けAPIキー管理 メルカリでは各チームの開発用Organizationとは別に、Devin Wiki用のOrganizationを運用しています。Devin Wikiは Devin MCP 経由でリポジトリの内容を取得したり、自然言語で検索したりできます。 ソースコードの探索をAI Agentが直接行うとコンテキストを大量に消費します。ソースコード調査が必要な場面ではDevinに処理を委託することで、コンテキスト消費を抑えられます。 ただし Devin MCP の利用にはAPIキーが必要で、前章のとおり一定期間で自動無効化されます。例外となるAPIキーを設けることもできますが、目的外利用を完全には防げません。そこでAPIキーを短い間隔で定期的に再作成し、Google Cloud Secret Managerに保存する自動化を構築しました。 これにより、Devin MCPを利用するAI AgentのサービスアカウントをTerraform上で一元管理し利用状況を可視化するとともに、APIキーの定期再作成による目的外利用の防止も実現しました。 resource "google_secret_manager_secret" "shared_wiki_api_key" { secret_id = "shared-wiki-api-key" } resource "google_secret_manager_secret_iam_member" "shared_wiki_api_key" { for_each = toset(local.accessor_service_accounts_shared_wiki_api_key) secret_id = google_secret_manager_secret.shared_wiki_api_key.secret_id role = "roles/secretmanager.secretAccessor" member = "serviceAccount:${each.value}" } locals { accessor_service_accounts_shared_wiki_api_key = [ "agent-1@---.iam.gserviceaccount.com", "agent-2@---.iam.gserviceaccount.com", ] } 管理操作を動かすCIパイプライン これらの管理操作はすべてGitHub Actionsで自動化しています。SaaS管理向けに独自管理ツールを作る場合、長期的なメンテナンスが避けられません。組織変更時の引き継ぎも考慮すると、依存関係を小さく保ち、メンテナンスしやすい技術・プラットフォームを選ぶ必要があります。 Secret ManagerやサービスアカウントはGoogle Cloud上に置きつつも、処理の実行にはGitHub Actionsを選びました。リポジトリ内の自動化がデプロイなしで直接動作するためメンテナンスの手間が減り、不要なクラウドリソースを持たないことでコストと管理・引き継ぎ時の認知負荷も抑えられます。また定期実行に加え手動トリガー( workflow_dispatch )にも対応しており、緊急時のシークレットローテーションを即座に実行できます。 一方、GitHub Actionsは自由に実行できてしまうため、権限管理や ブランチ保護の設定 を厳格に行っています。認証情報の取得には Google Cloud Workload Identity Federation を使用し、GitHub ActionsからサービスアカウントやSecret Managerへ 安全にアクセス しています。 まとめ Devin Enterpriseを大規模に運用するにあたり、標準機能だけではカバーできない管理要件を、v2およびv3 APIを活用した自作ツールで補いました。これにより、これまで手作業に依存していた管理上の課題を克服し、多数のOrganizationを同時に提供しつつ適切に管理できるようになりました。 現在提供されているDevin v3 APIには、Enterprise管理に必要なエンドポイントが揃っています。今後は、Devinの機能拡張に合わせて、さまざまなリソースの管理を安全性を維持したまま自動化していく計画です。 また、この記事が、同様の課題を抱えている方の参考になれば幸いです。 メルカリでのAI/LLM活用やセキュリティに関する取り組みに興味がある方は、ぜひ メルカリの採用ページ をご覧ください。
概要 前回の記事「 SSL/TLS証明書の有効期限短縮に備えて脱・手動更新① 」の続きとなります。 本記事では、Certbotサーバがどのように認証局(CA)から証明書を取得するのか、 そのための手段としてACME-DNSというソフトウェアがどのように関わるのかを説明します。 CertBOTを用いた証明書発行と設定の流れ Certbotが認証局(CA)から証明書を取得しする過程はこちらの図の通りですが、 これは大まかな流れとなります。 CAがCertBOTサーバに対して行うドメイン所有確認の手法には、 HTTP-01チャレンジとDNS-01チャレンジがあります。 HTTP-01 チャレンジは、 Web サーバーを使ってドメインの所有を証明する方式です。 Let’s Encryptなど認証局 は、「このドメインの管理者であるなら、Web サーバー上の特定の場所に指定した内容のファイルを置けるはずだ」という考え方で確認を行います。 ただし、認証局が対象ドメインに対して HTTP(ポート80)でアクセスするため、インターネットから対象ドメインの80番ポートへアクセスできる必要があります。 Webサーバーを公開していない環境や、80番ポートを外部公開できない環境では利用できないという制約があります。 本記事ではそのような制約を受けないDNS-01チャレンジを採用します。 DNS-01チャレンジ DNS-01チャレンジでは、下記のような流れで証明書取得が行われていきます。 HTTP-01チャレンジが「Web サーバーに置いたファイル(トークン)を見に来る」方式なのに対し、DNS チャレンジは「DNS に登録された情報を見に来る」方式です。 HTTP-01チャレンジとDNS-01チャレンジ、それぞれの特徴を比較すると表のようになります。 DNS-01チャレンジは80 番ポートの公開が不要であるため、メールサーバーや LDAPサーバーなど80 番ポートを使わないサーバーを対象にドメインの所有確認ができ、証明書自動取得を行えます。 一方で、DNS-01チャレンジには注意点もあります。一部のDNSサービスでは、そもそもAPIが公開されておらず、Certbotから自動で書き換える手段がありません。 すべての DNS プロバイダがAPI を提供しているわけではないため、APIがない場合はDNS-01 チャレンジの自動化はできず、更新のたびに手作業が必要になります。 その課題に対する対処法として、acme-dns というオープンソースソフトウェアが挙げられます。 ACME-DNSとは ACME-DNSは、DNS-01 チャレンジ認証を実施するための簡易 DNS サーバ、Web API サーバ機能を有するソフトウェアです。 https://github.com/joohoi/acme-dns acme-dns を使う場合、実際の DNS には最初に一度だけ設定を行います。 まず、ドメインを管理するDNS側で、サブドメイン(_acme-challenge)を、CNAMEを使ってACME-DNSサーバーへ向くように設定(委任)します。 これにより、認証局からのドメイン所有確認のクエリは、自動的にACME-DNSサーバーへと転送されるようになります。 また、ACME-DNSサーバーへの問い合わせを委任するための情報として、Aレコード、acme.example.comのNSレコードもメインのDNSに登録しています。 委任に必要なUUIDとはACME-DNSがFQDNごとに発行するもので、 ACME-DNSサーバーのエンドポイントを叩いた際に発行される情報ですが、 それを取得するコマンドはこの後説明させていただきます。 CertbotとACME-DNSを用いて証明書取得を行う具体的な流れは6つのステップです。 (なお、今回構築する環境では、CertbotとACME-DNSの機能が1つのサーバに同居している構成としています) まず、CertbotがACMEサーバに証明書を要求し、それに対してACMEサーバがドメイン所有を確認しようとDNSチャレンジを要求します。 次に、CertbotはACME-DNSのAPIを叩き、取得する証明書のFQDNに対応するUUIDのレコードに検証用トークンを書き込みます。 ACMEサーバがDNS検証を開始します。 メインDNSはCNAME設定に従い、問い合わせをACME-DNSサーバへ転送します。 ACME-DNSがUUIDに基づいた適切なトークンを回答することで検証が成功し、 証明書が発行されます。 結果、DNSのプロバイダにAPI がなくても、DNS チャレンジの自動更新が可能になります。CNAMEレコードさえ設定すればDNSのレコードを手でいじる手間がなくなり自動更新されるものとなります。 ACME-DNSの構築手順 まずは、ACME-DNSのソースコードを取得します。 # ACME-DNSのソースをGithubから取得 $ git clone https://github.com/joohoi/acme-dns # 設定ファイルやデータベース用のディレクトリを作成 $ cd acme-dns $ mkdir data db 次に、オリジナルをコピーした上で、設定ファイルを編集します。 $ cp config.cfg config.org $ vim config.cfg 下記のような内容に編集します。 [general] # DNS interface. Note that systemd-resolved may reserve port 53 on 127.0.0.53 # In this case acme-dns will error out and you will need to define the listening interface # for example: listen = "127.0.0.1:53" #listen = "127.0.0.1:53" listen = "0.0.0.0:53" # protocol, "both", "both4", "both6", "udp", "udp4", "udp6" or "tcp", "tcp4", "tcp6" protocol = "both" # domain name to serve the requests off of domain = "auth.example.org" # acme-dns が管理する DNS ゾーン名 # zone name server nsname = "auth.example.org" # domain で指定したゾーンのネームサーバ名 # admin email address, where @ is substituted with . nsadmin = "admin.example.org" # SOAレコード内の管理者メールアドレス # predefined records served in addition to the TXT records = [ # acme-dns サーバが固定で返す DNS レコードを定義 # domain pointing to the public IP of your acme-dns server auth.example.org. A 198.51.100.1, # specify that auth.example.org will resolve any *.auth.example.org records auth.example.org. NS auth.example.org., ] # debug messages from CORS etc debug = true # デバッグ用の詳細ログを出力するかどうかを指定する項目 [database] # Database engine to use, sqlite3 or postgres engine = "sqlite3" # acme-dns が TXT レコードや登録情報を保存するデータベースの種類を指定 # Connection string, filename for sqlite3 and postgres://$username:$password@$host/$db_name for postgres # Please note that the default Docker image uses path /var/lib/acme-dns/acme-dns.db for sqlite3 connection = "/var/lib/acme-dns/acme-dns.db" # データベースへの接続情報(保存先)を指定 # connection = "postgres://user:password@localhost/acmedns_db" [api] # listen ip eg. 127.0.0.1 #ip = "0.0.0.0" ip = "127.0.0.1" # API サーバが待ち受ける IP アドレスを指定。ACME-DNSサーバー内でAPI叩く構成であれば 127.0.0.1 を指定。 # disable registration endpoint disable_registration = false # /register エンドポイントを無効化するか指定する項目。false を設定することで、新しいサブドメインを ACME-DNS に登録することが可能。 # listen port, eg. 443 for default HTTPS port = "8080" # APIサーバの待受ポート # possible values: "letsencrypt", "letsencryptstaging", "cert", "none" tls = "none" # APIとの通信を HTTPS (TLS) で暗号化するかどうかを指定 # only used if tls = "cert" # tls = "cert" を選んだ際に使用する項目。ACME-DNS の API との通信を暗号化する際に使用する SSL/TLS 証明書のパスを指定。 tls_cert_privkey = "/etc/tls/example.org/privkey.pem" tls_cert_fullchain = "/etc/tls/example.org/fullchain.pem" # only used if tls = "letsencrypt" acme_cache_dir = "api-certs" # tls = "letsencrypt" を選んだ際、API との通信に使用する証明書を保存するディレクトリ # optional e-mail address to which Let's Encrypt will send expiration notices for the API's cert notification_email = "" # tls = "letsencrypt" に設定している場合に使用。ACME-DNS の API との通信を暗号化する際に使用する証明書の期限を通知する先のメールアドレスを指定。 # CORS AllowOrigins, wildcards can be used corsorigins = [ # ブラウザから API を呼び出せる Web ページのドメインを指定する設定。 * ] # use HTTP header to get the client ip use_header = false # 接続してきたクライアントのIPアドレスを特定する際に、HTTPヘッダーの情報を使用するかどうかを指定する項目。 # header name to pull the ip address / list of ip addresses from header_name = "X-Forwarded-For" # use_header = true に設定した場合に、どの名前のHTTPヘッダにIPアドレスが入っているかを指定。 [logconfig] # logging level: "error", "warning", "info" or "debug" loglevel = "debug" # ログの出力レベルを指定 # possible values: stdout, TODO file & integrations logtype = "stdout" # ログの出力先を指定 # file path for logfile TODO # logfile = "./acme-dns.log" # format, either "json" or "text" logformat = "text" # 記録されるログのフォーマットを指定 設定ファイルを編集したら、諸々の準備を行います。 # Go言語の開発環境(コンパイラ)をインストール $ sudo dnf install -y golang # ソースコードから実行可能なプログラムを生成 $ go build # ビルドしたプログラムを、システム全体の実行用フォルダへ配置 $ sudo cp acme-dns /usr/local/bin/ # 配置されたことを確認 $ which acme-dns # 設定ファイル用のディレクトリを root 権限で作成 $ sudo install -d -m 755 -o root -g root /etc/acme-dns # 専用ユーザーの作成(この手順ではacmednsというユーザでACME-DNSを実行させることとしています) getent passwd acmedns || sudo useradd -r -s /sbin/nologin -d /var/lib/acme-dns -M acmedns # 設定ファイルをコピーしつつ、所有者を root、グループを acmedns に設定 # /path/to は git clone を実行ユーザーの home ディレクトリに置き換えます $ sudo rsync -a --chown=root:acmedns /path/to/acme-dns/config.cfg /etc/acme-dns/ # データディレクトリの作成と権限設定 sudo install -d -m 700 -o acmedns -g acmedns /var/lib/acme-dns # データベースファイルの空作成 sudo test -f /var/lib/acme-dns/acme-dns.db || sudo touch /var/lib/acme-dns/acme-dns.db # ファイルの所有権変更 sudo chown acmedns:acmedns /var/lib/acme-dns/acme-dns.db # ファイルのアクセス権制限 sudo chmod 600 /var/lib/acme-dns/acme-dns.db # 一般ユーザー(acmedns)に、特権が必要なポート(53番)を使うための権限を付与 $ sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/acme-dns 次に、ACME-DNSをSystemd化させて常駐化します。 $ sudo vim /etc/systemd/system/acme-dns.service こちらのファイルを下記のように編集します。 [Unit] Description=acme-dns authoritative DNS server for ACME DNS-01 Wants=network-online.target After=network-online.target [Service] User=acmedns Group=acmedns ExecStart=/usr/local/bin/acme-dns -c /etc/acme-dns/config.cfg WorkingDirectory=/var/lib/acme-dns Restart=on-failure RestartSec=2s # 低権限でも 53 を開ける(setcapコマンドを実行しているので不要ですが予備措置として記載) AmbientCapabilities=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_NET_BIND_SERVICE NoNewPrivileges=true # ログは journal に流す StandardOutput=append:/var/log/acme-dns/acme-dns.log [Install] WantedBy=multi-user.target 編集後、サービスを読み込んで起動。 $ sudo systemctl daemon-reload $ systemctl restart acme-dns ここまで実行すれば、ACME-DNSの初期設定・構築は完了です。 次に、「3. 認証スクリプトの用意」のステップへ進みますが、次回の記事にて解説させていただきます。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post SSL/TLS証明書の有効期限短縮に備えて脱・手動更新② first appeared on SIOS Tech Lab .
はじめに AI エージェントをオープンソースのフレームワークで作ろうとすると、実装はもちろんですが「コンテナ化」「Webサーバー構築」「認証・セキュリティ統合」「スケーリング」「監視」「ロールバック」といった運用まわりの課題に直面することが多いのではないでしょうか。 Microsoft Foundry の Hosted Agents は、こうした "エージェントを動かし続けるための面倒ごと" をプラットフォーム側に任せ、開発者が エージェントの振る舞いそのものに集中できる ようにするためのフルマネージドな AI エージェント実行基盤です。 Microsoft Foundry 上で実行





















