Microsoft developer platform documentation update: Agent Message and Task – Fix modifying functions to only modify the target values は、Dynamics 365 Business Central の AL 拡張で Agent Message や Agent Task を操作している開発者が早めに確認すべき更新です。結論から言うと、UpdateText、SetStatusToSent、SetStatusToReady、StopTask、RestartTask などで Record 変数を渡して更新しているコードは、TaskID / MessageID / AgentTaskID などの主キーを渡す呼び出しへ移行する準備をしてください。PRでは、var record パラメーターを使う更新APIが、対象フィールド以外の変更まで保存し得る問題として説明されています。(GitHub)
今回の変更は、単なるドキュメント表現の調整ではありません。呼び出し元が持っている Record に未保存の変更、いわゆる「dirty record」が残っている状態で更新メソッドを呼ぶと、本来はステータスや本文だけを変えたいのに、別フィールドまで書き戻される可能性がありました。PRの修正方針は、主キーで最新レコードを再取得し、対象フィールドだけを変更して保存する方向です。(GitHub)
なお、2026年5月6日時点で、関連PR #7618 は Open、Version 29.0 マイルストーン、AL: System Application ラベル付きで表示されています。また、2026年5月5日には “part 2” のPR #7979 も作成され、こちらは Draft として扱われています。実装に反映する際は、最終的なマージ状態と利用中の Business Central バージョンで確認してください。(GitHub)
Microsoft developer platform documentation updateで何が変わるのか
今回の更新対象は、Microsoft developer platform 全体の抽象的な仕様変更というより、microsoft/BCApps リポジトリ内の System Application / Agent / Interaction 周辺にある AL codeunit の変更です。PRの差分では、AgentMessage.Codeunit.al、AgentTask.Codeunit.al、AgentTaskMessageBuilder.Codeunit.al、内部実装の AgentMessageImpl.Codeunit.al、AgentTaskImpl.Codeunit.al、関連ページ、テストコードなどが対象に含まれています。(GitHub)
Business Central のエージェント機能は、ALコードから agent task を作成・管理し、UIアクション、ビジネスイベント、カスタムワークフローなどと連携できる仕組みです。Microsoft Learn でも、この領域はプレビュー機能として説明されており、agent task をプログラムからトリガーできること、Agent Task Builder codeunit がタスク作成の主要インターフェースであることが示されています。(Microsoft Learn)
今回の要点は、次の3つです。
| 確認項目 | 内容 | 開発者が見るべきポイント |
|---|---|---|
| APIの呼び出し方法 | Recordを渡す更新メソッドから、主キーを渡すメソッドへ寄せる | var AgentTaskMessage や var AgentTask を渡す箇所を検索する |
| 更新対象 | メッセージ本文、メッセージステータス、タスク状態など | 更新対象以外のフィールドが保存されないか確認する |
| 移行タイミング | PR時点では一部メソッドに「今後obsolete予定」のコメントがある | コンパイラ警告、参照ドキュメント、Version 29.0以降の差分を追う |
なぜRecordを渡す更新メソッドが問題になったのか
ALの Record 変数は、単に「現在のデータベース上の値」を表すだけではありません。呼び出し元でフィールドを書き換えたあと、まだ Modify していない値を抱えていることがあります。その状態で var record を受け取る更新APIが Modify(true) を行うと、API側が意図したフィールド以外も保存対象になり得ます。
PRでは例として、SetStatusToSent のようなメソッドを呼んだとき、本来はステータスだけを更新したいにもかかわらず、渡された record 側に変更済みフィールドがあると、それらも含めて modify しようとする問題が説明されています。(GitHub)
たとえば、次のようなコードがあるとします。
AgentTaskMessage.Get(TaskID, MessageID);
// 何らかの処理で、意図せず別フィールドを変更した状態
AgentTaskMessage.From := 'temporary-test-value';
// 本来は本文だけを更新したい
AgentMessage.UpdateText(AgentTaskMessage, NewMessageText);
このような呼び出しでは、UpdateText の目的は本文更新であっても、呼び出し元の AgentTaskMessage に残っている別フィールドの変更が混ざるリスクがあります。Record.Modify(true) はテーブル上のレコードを変更し、引数が true の場合は OnModify トリガーも実行するため、想定外の書き戻しはデータ整合性や後続処理にも影響します。(Microsoft Learn)
影響を受けやすいコード
今回の Microsoft developer platform documentation update で特に確認すべきなのは、Business Central の AL 拡張で agent task のライフサイクルやメッセージ更新を直接扱っているコードです。
次のようなコードは優先的に見直してください。
| 影響度 | 該当するコード | 確認すべき理由 |
|---|---|---|
| 高 | Agent Message の UpdateText(var AgentTaskMessage, ...) を使っている | 本文以外のフィールドを巻き込む可能性がある |
| 高 | Agent Message の SetStatusToSent(var AgentTaskMessage) を使っている | ステータス更新時に別フィールドまで保存されるリスクがある |
| 高 | Agent Task の SetStatusToReady(var AgentTask)、StopTask(var AgentTask, ...)、RestartTask(var AgentTask, ...) を使っている | タスク状態の更新時に、呼び出し元Recordの状態が影響する可能性がある |
| 中 | CanSetStatusToReady(var AgentTask)、IsTaskRunning(var AgentTask) などの判定系を使っている | Recordが再取得されない場合、古い状態を見て判断する可能性がある |
| 低 | Agent Task Builder でタスク作成だけをしている | 直接の更新APIを使っていなければ影響は限定的 |
PRのコミット説明では、既存の呼び出し箇所として AgentTaskMessageCard、SOAEmailMessage、SOASendReplies、AgentTaskManagementTest などが record-based overload から PK-based overload へ置き換えられたことが示されています。自社拡張でも、似た画面処理、メール処理、テストコードがないか確認すると効率的です。(GitHub)
変更対象の主なメソッド
Agent Message では、TaskID と MessageID を受け取る GetText、UpdateText、IsEditable、SetStatusToSent が追加・利用される流れです。一方で、Recordを渡す既存の UpdateText と SetStatusToSent には、今後 TaskID と MessageID を受け取るオーバーロードを使うよう促すコメントが入っています。(GitHub)
Agent Task では、AgentTaskID を受け取る SetStatusToReady、CanSetStatusToReady、StopTask、RestartTask、IsTaskRunning、IsTaskCompleted、IsTaskStopped が確認できます。Recordを渡す一部メソッドには、今後 AgentTaskID を受け取るオーバーロードを使うよう促すコメントが入っています。(GitHub)
| codeunit | 優先して使いたい呼び出し | 見直すべき呼び出し | 実務上のポイント |
|---|---|---|---|
Agent Message | UpdateText(TaskID, MessageID, NewMessageText) | UpdateText(var AgentTaskMessage, NewMessageText) | メッセージ本文だけを更新したい場合は、メッセージの主キーを渡す |
Agent Message | SetStatusToSent(TaskID, MessageID) | SetStatusToSent(var AgentTaskMessage) | ステータスだけを送信済みにしたい場合は、Record全体を渡さない |
Agent Message | GetText(TaskID, MessageID)、IsEditable(TaskID, MessageID) | GetText(var AgentTaskMessage)、IsEditable(var AgentTaskMessage) | Record版は再取得されない前提で扱う |
Agent Task | SetStatusToReady(AgentTaskID) | SetStatusToReady(var AgentTask) | タスク再実行や再処理の前にIDベースへ置き換える |
Agent Task | StopTask(AgentTaskID, UserConfirm) | StopTask(var AgentTask, UserConfirm) | 停止理由や確認ダイアログの挙動を維持しつつIDを渡す |
Agent Task | RestartTask(AgentTaskID, UserConfirm) | RestartTask(var AgentTask, UserConfirm) | 画面上のRecordをそのまま渡す処理は特に確認する |
Agent Task | IsTaskRunning(AgentTaskID) など | IsTaskRunning(var AgentTask) など | 判定前に最新状態が必要ならID版か再取得を使う |
移行の基本方針は「Recordではなく主キーを渡す」
移行時の考え方はシンプルです。更新メソッドには、変更したいレコードそのものではなく、そのレコードを特定する主キーを渡すようにします。
Agent Messageの置き換え例
Recordを渡している場合は、メッセージの Task ID と ID を渡す形に変更します。
// 旧: Recordを渡す
AgentMessage.UpdateText(AgentTaskMessage, NewMessageText);
AgentMessage.SetStatusToSent(AgentTaskMessage);
// 新: 主キーを渡す
AgentMessage.UpdateText(
AgentTaskMessage."Task ID",
AgentTaskMessage.ID,
NewMessageText
);
AgentMessage.SetStatusToSent(
AgentTaskMessage."Task ID",
AgentTaskMessage.ID
);
PR内の実装では、UpdateText(TaskID, MessageID, NewMessageText) が Task ID と ID をセットし、その後の処理で対象レコードを Get してから Content を更新しています。ステータス更新でも、内部の UpdateStatus が対象メッセージを主キーで取得し、Status だけを変更する構造になっています。(GitHub)
Agent Taskの置き換え例
タスク操作も同様に、Recordではなく AgentTaskID を渡す形にします。
// 旧: Recordを渡す
AgentTaskCU.StopTask(AgentTask, true);
AgentTaskCU.RestartTask(AgentTask, true);
if AgentTaskCU.CanSetStatusToReady(AgentTask) then
AgentTaskCU.SetStatusToReady(AgentTask);
// 新: AgentTaskIDを渡す
AgentTaskCU.StopTask(AgentTaskID, true);
AgentTaskCU.RestartTask(AgentTaskID, true);
if AgentTaskCU.CanSetStatusToReady(AgentTaskID) then
AgentTaskCU.SetStatusToReady(AgentTaskID);
ここでの AgentTaskID は、対象タスクを一意に特定する主キーです。既存処理で Record "Agent Task" を取得している場合でも、更新APIへ渡すのは Record そのものではなく、そこから取り出したIDに寄せるのが安全です。
Record版の判定メソッドは「最新値を見ている」と思い込まない
今回の変更で見落としやすいのは、更新メソッドだけでなく、判定メソッドにもIDベースのオーバーロードが追加されている点です。
Agent Message の GetText(var AgentTaskMessage) や IsEditable(var AgentTaskMessage) には、Recordが再取得されないため、呼び出し元が最新状態を保証する必要があるという説明が追加されています。Agent Task の CanSetStatusToReady(var AgentTask)、IsTaskRunning(var AgentTask)、IsTaskCompleted(var AgentTask)、IsTaskStopped(var AgentTask) でも同様に、Recordが再取得されない前提が明記されています。(GitHub)
そのため、次のような場面ではIDベースの呼び出しを選ぶほうが安全です。
- 画面を開いてから時間が経っている
- 別セッションやジョブキューが同じ agent task を更新する
- メール連携やイベント購読で、非同期に状態が変わる
- テストで Record を使い回している
- 「停止済みなら再開」「完了済みなら次の処理」など、状態判定が後続処理を左右する
判定系はデータを書き換えないため軽く見られがちですが、古いRecordを見て処理を分岐すると、結果的に二重実行、再開漏れ、送信済みメッセージの再編集などにつながります。
設定・バージョン確認で見るべきポイント
今回の Microsoft developer platform documentation update は、PR時点では最終リリース済み仕様ではなく、Business Central のプレビュー領域に関係します。Microsoft Learn でも agent task のプログラム管理はプレビュー機能として説明されており、本番利用を前提にしない注意書きがあります。(Microsoft Learn)
移行前に、次の観点で確認してください。
| 確認項目 | 確認内容 | 判断基準 |
|---|---|---|
| 利用バージョン | 新しいオーバーロードが自分のターゲット環境で参照できるか | コンパイル時にメソッド解決できるか確認する |
| PRの反映状況 | #7618 / #7979 がマージ済みか、差分が変更されていないか | GitHubの最終差分とリリースノートを確認する |
| プレビュー機能 | Agent関連機能を利用する環境か | 本番環境で使う場合はプレビュー制約を確認する |
| obsolete警告 | Record版メソッドに警告が出るか | 警告が出たらIDベースへ置換する |
| テスト環境 | agent task の状態遷移を再現できるか | Stop / Restart / Ready / Sent のテストを用意する |
ALでは、メソッドやシンボルを削除する前に [Obsolete] 属性で代替手段を示し、互換性を保ちながら移行期間を作る考え方が説明されています。Microsoftのガイドラインでは、ObsoleteTag のメジャーバージョンに対応する CLEAN<Version> 形式のプリプロセッサシンボルを使う例も示されています。(Microsoft Learn)
テストで確認すべき失敗パターン
今回の修正は、通常の「正しく値を渡したら更新できるか」だけでは十分に検証できません。重要なのは、対象外のフィールドが保存されないことを確認することです。
PRでも、UpdateText のテストとして、渡されたRecord変数の From フィールドを事前に変更して dirty な状態にし、その後 UpdateText を呼んでも、From はデータベースへ保存されず Content だけが更新されることを検証するテストが追加されています。(GitHub)
自社拡張で追加するなら、次の観点が実務的です。
| テスト観点 | 具体例 | 合格条件 |
|---|---|---|
| メッセージ本文更新 | From や Status を未保存変更したまま UpdateText を呼ぶ | Content だけが変わる |
| メッセージ送信済み更新 | 本文や送信者を変更したRecordで SetStatusToSent を呼ぶ | Status だけが送信済みになる |
| タスク停止 | 画面上で保持している古い Agent Task Record から停止する | 対象タスクだけが停止し、他フィールドが巻き込まれない |
| タスク再開 | 完了・停止状態のタスクを RestartTask / SetStatusToReady で扱う | 最新状態を見て正しく遷移する |
| 並行更新 | 別セッションで同じタスクを更新したあと判定系を呼ぶ | stale record に依存しない |
特に、ページアクションやメール連携の処理では、ユーザー操作・ジョブキュー・エージェント処理が同じタスクやメッセージに触れる可能性があります。単体テストだけでなく、画面操作を含むシナリオテストでも確認しておくと安全です。
実務での移行チェックリスト
まずはコード全体を検索し、Record版の呼び出しを洗い出します。VS Code や grep で、次のキーワードを検索してください。
UpdateText(
SetStatusToSent(
SetStatusToReady(
CanSetStatusToReady(
StopTask(
RestartTask(
IsTaskRunning(
IsTaskCompleted(
IsTaskStopped(
検索結果を見つけたら、次の順で対応すると効率的です。
| 手順 | 作業 | ポイント |
|---|---|---|
| 1 | 呼び出し先 codeunit を確認する | Agent Message / Agent Task の呼び出しかを見る |
| 2 | 第一引数の型を確認する | Recordを渡していれば移行候補 |
| 3 | 主キーを取得できる場所を確認する | TaskID、MessageID、AgentTaskID を変数化する |
| 4 | IDベースのオーバーロードへ変更する | 既存の UserConfirm などの引数は維持する |
| 5 | 更新後にRecordが必要なら再取得する | 呼び出し後のRecord内容を信用しすぎない |
| 6 | dirty record テストを追加する | 対象外フィールドが保存されないことを確認する |
| 7 | obsolete警告を確認する | 将来の削除に備えて警告を残さない |
注意したいのは、「Recordを渡すAPIがまだ動くなら放置してよい」と考えないことです。今回のPRでは互換性のために既存メソッドが残っているように見える箇所がありますが、コードコメント上は今後の obsolete 化が示されています。後から一気に修正すると、画面処理・テストコード・イベント購読処理を同時に直すことになり、影響調査が難しくなります。(GitHub)
対応優先度の判断基準
すべてのコードを同じ優先度で直す必要はありません。まずは、データを書き換える処理から対応してください。
| 優先度 | 対象 | 理由 |
|---|---|---|
| 最優先 | UpdateText、SetStatusToSent、SetStatusToReady、StopTask、RestartTask | データベース更新を伴い、対象外フィールドの巻き込みリスクがある |
| 高 | 画面アクション、ジョブキュー、メール処理、イベント購読 | 複数セッションや非同期処理でRecordが古くなりやすい |
| 中 | CanSetStatusToReady、IsTaskRunning などの判定系 | 更新はしないが、古い状態で分岐するリスクがある |
| 低 | タスク作成のみ、または Agent Task Builder 中心の処理 | 直接の更新APIを使っていなければ影響は限定的 |
判断に迷う場合は、「そのRecordに、API呼び出し前の一時的な変更が残っている可能性があるか」で考えると分かりやすいです。少しでも可能性があるなら、Recordを渡すより主キーを渡す設計に変えるほうが安全です。
まとめ:まずRecord版APIの棚卸しから始める
今回の Microsoft developer platform documentation update の本質は、Agent Message と Agent Task の更新処理を Record全体の変更ではなく、対象値だけの変更に寄せることです。AL拡張で agent task を操作している場合は、Recordを渡す更新メソッドを使っていないかを最初に確認してください。
次に取るべき行動は明確です。まず UpdateText、SetStatusToSent、SetStatusToReady、StopTask、RestartTask を検索し、Recordを渡している箇所を主キーベースの呼び出しへ置き換えます。その後、判定系メソッドで古いRecordを見ていないかを確認し、dirty record を使ったテストを追加します。
PRは Version 29.0 マイルストーンに紐づく変更として扱われていますが、2026年5月6日時点では関連PRの状態が完全な安定版仕様を示すものとは限りません。実装時は、利用中のBusiness Central環境で新しいオーバーロードが利用できるか、obsolete警告が出るか、最終マージ差分がどうなっているかを確認してから進めてください。(GitHub)

コメント