AI Agentが「質問に答える」だけでなく、ユーザーの代わりに実際の操作をするケースが増えてきました。
例えば、
- 商品を購入する
- ホテルを予約する
- メールを送信する
- GitHub Issueを作成する
- 社内システムを更新する
といった操作です。
RailsアプリケーションにAI Agentを接続することを考えていて、一つ気になったことがありました。
「このAgentは、誰の代理として、どこまで操作してよいのか?」をRails側でどう管理するのか?
この問題をRailsらしく扱うために、OSS Gem ActingFor を作りました。
現在 v0.1.0 を公開しています。
きっかけ
通常のRailsアプリでは、
current_user
を中心に認証・認可を考えることが多いと思います。
CanCanCanやPunditなどを使えば、
このUserは、この操作をしてよいか?
を判断できます。
ところが、AI AgentがUserの代理として操作する場合は少し違います。
例えばUserがShopping Agentに、
「私の代わりに商品を買っていい。ただし10,000円まで」
と権限を与えたとします。
このときRails側で知りたいのは、
このUserは商品を購入できるか?
だけではありません。
どのAgentなのか?
↓
誰の代理なのか?
↓
purchase権限を委任されているか?
↓
対象の商品は?
↓
金額制限を超えていないか?
↓
期限切れではないか?
↓
権限がrevokeされていないか?
まで判断する必要があります。
そこでActingForでは、
User(Principal)とAgentを別の主体として扱う
ことを基本にしました。
ActingForとは
ActingForは、
Rails-native delegated authorization for AI agents.
を目的としたRails Engineです。
簡単に言えば、
AI Agentが「誰の代理として、何をしてよいか」をRailsで判定する
ためのGemです。
全体像はこうなります。
User / Principal
│
│ 権限を委任
▼
AI Agent
│
│ 操作を要求
▼
Rails Application
│
▼
ActingFor
│
├─ Agentは誰?
├─ 誰の代理?
├─ 権限は委任されている?
├─ 制約を満たしている?
├─ 有効期限内?
└─ revokeされていない?
│
▼
allow / require_approval / deny
│
▼
Rails Business Logic
具体例:Shopping Agent
UserがShopping Agentに、
10,000円までの商品なら購入してよい
という権限を与えたケースを考えます。
User
│
│ 「10,000円まで買っていい」
▼
Shopping Agent
│
│ Product ¥8,900を購入したい
▼
Rails
│
│ DBからProductを取得
▼
ActingFor
│
├─ Agentは誰?
├─ 誰の代理?
├─ purchase権限がある?
├─ Productは対象?
├─ 期限内?
├─ revokeされていない?
└─ ¥8,900 <= ¥10,000?
│
▼
ALLOW
│
├─ AuditEventを保存
▼
Rails
│
▼
Purchase作成
重要なのは、AI Agent自身に「8,900円だから大丈夫」と判断させないことです。
Railsアプリケーションが信頼できるDBから商品の価格を取得し、その値を使ってActingForが認可を判定します。
実際のコード
まずPrincipalからAgentへ権限を委任します。
ActingFor.delegate(
agent: shopping_agent,
principal: user,
action: :purchase,
resource: Product,
constraints: [
{ field: "amount", operator: "lte", value: 10_000 }
],
effect: :allow
)
これは、
shopping_agent が
user の代理として
Productを
10,000円以下なら
purchaseできる
というDelegationです。
Agentが実際に購入を要求したら、Rails側でProductを取得して認可します。
product = Product.find(params[:product_id])
decision = ActingFor.authorize(
agent: shopping_agent,
principal: user,
action: :purchase,
resource: product,
context: {
amount: product.price
}
)
Decisionは3種類です。
decision.allowed?
decision.denied?
decision.approval_required?
つまり、
ALLOW
REQUIRE_APPROVAL
DENY
です。
なぜALLOW / DENYだけではないのか
AI Agentでは、
「禁止するほどではないけれど、勝手には実行してほしくない」
という操作があると思います。
例えば、
1,000円の商品
→ Agentだけで購入してよい
30,000円の商品
→ 本人に確認してから購入
500,000円の商品
→ Agentには許可しない
というケースです。
そこでActingForでは、
allowrequire_approvaldeny
の3種類をDecisionとして扱います。
なお、本人承認のUIやワークフローそのものはRails Host Application側の責務です。
ActingForは、
「この操作には本人承認が必要」
というDecisionを返すところまでを担当します。
CanCanCan / Punditとは何が違う?
このGemを作るとき、自分自身も最初に考えました。
CanCanCanやPunditがあるなら、それでいいのでは?
自分の中では、責務を次のように整理しています。
CanCanCanは「このUserが何をできるか」を判断する。
ActingForは「このAgentが、そのUserの代理として何をできるか」を判断する。
例えば、
User A
│
├─ 自分で商品を購入
│ ↓
│ CanCanCan / Pundit
│
└─ Shopping Agentへ委任
↓
ActingFor
↓
「User Aの代理として
このAgentは購入可能か?」
という関係です。
CanCanCan/Punditを置き換えるというより、認可する対象・問題が違うと考えています。
Auditとの違い
ActingForでは、認可判定時にAuditEventも保存します。
一般的なAuditが、
何が起きたか
を記録するものだとすると、ActingForでは、
代理認可でどのDecisionを行ったか
を記録します。
例えば、
Agent: shopping-agent
Principal: User A
Action: purchase
Resource: Product #123
Amount: 8,900
Decision: allow
といった情報です。
AI Agentが自律的に操作するようになるほど、
なぜこの操作が許可されたのか?
を後から追えることも重要になると考えています。
MCPとはどういう関係?
MCPを使うと、AIクライアントからRailsアプリケーションのToolを呼び出す構成が考えられます。
例えば、
ChatGPT / Claude
│
│ MCP
▼
purchase_product
│
▼
Rails
しかし、
Toolを呼べることと、
そのAgentが、そのUserの代理として、そのToolを実行してよいこと
は別の問題です。
そこで、
AI Agent
│
│ MCP
▼
Rails
│
│ purchase_product
▼
ActingFor
│
▼
ALLOW / REQUIRE_APPROVAL / DENY
という位置にActingForを置きます。
つまり、
MCP gives Agents a way to interact with your Rails application.
ActingFor adds delegated authorization behind that interaction.
という責務分離です。
ActingForはMCP専用ではありません。
REST API、Background Job、独自Agentなどからも利用できます。
Agent認証はActingForの責務ではない
ここも意図的に分離しています。
ActingForはAgent Authenticationを提供しません。
つまり、
「このリクエストが本当にShopping Agentから来たのか?」
をActingFor自身が証明するわけではありません。
イメージとしては、
OAuth / OIDC / etc.
│
│ Agentを認証
▼
Rails
│
│ Agentを特定
▼
ActingFor
│
│ 委任権限を判定
▼
ALLOW / REQUIRE_APPROVAL / DENY
です。
OAuth / OIDC / MCPなどと競合するのではなく、ActingForは代理権限の認可に集中します。
インストール
RubyGemsからインストールできます。
gem "acting_for", "~> 0.1.0"
bundle install
bin/rails acting_for:install:migrations
bin/rails db:migrate
v0.1.0ではCIで、
- Ruby 3.4 / 4.0
- Rails 8.0 / 8.1
- PostgreSQL 16
を対象にしています。
詳しい導入方法はGitHubのGetting Startedにまとめています。
v0.1で意図的に作らなかったもの
ActingForでAI Agent基盤を全部作ろうとはしていません。
v0.1では、
- Agent
- Delegation
- Authorization
- Constraints
- Expiry / Revocation
allow / require_approval / deny- Audit
- Rails integration
に集中しています。
逆に、
- OAuth Server
- 独自Agent ID規格
- MCP Server
- Agent間通信
- 決済機能
- 管理画面
などはActingForの責務にしていません。
「AI Agentに関係するものを全部作る」のではなく、「RailsにおけるDelegated Authorization」に集中する。
という方針です。
おわりに
ActingForはまだ v0.1.0 です。
このGemを作った一番のきっかけは、
AI Agentが「提案する」だけでなく「ユーザーの代理で実際に操作する」ようになったとき、Rails側ではその代理権限をどう管理するのか?
という疑問でした。
Authenticationだけでは、
「このAgentは誰か」
までは分かっても、
「このAgentは、このUserの代理として、どこまでやってよいか」
までは表現できません。
ActingForでは、この部分をRails向けの小さなGemとして切り出してみました。
まだ公開したばかりなので、設計・APIともに改善していきたいと思っています。
同じような問題を考えているRails開発者の方がいれば、Issueやフィードバックをもらえるとうれしいです。
