diff --git a/src/Apps/W1/ExpenseAgent/app/src/Setup/Codeunits/EAAgentArchiving.Codeunit.al b/src/Apps/W1/ExpenseAgent/app/src/Setup/Codeunits/EAAgentArchiving.Codeunit.al
new file mode 100644
index 00000000000..25d818bf06e
--- /dev/null
+++ b/src/Apps/W1/ExpenseAgent/app/src/Setup/Codeunits/EAAgentArchiving.Codeunit.al
@@ -0,0 +1,20 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace Microsoft.ExpenseAgent;
+
+using System.Agents;
+
+codeunit 7104 "EA Agent Archiving" implements IAgentArchiving
+{
+ Access = Internal;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ procedure IsArchivingSupported(): Boolean
+ begin
+ exit(false);
+ end;
+}
diff --git a/src/Apps/W1/ExpenseAgent/app/src/Setup/EnumExtensions/EAAgentMetadata.EnumExt.al b/src/Apps/W1/ExpenseAgent/app/src/Setup/EnumExtensions/EAAgentMetadata.EnumExt.al
index cdb7dfefee6..061d575a942 100644
--- a/src/Apps/W1/ExpenseAgent/app/src/Setup/EnumExtensions/EAAgentMetadata.EnumExt.al
+++ b/src/Apps/W1/ExpenseAgent/app/src/Setup/EnumExtensions/EAAgentMetadata.EnumExt.al
@@ -13,6 +13,6 @@ enumextension 6998 "EA Agent Metadata" extends "Agent Metadata Provider"
value(6998; "Expense Agent")
{
Caption = 'Expense Agent', Locked = true;
- Implementation = IAgentFactory = "EA Metadata Provider", IAgentMetadata = "EA Metadata Provider", IAgentTaskExecution = "EA Agent Task Execution";
+ Implementation = IAgentFactory = "EA Metadata Provider", IAgentMetadata = "EA Metadata Provider", IAgentTaskExecution = "EA Agent Task Execution", IAgentArchiving = "EA Agent Archiving";
}
}
diff --git a/src/Apps/W1/PayablesAgent/app/Integration/PAAgentArchiving.Codeunit.al b/src/Apps/W1/PayablesAgent/app/Integration/PAAgentArchiving.Codeunit.al
new file mode 100644
index 00000000000..36fe3bef3d5
--- /dev/null
+++ b/src/Apps/W1/PayablesAgent/app/Integration/PAAgentArchiving.Codeunit.al
@@ -0,0 +1,20 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace Microsoft.Agent.PayablesAgent;
+
+using System.Agents;
+
+codeunit 3319 "PA Agent Archiving" implements IAgentArchiving
+{
+ Access = Internal;
+ InherentEntitlements = X;
+ InherentPermissions = X;
+
+ procedure IsArchivingSupported(): Boolean
+ begin
+ exit(false);
+ end;
+}
diff --git a/src/Apps/W1/PayablesAgent/app/PAAgentMetadata.EnumExt.al b/src/Apps/W1/PayablesAgent/app/PAAgentMetadata.EnumExt.al
index 3a6b1496e0c..0ea2395884e 100644
--- a/src/Apps/W1/PayablesAgent/app/PAAgentMetadata.EnumExt.al
+++ b/src/Apps/W1/PayablesAgent/app/PAAgentMetadata.EnumExt.al
@@ -13,6 +13,6 @@ enumextension 3304 "PA Agent Metadata" extends "Agent Metadata Provider"
value(3303; "Payables Agent")
{
Caption = 'Payables Agent', Locked = true;
- Implementation = IAgentFactory = "Payables Agent", IAgentMetadata = "Payables Agent", IAgentTaskExecution = "PA Agent Task Execution";
+ Implementation = IAgentFactory = "Payables Agent", IAgentMetadata = "Payables Agent", IAgentTaskExecution = "PA Agent Task Execution", IAgentArchiving = "PA Agent Archiving";
}
}
diff --git a/src/System Application/App/Agent/Setup/Agent.Codeunit.al b/src/System Application/App/Agent/Setup/Agent.Codeunit.al
index 4f882e0b9e9..b802c4d826b 100644
--- a/src/System Application/App/Agent/Setup/Agent.Codeunit.al
+++ b/src/System Application/App/Agent/Setup/Agent.Codeunit.al
@@ -61,6 +61,7 @@ codeunit 4321 Agent
/// Archives the agent. Archiving removes the agent from active use and cannot be undone. The agent must be inactive (deactivated) before it can be archived.
///
/// The user security ID of the agent.
+ /// An error is raised if the agent's type does not support archiving. Call IsArchivingSupported to check before archiving.
procedure Archive(AgentUserSecurityID: Guid)
var
AgentImpl: Codeunit "Agent Impl.";
@@ -69,6 +70,19 @@ codeunit 4321 Agent
AgentImpl.Archive(AgentUserSecurityID);
end;
+ ///
+ /// Checks if the agent type supports archiving.
+ ///
+ /// The user security ID of the agent.
+ /// True if the agent type supports archiving; otherwise false.
+ procedure IsArchivingSupported(AgentUserSecurityID: Guid): Boolean
+ var
+ AgentImpl: Codeunit "Agent Impl.";
+ begin
+ FeatureAccessManagement.AgentManagementAllowed(true);
+ exit(AgentImpl.IsArchivingSupported(AgentUserSecurityID));
+ end;
+
///
/// Checks if the agent is archived.
///
diff --git a/src/System Application/App/Agent/Setup/AgentCard.Page.al b/src/System Application/App/Agent/Setup/AgentCard.Page.al
index c4d8987ec25..ec0257e8a96 100644
--- a/src/System Application/App/Agent/Setup/AgentCard.Page.al
+++ b/src/System Application/App/Agent/Setup/AgentCard.Page.al
@@ -151,6 +151,9 @@ page 4315 "Agent Card"
Agent: Codeunit Agent;
ArchiveConfirmation: Page "Agent Archive Confirmation";
begin
+ if not Agent.IsArchivingSupported(Rec."User Security ID") then
+ Error(ArchivingNotSupportedErr, Rec."Agent Metadata Provider");
+
if Rec.State <> Rec.State::Disabled then
Error(DeactivateBeforeArchivingErr);
@@ -324,6 +327,7 @@ page 4315 "Agent Card"
YouCannotEnableAgentWithoutUsingConfigurationPageErr: Label 'You can''t activate the agent from this page. Use the action to configure and activate the agent.';
YouDoNotHavePermissionToModifyThisAgentErr: Label 'You do not have permission to modify this agent. Contact your system administrator to update your permissions or to mark you as one of the administrators for the agent.';
DeactivateBeforeArchivingErr: Label 'Deactivate the agent before archiving it.';
+ ArchivingNotSupportedErr: Label 'Archiving agents of type ''%1'' is not supported.', Comment = '%1 = the type of the agent.';
AgentArchivedMsg: Label 'The agent has been archived.';
AgentArchivedNotificationMsg: Label 'This agent is archived and can no longer be modified. Its tasks and logs remain available for auditing.';
-}
\ No newline at end of file
+}
diff --git a/src/System Application/App/Agent/Setup/AgentImpl.Codeunit.al b/src/System Application/App/Agent/Setup/AgentImpl.Codeunit.al
index 8b14bb3c40a..3c60ce14129 100644
--- a/src/System Application/App/Agent/Setup/AgentImpl.Codeunit.al
+++ b/src/System Application/App/Agent/Setup/AgentImpl.Codeunit.al
@@ -67,6 +67,9 @@ codeunit 4301 "Agent Impl."
if Agent.Substate = Agent.Substate::Archived then
exit; // Archiving is terminal; idempotent no-op avoids the platform "archived agent cannot be modified" error on re-archive.
+ if not IsArchivingSupported(Agent) then
+ Error(ArchivingNotSupportedErr, Agent."Agent Metadata Provider");
+
if Agent.State <> Agent.State::Disabled then
Error(DeactivateBeforeArchivingErr);
@@ -74,6 +77,27 @@ codeunit 4301 "Agent Impl."
Agent.Modify(true);
end;
+ procedure IsArchivingSupported(AgentUserSecurityID: Guid): Boolean
+ var
+ Agent: Record Agent;
+ begin
+ GetAgent(Agent, AgentUserSecurityID);
+
+ exit(IsArchivingSupported(Agent));
+ end;
+
+ local procedure IsArchivingSupported(Agent: Record Agent): Boolean
+ var
+ AgentArchiving: Interface IAgentArchiving;
+ begin
+ if IsNullGuid(Agent."User Security ID") then
+ exit(false);
+
+ AgentArchiving := Agent."Agent Metadata Provider";
+
+ exit(AgentArchiving.IsArchivingSupported());
+ end;
+
procedure IsArchived(AgentUserSecurityID: Guid): Boolean
var
Agent: Record Agent;
@@ -644,6 +668,7 @@ codeunit 4301 "Agent Impl."
AgentDoesNotExistErr: Label 'Agent does not exist.';
AgentArchivedCannotBeModifiedErr: Label 'The agent is archived and cannot be modified.';
DeactivateBeforeArchivingErr: Label 'Deactivate the agent before archiving it.';
+ ArchivingNotSupportedErr: Label 'Archiving agents of type ''%1'' is not supported.', Comment = '%1 = the type of the agent.';
AutoLbl: Label 'Auto';
NoActiveAgentsErr: Label 'There are no active agents setup on the system.';
NoAgentsAvailableNotificationLbl: Label 'Business Central agents are currently not available in your country.';
diff --git a/src/System Application/App/Agent/Setup/AgentList.Page.al b/src/System Application/App/Agent/Setup/AgentList.Page.al
index 4237cb0de76..0f825e1a801 100644
--- a/src/System Application/App/Agent/Setup/AgentList.Page.al
+++ b/src/System Application/App/Agent/Setup/AgentList.Page.al
@@ -99,6 +99,9 @@ page 4316 "Agent List"
if Rec.IsEmpty() then
Error(NoAgentSetupErr);
+ if not Agent.IsArchivingSupported(Rec."User Security ID") then
+ Error(ArchivingNotSupportedErr, Rec."Agent Metadata Provider");
+
if Agent.IsActive(Rec."User Security ID") then
Error(DeactivateBeforeArchivingErr);
@@ -302,4 +305,5 @@ page 4316 "Agent List"
AgentIsArchived: Boolean;
NoAgentSetupErr: Label 'No agents have been setup. You must set up an agent first.';
DeactivateBeforeArchivingErr: Label 'Deactivate the agent before archiving it.';
-}
\ No newline at end of file
+ ArchivingNotSupportedErr: Label 'Archiving agents of type ''%1'' is not supported.', Comment = '%1 = the type of the agent.';
+}
diff --git a/src/System Application/Test/Agent/src/SDK/AgentTest.Codeunit.al b/src/System Application/Test/Agent/src/SDK/AgentTest.Codeunit.al
index 08d454abd54..a28b01df367 100644
--- a/src/System Application/Test/Agent/src/SDK/AgentTest.Codeunit.al
+++ b/src/System Application/Test/Agent/src/SDK/AgentTest.Codeunit.al
@@ -23,6 +23,7 @@ codeunit 133961 "Agent Test"
LibraryVariableStorage: Codeunit "Library - Variable Storage";
DeactivateBeforeArchivingErr: Label 'Deactivate the agent before archiving it.', Locked = true;
AgentArchivedCannotBeModifiedErr: Label 'The agent is archived and cannot be modified.', Locked = true;
+ ArchivingNotSupportedErr: Label 'Archiving agents of type ''%1'' is not supported.', Locked = true;
local procedure Initialize()
begin
@@ -993,6 +994,7 @@ codeunit 133961 "Agent Test"
Agent.Deactivate(AgentId);
Assert.IsFalse(Agent.IsArchived(AgentId), 'Agent should not be archived initially');
+ Assert.IsTrue(Agent.IsArchivingSupported(AgentId), 'Archiving should be supported for a type that does not opt out');
// [WHEN] Archiving the agent
Agent.Archive(AgentId);
@@ -1005,6 +1007,37 @@ codeunit 133961 "Agent Test"
Assert.AreEqual(AgentRecord.Substate::Archived, AgentRecord.Substate, 'Agent substate should be Archived');
end;
+ [Test]
+ procedure ArchiveAgentOfUnsupportedTypeErrors()
+ var
+ AgentRecord: Record Agent;
+ TempAgentAccessControl: Record "Agent Access Control" temporary;
+ Any: Codeunit Any;
+ AgentId: Guid;
+ AgentUserName: Code[50];
+ begin
+ Initialize();
+
+ // [SCENARIO] Archiving an agent whose type opts out of archiving is rejected
+
+ // [GIVEN] An agent of a type that reports archiving as unsupported
+ AgentUserName := CopyStr(Any.AlphanumericText(MaxStrLen(AgentRecord."User Name")), 1, MaxStrLen(AgentRecord."User Name"));
+ AgentId := Agent.Create(
+ "Agent Metadata Provider"::"SDK Mock Agent No Archiving",
+ AgentUserName,
+ CopyStr(Any.AlphanumericText(80), 1, 80),
+ TempAgentAccessControl);
+
+ // [THEN] Archiving is reported as unsupported for that agent
+ Assert.IsFalse(Agent.IsArchivingSupported(AgentId), 'Archiving should not be supported for this agent type');
+
+ // [WHEN] Archiving the agent
+ // [THEN] An error is raised and the agent is not archived
+ asserterror Agent.Archive(AgentId);
+ Assert.ExpectedError(StrSubstNo(ArchivingNotSupportedErr, "Agent Metadata Provider"::"SDK Mock Agent No Archiving"));
+ Assert.IsFalse(Agent.IsArchived(AgentId), 'Agent should not be archived');
+ end;
+
[Test]
procedure ArchiveActiveAgentErrors()
var
diff --git a/src/System Application/Test/Agent/src/Setup/LibraryMockAgent.codeunit.al b/src/System Application/Test/Agent/src/Setup/LibraryMockAgent.codeunit.al
index 933e0f04381..a35be59b12f 100644
--- a/src/System Application/Test/Agent/src/Setup/LibraryMockAgent.codeunit.al
+++ b/src/System Application/Test/Agent/src/Setup/LibraryMockAgent.codeunit.al
@@ -49,7 +49,7 @@ codeunit 133954 "Library Mock Agent"
AgentRecord: Record Agent;
MockAgentSetup: Record "Mock Agent Setup";
begin
- AgentRecord.SetRange("Agent Metadata Provider", AgentRecord."Agent Metadata Provider"::"SDK Mock Agent");
+ AgentRecord.SetFilter("Agent Metadata Provider", '%1|%2', AgentRecord."Agent Metadata Provider"::"SDK Mock Agent", AgentRecord."Agent Metadata Provider"::"SDK Mock Agent No Archiving");
if AgentRecord.FindSet() then
repeat
if MockAgentSetup.Get(AgentRecord."User Security ID") then
diff --git a/src/System Application/Test/Agent/src/Setup/MockAgent/Integration/MockAgentMetaProv.Codeunit.al b/src/System Application/Test/Agent/src/Setup/MockAgent/Integration/MockAgentMetaProv.Codeunit.al
index fba61972d23..fd5c5b19fef 100644
--- a/src/System Application/Test/Agent/src/Setup/MockAgent/Integration/MockAgentMetaProv.Codeunit.al
+++ b/src/System Application/Test/Agent/src/Setup/MockAgent/Integration/MockAgentMetaProv.Codeunit.al
@@ -10,7 +10,7 @@ using System.AI;
using System.Reflection;
using System.Security.AccessControl;
-codeunit 133952 "Mock Agent Meta. Prov." implements IAgentMetadata, IAgentFactory
+codeunit 133952 "Mock Agent Meta. Prov." implements IAgentMetadata, IAgentFactory, IAgentArchiving
{
InherentEntitlements = X;
InherentPermissions = X;
@@ -21,6 +21,11 @@ codeunit 133952 "Mock Agent Meta. Prov." implements IAgentMetadata, IAgentFactor
MockAgentSetup: Codeunit "Mock Agent Setup";
MockAgentInitialLbl: Label 'MA', MaxLength = 4;
+ procedure IsArchivingSupported(): Boolean
+ begin
+ exit(false);
+ end;
+
procedure GetDefaultInitials(): Text[4]
begin
exit(MockAgentInitialLbl);
diff --git a/src/System Application/Test/Agent/src/Setup/MockAgent/Integration/MockAgentMetaProv.EnumExt.al b/src/System Application/Test/Agent/src/Setup/MockAgent/Integration/MockAgentMetaProv.EnumExt.al
index 4a309e58cf5..75888285417 100644
--- a/src/System Application/Test/Agent/src/Setup/MockAgent/Integration/MockAgentMetaProv.EnumExt.al
+++ b/src/System Application/Test/Agent/src/Setup/MockAgent/Integration/MockAgentMetaProv.EnumExt.al
@@ -13,4 +13,10 @@ enumextension 133952 "Mock Agent Meta. Prov." extends "Agent Metadata Provider"
Caption = 'SDK Mock Agent';
Implementation = IAgentFactory = "Mock Agent Meta. Prov.", IAgentMetadata = "Mock Agent Meta. Prov.";
}
+
+ value(133955; "SDK Mock Agent No Archiving")
+ {
+ Caption = 'SDK Mock Agent No Archiving';
+ Implementation = IAgentFactory = "Mock Agent Meta. Prov.", IAgentMetadata = "Mock Agent Meta. Prov.", IAgentArchiving = "Mock Agent Meta. Prov.";
+ }
}