Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
permissionset 50100 "SALES REVIEW AGENT"
{
Assignable = true;
Permissions =
tabledata "Sales Header" = RIM,
tabledata Customer = R,
tabledata User = RIMD,
tabledata "Access Control" = RIMD,
page "Sales Order" = X,
page "User Card" = X;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
permissionset 50100 "SALES REVIEW AGENT"
{
Assignable = true;
Permissions =
tabledata "Sales Header" = RIM,
tabledata Customer = R,
page "Sales Order" = X;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
bc-version: [27..]
domain: agents
keywords: [permissions, assigner, intersection, user-card, least-privilege]
technologies: [al]
countries: [w1]
application-area: [all]
---

# Agent permissions intersect the assigner's; agents cannot configure users

## Description

An agent is a user, but it cannot configure users or other agents, and it cannot open sensitive pages such as user cards or permission-set assignment. Effective rights are the intersection of the assigning user's permissions and the agent's permission sets. Granting the agent a wide set does not bypass the assigner's limits, and a wide assigner still cannot give the agent user-admin powers the platform forbids.

## Best Practice

Document that intersection. Give the agent only the table and page rights its tasks need. Do not add user-setup or permission-assignment pages to the agent profile or permission sets; those operations will fail by design.

See sample: `agent-permissions-intersect-with-assigner.good.al`.

## Anti Pattern

Permission sets or profiles that include User card, Permission Set Assignment, or agent-admin pages, or comments that the agent runs as SUPER regardless of who assigned it. Detection signal: default access controls or profile including user-administration objects.

See sample: `agent-permissions-intersect-with-assigner.bad.al`.

## See also

`get-default-access-controls-least-privilege.md` covers the permission sets assigned when an agent instance is created.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
codeunit 50100 "Sales Review Agent Factory"
{
procedure GetDefaultProfile(var TempAllProfile: Record "All Profile" temporary)
begin
TempAllProfile."Profile ID" := 'BUSINESS MANAGER';
TempAllProfile.Insert();
end;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
profile "SALES REVIEW AGENT"
{
Caption = 'Sales Review Agent';
Description = 'Restricted UI for the Sales Review Agent.';
RoleCenter = "Order Processor Role Center";
Customizations = "Sales Review Agent Sales Ord.";
}

pagecustomization "Sales Review Agent Sales Ord." customizes "Sales Order"
{
layout
{
modify("Payment Terms Code")
{
Visible = false;
}
}

actions
{
modify(Post)
{
Visible = false;
}
}
}
30 changes: 30 additions & 0 deletions community/knowledge/agents/agent-profile-narrows-visible-ui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
bc-version: [27..]
domain: agents
keywords: [profile, page-customization, hidden-actions, tooltip, role-center]
technologies: [al]
countries: [w1]
application-area: [all]
---

# Give the agent a dedicated profile that hides unrelated UI

## Description

The agent only sees what its profile shows. Extra actions, views, and Role Center tiles become extra tools and extra tokens. Accuracy and cost both get worse as the UI widens. A human Order Processor profile is usually far too broad. Tooltips on the remaining actions are part of the tool description.

## Best Practice

Ship an agent-specific profile and page customizations: hide unrelated actions, keep descriptive tooltips, add Role Center links to the few pages the agent should open. Prefer fewer navigation hops.

See sample: `agent-profile-narrows-visible-ui.good.al`.

## Anti Pattern

Assigning `BUSINESS MANAGER` or `ORDER PROCESSOR` as `GetDefaultProfile` so the agent can do anything. Detection signal: default profile equal to a full-user role with no agent page customizations.

See sample: `agent-profile-narrows-visible-ui.bad.al`.

## See also

`get-default-profile-lives-in-the-app.md` covers packaging and assigning the profile that this rule narrows.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
page 50100 "Sales Review Agent Setup"
{
PageType = Card;
Caption = 'Set up Sales Review Agent';
SourceTable = "Sales Review Agent Setup";

layout
{
area(Content)
{
field(ReviewThreshold; Rec."Review Threshold")
{
ApplicationArea = All;
Caption = 'Review Threshold';
ToolTip = 'Specifies the threshold used when the agent requests a review.';
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
page 50100 "Sales Review Agent Setup"
{
PageType = ConfigurationDialog;
Caption = 'Set up Sales Review Agent';
SourceTable = "Sales Review Agent Setup";
SourceTableTemporary = true;
Extensible = false;

layout
{
area(Content)
{
part(AgentSetupPart; "Agent Setup Part")
{
ApplicationArea = All;
UpdatePropagation = Both;
}
group(AdditionalConfiguration)
{
Caption = 'Additional Configuration';
field(ReviewThreshold; Rec."Review Threshold")
{
ApplicationArea = All;
Caption = 'Review Threshold';
ToolTip = 'Specifies the threshold used when the agent requests a review.';
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
bc-version: [27..]
domain: agents
keywords: [configurationdialog, agent-setup-part, setup-page, pagetype, system-actions]
technologies: [al]
countries: [w1]
application-area: [all]
---

# Agent setup pages use ConfigurationDialog and the Agent Setup Part

## Description

Instance setup is not a Card or StandardDialog. The toolkit expects `PageType = ConfigurationDialog` so OK and Cancel are system actions, plus the built-in `Agent Setup Part` for name, display name, state, and access. A Card with custom fields only drops those shared controls and the AI-use notices the part carries.

## Best Practice

Declare `PageType = ConfigurationDialog`, host `part(...; "Agent Setup Part")`, and put agent-specific fields in another group. Keep system OK/Cancel. Use a temporary source record and defer persistence until Update, as described in `agent-setup-source-table-is-temporary.md`.
The Extensible property of the page must be set to false.

See sample: `agent-setup-page-is-configuration-dialog.good.al`.

## Anti Pattern

A Card or StandardDialog setup page with no `Agent Setup Part`. Detection signal: setup page ID from `IAgentFactory` / `IAgentMetadata` whose page is not `ConfigurationDialog` or has no `Agent Setup Part`.

See sample: `agent-setup-page-is-configuration-dialog.bad.al`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
page 50100 "Sales Review Agent Setup"
{
PageType = ConfigurationDialog;
SourceTable = "Sales Review Agent Setup";

layout
{
area(Content)
{
field(ReviewThreshold; Rec."Review Threshold")
{
ApplicationArea = All;
Caption = 'Review Threshold';
ToolTip = 'Specifies the threshold used when the agent requests a review.';

trigger OnValidate()
begin
Rec.Modify(true);
end;
}
}
}

trigger OnOpenPage()
begin
if Rec.IsEmpty() then
Rec.Insert(true);
end;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
page 50100 "Sales Review Agent Setup"
{
PageType = ConfigurationDialog;
SourceTable = "Sales Review Agent Setup";
SourceTableTemporary = true;
Extensible = false;

layout
{
area(Content)
{
part(AgentSetupPart; "Agent Setup Part")
{
ApplicationArea = All;
UpdatePropagation = Both;
}
group(AdditionalConfiguration)
{
Caption = 'Additional Configuration';
field(ReviewThreshold; Rec."Review Threshold")
{
ApplicationArea = All;
Caption = 'Review Threshold';
ToolTip = 'Specifies the threshold used when the agent requests a review.';
}
}
}
}

trigger OnOpenPage()
var
SalesReviewAgentSetup: Record "Sales Review Agent Setup";
begin
if IsNullGuid(Rec."User Security ID") then
exit;
if SalesReviewAgentSetup.Get(Rec."User Security ID") then
Rec := SalesReviewAgentSetup;
end;

trigger OnQueryClosePage(CloseAction: Action): Boolean
var
AgentSetup: Codeunit "Agent Setup";
AgentSetupBuffer: Record "Agent Setup Buffer";
begin
if CloseAction = CloseAction::Cancel then
exit(true);
CurrPage.AgentSetupPart.Page.GetAgentSetupBuffer(AgentSetupBuffer);
if AgentSetup.GetChangesMade(AgentSetupBuffer) then
Rec."User Security ID" := AgentSetup.SaveChanges(AgentSetupBuffer);
if IsNullGuid(Rec."User Security ID") then
exit(true);
SaveCustomProperties();
exit(true);
end;

local procedure SaveCustomProperties()
var
SalesReviewAgentSetup: Record "Sales Review Agent Setup";
begin
if not SalesReviewAgentSetup.Get(Rec."User Security ID") then begin
SalesReviewAgentSetup.Init();
SalesReviewAgentSetup."User Security ID" := Rec."User Security ID";
SalesReviewAgentSetup.Insert(true);
end;
SalesReviewAgentSetup."Review Threshold" := Rec."Review Threshold";
SalesReviewAgentSetup.Modify(true);
end;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
bc-version: [27..]
domain: agents
keywords: [sourcetabletemporary, configurationdialog, savechanges, cancel, draft]
technologies: [al]
countries: [w1]
application-area: [all]
---

# Keep the agent setup page source temporary until Update

## Description

ConfigurationDialog setup is a draft: the user can Cancel without writing. That only works if `SourceTableTemporary = true` and custom fields stay in memory until Update. Writing the real table in OnValidate or OnOpenPage commits a partial agent when the dialog errors or is cancelled.

## Best Practice

Mark the page `SourceTableTemporary = true`. Copy into the temp record on open. Persist the Agent Setup buffer and custom fields only from the close path when the action is not Cancel, using `Agent Setup.GetChangesMade` / `SaveChanges`.

See sample: `agent-setup-source-table-is-temporary.good.al`.

## Anti Pattern

A non-temporary source table, or `Insert`/`Modify` on the persisted setup row from field OnValidate. Detection signal: agent `ConfigurationDialog` without `SourceTableTemporary = true`, or database writes before Update.

See sample: `agent-setup-source-table-is-temporary.bad.al`.

## See also

`agent-setup-page-is-configuration-dialog.md` defines the setup page shape that uses this draft lifecycle.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
table 50100 "Sales Review Agent Setup"
{
DataClassification = CustomerContent;

fields
{
field(1; "Primary Key"; Code[10])
{
Caption = 'Primary Key';
}
field(10; "Review Threshold"; Decimal)
{
Caption = 'Review Threshold';
}
}

keys
{
key(PK; "Primary Key")
{
Clustered = true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
table 50100 "Sales Review Agent Setup"
{
DataClassification = CustomerContent;

fields
{
field(1; "User Security ID"; Guid)
{
Caption = 'User Security ID';
DataClassification = EndUserPseudonymousIdentifiers;
}
field(10; "Review Threshold"; Decimal)
{
Caption = 'Review Threshold';
}
}

keys
{
key(PK; "User Security ID")
{
Clustered = true;
}
}
}
Loading
Loading