Microsoft developer platform documentation update解説:Agent Message/Taskの変更点と移行確認

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 MessageUpdateText(TaskID, MessageID, NewMessageText)UpdateText(var AgentTaskMessage, NewMessageText)メッセージ本文だけを更新したい場合は、メッセージの主キーを渡す
Agent MessageSetStatusToSent(TaskID, MessageID)SetStatusToSent(var AgentTaskMessage)ステータスだけを送信済みにしたい場合は、Record全体を渡さない
Agent MessageGetText(TaskID, MessageID)、IsEditable(TaskID, MessageID)GetText(var AgentTaskMessage)、IsEditable(var AgentTaskMessage)Record版は再取得されない前提で扱う
Agent TaskSetStatusToReady(AgentTaskID)SetStatusToReady(var AgentTask)タスク再実行や再処理の前にIDベースへ置き換える
Agent TaskStopTask(AgentTaskID, UserConfirm)StopTask(var AgentTask, UserConfirm)停止理由や確認ダイアログの挙動を維持しつつIDを渡す
Agent TaskRestartTask(AgentTaskID, UserConfirm)RestartTask(var AgentTask, UserConfirm)画面上のRecordをそのまま渡す処理は特に確認する
Agent TaskIsTaskRunning(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 を変数化する
4IDベースのオーバーロードへ変更する既存の UserConfirm などの引数は維持する
5更新後にRecordが必要なら再取得する呼び出し後のRecord内容を信用しすぎない
6dirty record テストを追加する対象外フィールドが保存されないことを確認する
7obsolete警告を確認する将来の削除に備えて警告を残さない

注意したいのは、「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)

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次