Improve partner onboarding and documentation navigation (#174)
Some checks failed
Validate knowledge index / validate-index (push) Has been cancelled
Validate AL review fixtures / validate-review-fixtures (push) Has been cancelled
Validate frontmatter and structure / validate (push) Has been cancelled

Lead with a complete plugin quick start and add task-oriented usage, troubleshooting, customization, and contribution guides. Preserve the broader plugin framing, correct conflicting contract guidance, support Agents folder reviews, and align repository validation. Convert existing sample references to clickable links without changing knowledge rules.

Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Jesper Schulz-Wedde 2026-09-09 17:31:03 +02:00 • committed by GitHub
parent a21edfec46
commit 2b5550c346
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
276 changed files with 1287 additions and 756 deletions

View file

@ -17,13 +17,13 @@ An agent is a user, but it cannot configure users or other agents, and it cannot
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`.
See sample: [`agent-permissions-intersect-with-assigner.good.al`](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 sample: [`agent-permissions-intersect-with-assigner.bad.al`](agent-permissions-intersect-with-assigner.bad.al).
## See also

View file

@ -17,13 +17,13 @@ The agent only sees what its profile shows. Extra actions, views, and Role Cente
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`.
See sample: [`agent-profile-narrows-visible-ui.good.al`](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 sample: [`agent-profile-narrows-visible-ui.bad.al`](agent-profile-narrows-visible-ui.bad.al).
## See also

View file

@ -17,10 +17,10 @@ Instance setup is not a Card or StandardDialog. The toolkit expects `PageType =
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`. Following Microsoft's agent setup samples, set `Extensible = false`.
See sample: `agent-setup-page-is-configuration-dialog.good.al`.
See sample: [`agent-setup-page-is-configuration-dialog.good.al`](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`.
See sample: [`agent-setup-page-is-configuration-dialog.bad.al`](agent-setup-page-is-configuration-dialog.bad.al).

View file

@ -17,13 +17,13 @@ ConfigurationDialog setup is a draft: the user can Cancel without writing. That
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`.
See sample: [`agent-setup-source-table-is-temporary.good.al`](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 sample: [`agent-setup-source-table-is-temporary.bad.al`](agent-setup-source-table-is-temporary.bad.al).
## See also

View file

@ -17,10 +17,10 @@ Each agent instance is a user. Instance-specific setup is keyed by that user's `
Give the setup table a Guid field `User Security ID` as the clustered primary key. Other settings are attributes of that key. When the page opens, `Get` or insert by the Guid the Agent Setup part already holds.
See sample: `agent-setup-table-keyed-by-user-security-id.good.al`.
See sample: [`agent-setup-table-keyed-by-user-security-id.good.al`](agent-setup-table-keyed-by-user-security-id.good.al).
## Anti Pattern
A setup table keyed by Code, Integer, or with no Guid user key, then mapping one row to every instance. Detection signal: source table of the agent setup page whose primary key is not `User Security ID`.
See sample: `agent-setup-table-keyed-by-user-security-id.bad.al`.
See sample: [`agent-setup-table-keyed-by-user-security-id.bad.al`](agent-setup-table-keyed-by-user-security-id.bad.al).

View file

@ -17,10 +17,10 @@ application-area: [all]
Validate inbound payloads in analysis: Error when the task must not run; Warning when a human must confirm. For outbound messages, adjust text in this method rather than in a later subscriber. Do not rely on skip-review to bypass warnings.
See sample: `analyze-message-error-stops-warning-forces-review.good.al`.
See sample: [`analyze-message-error-stops-warning-forces-review.good.al`](analyze-message-error-stops-warning-forces-review.good.al).
## Anti Pattern
Ignoring analysis entirely, or emitting Warning while documenting that `SetRequiresReview(false)` means unattended run. Detection signal: empty `AnalyzeAgentTaskMessage` plus skip-review on external input.
See sample: `analyze-message-error-stops-warning-forces-review.bad.al`.
See sample: [`analyze-message-error-stops-warning-forces-review.bad.al`](analyze-message-error-stops-warning-forces-review.bad.al).

View file

@ -17,10 +17,10 @@ Page-filter tweaks, extra validation, and prompt dialogs for the agent should no
On `OnAfterInitialization`, exit unless `Agent Session.IsAgentSession`. Then `BindSubscription` a single-instance codeunit that holds the current task id. Keep those subscribers internal.
See sample: `bind-agent-subscribers-only-in-agent-session.good.al`.
See sample: [`bind-agent-subscribers-only-in-agent-session.good.al`](bind-agent-subscribers-only-in-agent-session.good.al).
## Anti Pattern
Event subscribers on `Sales Header` OnAfterInsert that always `Message` the agent, with no `IsAgentSession` guard. Detection signal: agent-only behaviour in a static subscriber that is not bind-gated.
See sample: `bind-agent-subscribers-only-in-agent-session.bad.al`.
See sample: [`bind-agent-subscribers-only-in-agent-session.bad.al`](bind-agent-subscribers-only-in-agent-session.bad.al).

View file

@ -17,10 +17,10 @@ For isolation, `Agent`, `Agent Task Builder`, and related toolkit codeunits erro
Expose a public codeunit in the agent app (`Access = Public`) whose procedures take `User Security ID` and forward to `Agent` / `Agent Task Builder`. Document that surface as the integration contract. Keep toolkit calls inside that app.
See sample: `cross-app-agent-calls-need-your-public-api.good.al`.
See sample: [`cross-app-agent-calls-need-your-public-api.good.al`](cross-app-agent-calls-need-your-public-api.good.al).
## Anti Pattern
From app B, calling `Agent.SetDisplayName` or `Agent.Create` with app A's metadata provider. Detection signal: toolkit agent APIs used with an `Agent Metadata Provider` value not declared in the same app.
See sample: `cross-app-agent-calls-need-your-public-api.bad.al`.
See sample: [`cross-app-agent-calls-need-your-public-api.bad.al`](cross-app-agent-calls-need-your-public-api.bad.al).

View file

@ -17,10 +17,10 @@ application-area: [all]
Create instances from a setup page, a wizard, or another UI-driven path after the user is in a client session. Apply instructions and `Activate` there. For existing companies after an upgrade, document that an admin must open setup; do not create from the upgrade codeunit.
See sample: `do-not-create-agents-in-install-upgrade-or-background.good.al`.
See sample: [`do-not-create-agents-in-install-upgrade-or-background.good.al`](do-not-create-agents-in-install-upgrade-or-background.good.al).
## Anti Pattern
`Agent.Create` inside `OnInstallAppPerCompany`, `OnUpgradePerCompany`, or a job-queue codeunit. The call fails at runtime even if it compiles. Detection signal: `Agent.Create` in `Subtype = Install`, `Subtype = Upgrade`, or a non-UI session.
See sample: `do-not-create-agents-in-install-upgrade-or-background.bad.al`.
See sample: [`do-not-create-agents-in-install-upgrade-or-background.bad.al`](do-not-create-agents-in-install-upgrade-or-background.bad.al).

View file

@ -17,13 +17,13 @@ application-area: [all]
Insert only the permission sets the agent needs. For an AL `permissionset` object, use `Scope::System` and the ID of the app that defines it. Recreate permission sets that exist only as user-defined configuration in Business Central as AL objects first. Prefer a dedicated permission set over a full-user role.
See sample: `get-default-access-controls-least-privilege.good.al`.
See sample: [`get-default-access-controls-least-privilege.good.al`](get-default-access-controls-least-privilege.good.al).
## Anti Pattern
Empty `GetDefaultAccessControls`, or inserting `SUPER` / `D365 BUS FULL ACCESS` because it made the demo work. Detection signal: Role ID on the default buffer that is a full-user role, or a set that is not in the app.
See sample: `get-default-access-controls-least-privilege.bad.al`.
See sample: [`get-default-access-controls-least-privilege.bad.al`](get-default-access-controls-least-privilege.bad.al).
## See also

View file

@ -17,13 +17,13 @@ application-area: [all]
Ship a `profile` object (and page customizations) in the app. In `GetDefaultProfile`, call `Agent.PopulateDefaultProfile` with that profile ID and `NavApp.GetCurrentModuleInfo`. Include UI-exported customizations as AL.
See sample: `get-default-profile-lives-in-the-app.good.al`.
See sample: [`get-default-profile-lives-in-the-app.good.al`](get-default-profile-lives-in-the-app.good.al).
## Anti Pattern
Setting `TempAllProfile."Profile ID"` to a client-only profile, or skipping `GetDefaultProfile`. Detection signal: factory default profile ID with no matching `profile` object in the app.
See sample: `get-default-profile-lives-in-the-app.bad.al`.
See sample: [`get-default-profile-lives-in-the-app.bad.al`](get-default-profile-lives-in-the-app.bad.al).
## See also

View file

@ -17,13 +17,13 @@ The runtime treats instructions as the agent's standing prompt. A one-line goal
Store a document that states responsibilities, then non-negotiable guidelines (when to request a review, when not to post), then numbered steps for each task. Keep that text in the resource you pass to `SetInstructions`.
See sample: `instruction-structure-is-role-rules-steps.good.al`.
See sample: [`instruction-structure-is-role-rules-steps.good.al`](instruction-structure-is-role-rules-steps.good.al).
## Anti Pattern
A single sentence such as Check customer credit for the sales order. Detection signal: instruction resource or `SetInstructions` payload with no responsibilities / guidelines / steps sections.
See sample: `instruction-structure-is-role-rules-steps.bad.al`.
See sample: [`instruction-structure-is-role-rules-steps.bad.al`](instruction-structure-is-role-rules-steps.bad.al).
## See also

View file

@ -17,13 +17,13 @@ Agent tools are the UI the profile exposes. Action names and tool ids change acr
Write steps as business outcomes (release the order, set the hold reason). Tell the agent to memorize identifiers it must reuse. Do not hard-code action captions or tool ids.
See sample: `instructions-describe-work-not-tool-ids.good.al`.
See sample: [`instructions-describe-work-not-tool-ids.good.al`](instructions-describe-work-not-tool-ids.good.al).
## Anti Pattern
Instructions that say invoke SalesOrder.Post_Promoted or use tool page-42-action-3. Detection signal: instruction text containing Promoted action names or tool identifiers.
See sample: `instructions-describe-work-not-tool-ids.bad.al`.
See sample: [`instructions-describe-work-not-tool-ids.bad.al`](instructions-describe-work-not-tool-ids.bad.al).
## See also

View file

@ -17,10 +17,10 @@ Static instructions stored as an app resource are copied onto an instance only w
In the upgrade codeunit, find existing instances of your metadata provider and call `SetInstructions` again with `NavApp.GetResourceAsText`. Guard with an upgrade tag so the rewrite runs once per version that changes the file.
See sample: `reapply-resource-instructions-on-upgrade.good.al`.
See sample: [`reapply-resource-instructions-on-upgrade.good.al`](reapply-resource-instructions-on-upgrade.good.al).
## Anti Pattern
Editing only the resource file, or calling `SetInstructions` solely from the first-time setup path. Detection signal: instruction resource in `resourceFolders` with no upgrade procedure that re-applies it.
See sample: `reapply-resource-instructions-on-upgrade.bad.al`.
See sample: [`reapply-resource-instructions-on-upgrade.bad.al`](reapply-resource-instructions-on-upgrade.bad.al).

View file

@ -17,13 +17,13 @@ Each agent type needs a `Copilot Capability` enum value that the factory links a
Extend `Copilot Capability` with a unique value. In `OnInstallAppPerDatabase`, call `Copilot Capability.IsCapabilityRegistered` and, if false, `RegisterCapability` with availability, billing type, and a learn-more URL. Point `IAgentFactory` at that capability.
See sample: `register-copilot-capability-for-the-agent.good.al`.
See sample: [`register-copilot-capability-for-the-agent.good.al`](register-copilot-capability-for-the-agent.good.al).
## Anti Pattern
Shipping the agent enum without a `Copilot Capability` value, or adding the enum but never calling `RegisterCapability`. Duplicate ordinals across extensions also collide. Detection signal: agent metadata provider with no matching capability registration in an install codeunit.
See sample: `register-copilot-capability-for-the-agent.bad.al`.
See sample: [`register-copilot-capability-for-the-agent.bad.al`](register-copilot-capability-for-the-agent.bad.al).
## See also

View file

@ -17,10 +17,10 @@ Instructions are instance data, not an enum caption. `Agent.SetInstructions` tak
Load instruction text from a resource or builder into a `SecretText` variable and call `Agent.SetInstructions(AgentUserSecurityId, Instructions)` after `Create`. Keep one instruction document per instance.
See sample: `set-instructions-as-secrettext.good.al`.
See sample: [`set-instructions-as-secrettext.good.al`](set-instructions-as-secrettext.good.al).
## Anti Pattern
Passing a `Label` or `Text` to `SetInstructions`, storing instructions in a setup Text field without wrapping as `SecretText`, or putting the prompt only in a code comment. Detection signal: `SetInstructions` with a non-`SecretText` argument, or no `SetInstructions` after `Create`.
See sample: `set-instructions-as-secrettext.bad.al`.
See sample: [`set-instructions-as-secrettext.bad.al`](set-instructions-as-secrettext.bad.al).

View file

@ -17,10 +17,10 @@ application-area: [all]
Use `ShowCanCreateAgent` to decide discovery. If only agent administrators should see the type, return `Agent System Permissions.CurrentUserHasCanManageAllAgentsPermission`. Enforce extra policy inside your own create API. Never assume UI hiding blocks code.
See sample: `show-can-create-agent-does-not-block-code-create.good.al`.
See sample: [`show-can-create-agent-does-not-block-code-create.good.al`](show-can-create-agent-does-not-block-code-create.good.al).
## Anti Pattern
Returning `exit(false)` from `ShowCanCreateAgent` and then documenting that instances cannot be created, while page actions or other apps still call `Agent.Create`. Detection signal: `ShowCanCreateAgent` always false with no matching guard on programmatic create.
See sample: `show-can-create-agent-does-not-block-code-create.bad.al`.
See sample: [`show-can-create-agent-does-not-block-code-create.bad.al`](show-can-create-agent-does-not-block-code-create.bad.al).

View file

@ -17,10 +17,10 @@ Incoming task messages default to requiring user approval before the agent runs.
Leave the default review-on for anything that originated outside your extension. Call `SetRequiresReview(false)` only on messages you constructed from already-authorized BC data.
See sample: `skip-incoming-review-only-for-trusted-input.good.al`.
See sample: [`skip-incoming-review-only-for-trusted-input.good.al`](skip-incoming-review-only-for-trusted-input.good.al).
## Anti Pattern
`SetRequiresReview(false)` on simulated email, incoming webhooks, or user-free text. Detection signal: `SetRequiresReview(false)` next to external content with no prior validation.
See sample: `skip-incoming-review-only-for-trusted-input.bad.al`.
See sample: [`skip-incoming-review-only-for-trusted-input.bad.al`](skip-incoming-review-only-for-trusted-input.bad.al).

View file

@ -17,13 +17,13 @@ The agent runtime looks for specific phrases: ask for assistance, request a revi
In the instruction resource, use those keywords at the decision points: request a review before posting; write an email only after stating that outbound mail is reviewed; memorize values the later steps need. Pair `Reply` / `Write an email` with an explicit review sentence.
See sample: `use-documented-instruction-keywords.good.al`.
See sample: [`use-documented-instruction-keywords.good.al`](use-documented-instruction-keywords.good.al).
## Anti Pattern
Inventing tool-like verbs (call Copilot, click Post_Promoted) or omitting request a review before posting. Detection signal: instruction text that says email the customer with no review keyword.
See sample: `use-documented-instruction-keywords.bad.al`.
See sample: [`use-documented-instruction-keywords.bad.al`](use-documented-instruction-keywords.bad.al).
## See also

View file

@ -17,13 +17,13 @@ An AL agent type is registered by extending `Agent Metadata Provider`. The platf
On the enum value, set `Implementation` for all three interfaces, each pointing at a dedicated codeunit. Keep factory (create, defaults, first-time setup), metadata (setup page, summary, annotations), and task execution (message analysis, intervention suggestions) in separate objects.
See sample: `wire-all-three-agent-interfaces.good.al`.
See sample: [`wire-all-three-agent-interfaces.good.al`](wire-all-three-agent-interfaces.good.al).
## Anti Pattern
An `Agent Metadata Provider` value with no `Implementation`, only one interface mapped, or all three interfaces pointing at one catch-all codeunit that cannot satisfy the contracts. Detection signal: enumextension of `Agent Metadata Provider` whose value does not list `IAgentFactory`, `IAgentMetadata`, and `IAgentTaskExecution`.
See sample: `wire-all-three-agent-interfaces.bad.al`.
See sample: [`wire-all-three-agent-interfaces.bad.al`](wire-all-three-agent-interfaces.bad.al).
## See also