# Predefined Actors Predefined actors are [BasicPlugin](https://docs.workflowengine.io/plugins/basic-plugin/overview/) actor definitions registered in application code and injected into matching [workflow schemes](https://docs.workflowengine.io/get-started/concepts/scheme/) by [WorkflowRuntime](https://docs.workflowengine.io/get-started/concepts/workflow-runtime/). Register actor names with `WithActor` or `WithActors`, resolve their identities with the plugin delegates, then select the injected actor in an `Allow` restriction on a command transition. **Prerequisites:** - [Basic Plugin Overview](https://docs.workflowengine.io/plugins/basic-plugin/overview/) - BasicPlugin registration and configuration. - [Workflow Runtime configuration](https://docs.workflowengine.io/get-started/concepts/workflow-runtime/) - builder, persistence provider, startup, and shutdown configuration. ## Real-world scenario A document management system uses separate schemes for invoices, contracts, and other document types. Each [process instance](https://docs.workflowengine.io/get-started/concepts/process-instance/) stores the document owner's identity in a persistent `AuthorId` [parameter](https://docs.workflowengine.io/get-started/concepts/parameter/), while the [application identity system](https://docs.workflowengine.io/evaluate/workflow-engine-features/pluggable-security/) assigns the `Manager` role independently of any document. Without predefined actors, every document scheme would need separate actor definitions that check the `Manager` role and determine the current document author. Register `Managers` and `DocumentAuthor` for all schemes with one `WithActors` call instead. The BasicPlugin callbacks resolve `Managers` through the role directory and resolve `DocumentAuthor` from the current process instance. ## Workflow scheme The `InvoiceApproval` scheme restricts `Submit` to the document author and restricts `Approve` to managers. A `ContractApproval` scheme can use the same predefined actor names without copying their rule configuration. ![Predefined actors document approval workflow](https://docs.workflowengine.io/images/plugins/basic-plugin/predefined-actors/document-approval.png) **Related capabilities:** `WithActor`, `WithActors`, `Predefined` [rule](https://docs.workflowengine.io/get-started/concepts/rule/), `CheckPredefinedActorAsync` delegate. ```xml filename="invoice-approval.xml" ``` The XML declares `AuthorId`, activities, commands, and restrictions, but it does not declare the predefined actors. WorkflowRuntime injects `DocumentAuthor` and `Managers` before parsing the restrictions. After BasicPlugin is registered, open the scheme in the Designer, enable **Show predefined actors**, and select the injected actor in each restriction. ## Configure predefined actors Configure actor names, scheme scopes, and identity delegates before passing BasicPlugin to `WorkflowRuntime.WithPlugin`. The registration determines which actor definitions the runtime injects into each loaded scheme. ### Register actor names BasicPlugin stores predefined actor names separately from the scheme. `WithActor` registers one name, while `WithActors` registers several names. Configure the names and identity delegates before passing the plugin to `WorkflowRuntime.WithPlugin`. ```csharp filename="PredefinedActorsConfiguration.cs" using System; using System.Collections.Generic; using System.Threading.Tasks; using OptimaJet.Workflow.Plugins; public interface IUserDirectory { Task IsInRoleAsync( string identityId, string roleName); Task> GetUsersInRoleAsync( string roleName); } public static class PredefinedActorsConfiguration { public static BasicPlugin CreateBasicPlugin( IUserDirectory userDirectory) { var basicPlugin = new BasicPlugin(); basicPlugin.WithActors(["Managers", "DocumentAuthor"]); basicPlugin.CheckPredefinedActorAsync = async (processInstance, runtime, actorName, identityId) => { if (actorName == "Managers") { return await userDirectory.IsInRoleAsync( identityId, "Manager"); } if (actorName == "DocumentAuthor") { string authorId = await processInstance .GetParameterAsync("AuthorId"); return string.Equals( authorId, identityId, StringComparison.Ordinal); } return false; }; basicPlugin.GetPredefinedIdentitiesAsync = async (processInstance, runtime, actorName) => { if (actorName == "Managers") { return await userDirectory .GetUsersInRoleAsync("Manager"); } if (actorName == "DocumentAuthor") { string authorId = await processInstance .GetParameterAsync("AuthorId"); return string.IsNullOrEmpty(authorId) ? [] : [authorId]; } return []; }; return basicPlugin; } } ``` Pass the returned BasicPlugin instance to `runtime.WithPlugin(...)` within the complete WorkflowRuntime configuration. The runtime configuration guide shows the required builder and persistence provider setup before `StartAsync()`. `CheckPredefinedActorAsync` checks one identity during rule authorization. BasicPlugin passes the registered actor name in the third string position and the identity ID in the fourth string position, which is why the example names those lambda arguments `actorName` and `identityId`. `GetPredefinedIdentitiesAsync` returns the same manager role members or the `AuthorId` belonging to the current document process. Configure both callbacks when the application checks individual identities and enumerates workflow participants. ### Choose actor scope The `schemes` argument on `WithActor` and `WithActors` controls which scheme codes receive a predefined actor. A missing or empty list registers the actor for every scheme; a non-empty list limits the actor to the listed scheme codes. Table: Predefined actor scopes | Registration | Resulting scope | |---|---| | `WithActor("Managers")` | `Managers` is available to every scheme | | `WithActors(names)` | Every name is available to every scheme | | `WithActor("DocumentAuthor", schemes)` | `DocumentAuthor` is available only to the listed scheme codes | | `WithActors(names, schemes)` | Every name is available only to the listed scheme codes | WorkflowRuntime combines the all-scheme names with the names registered for the current scheme code. Do not register the same actor name in both scopes for one scheme: duplicate predefined names cause `GetPredefinedActors` to throw `ArgumentException` while the scheme is loaded. ## Predefined actor reference WorkflowRuntime converts matching registrations into predefined actor definitions and uses the BasicPlugin callbacks to authorize identities. The provider API also supports applications that need to update registered actor collections explicitly. ### Generated actor definitions WorkflowRuntime creates an actor definition for every matching registered name before it parses [transitions](https://docs.workflowengine.io/get-started/concepts/transition/). The generated definition uses the registered name for both `Name` and `Value`, assigns the `Predefined` rule, and sets `IsPredefined` to `true`. Do not add a second actor with that name to the scheme. ### Runtime authorization For a command transition such as `Approve`, configure the restriction in the Designer as follows: Table: Predefined actor transition restriction | Transition setting | Value | |---|---| | Trigger | `Command` | | Command | `Approve` | | Restriction type | `Allow` | | Actor | `Managers` | The `Predefined` rule is excluded from the ordinary Designer rule list, but it remains available to runtime authorization. Select the injected `Managers` actor in the restriction instead of creating a manual actor or choosing `CheckRole`. When a user requests the command, the `Predefined` rule calls `CheckPredefinedActorAsync` with `Managers` and that user's identity ID. ### Actor provider operations `PredefinedActorProvider` exposes the thread-safe `IActorProvider` API behind the convenience methods. Use `WithActor` and `WithActors` for initial configuration; use the provider when the application needs explicit read, replace, merge, add, or remove operations grouped by scheme code. Table: PredefinedActorProvider operations | Member | Operation | |---|---| | `GetAllActors` | Returns copies of all actor collections grouped by scheme code | | `SetAllActors` | Replaces all grouped actor collections | | `UnionAllActors` | Merges actor collections into their matching scheme groups | | `GetActors` and `SetActors` | Reads or replaces the collection for one scheme code | | `AddActor` and `AddActors` | Adds one or more names to one scheme group | | `RemoveActor` and `RemoveActors` | Removes one or more names from one scheme group | | `IsActorExist` | Checks whether one scheme group contains an actor name | The [BasicPlugin API reference](https://api.workflowengine.io/core/OptimaJet.Workflow.Plugins/BasicPlugin/) lists the public plugin members. Actor registration methods are intended for configuration before BasicPlugin is initialized by WorkflowRuntime. ## Verify actor authorization WorkflowRuntime injects a scheme-specific predefined actor only when the loaded scheme code matches its registration. Open the matching scheme in the Designer, enable **Show predefined actors**, and confirm that the actor appears as predefined. Then request the commands available to a known identity. A matching identity receives the restricted command; an identity for which `CheckPredefinedActorAsync` returns `false` does not. Participant-enumeration APIs call `GetPredefinedIdentitiesAsync` instead of the single-identity check. Verify that this callback returns the same identity set represented by `CheckPredefinedActorAsync`, so command authorization and participant lists remain consistent. ## Troubleshooting common errors Predefined actor failures usually come from actor scope, duplicate names, or an unassigned BasicPlugin delegate. Match the observed symptom to the corresponding registration step. | Symptom | Cause | Fix | |---|---|---| | A predefined actor is absent from a scheme | The scheme code is not in the actor scope, or BasicPlugin was registered after the scheme was loaded | Match the exact scheme code and register BasicPlugin during runtime configuration | | Authorization fails when the rule runs | `CheckPredefinedActorAsync` is not configured | Assign the single-identity callback before registering BasicPlugin | | Participant enumeration fails | `GetPredefinedIdentitiesAsync` is not configured | Assign the identity-enumeration callback before registering BasicPlugin | | Scheme loading reports a duplicate predefined actor | The same name is registered for all schemes and for the current scheme | Keep the actor in only one applicable scope | | `Predefined` is missing from the rule dropdown | BasicPlugin intentionally excludes the system rule from ordinary choices | Select the runtime-injected actor in the transition restriction | ## See also - [Basic Plugin Overview](https://docs.workflowengine.io/plugins/basic-plugin/overview/): Register BasicPlugin and review its actions, conditions, rules, and configuration API. - [Role-Based Authorization](https://docs.workflowengine.io/plugins/basic-plugin/role-based-authorization/): Restrict commands by resolving identities through application roles. - [Rule](https://docs.workflowengine.io/get-started/concepts/rule/): Understand how actors connect transition restrictions to authorization checks. - [Pluggable Security](https://docs.workflowengine.io/evaluate/workflow-engine-features/pluggable-security/): Connect workflow authorization to an existing identity system. ## Frequently asked questions **Do I add predefined actors to the workflow scheme?** No. WorkflowRuntime injects predefined actors registered by BasicPlugin while it parses the scheme. Reference the injected actor from a transition restriction instead of declaring a duplicate actor in the scheme. **Can a predefined actor be limited to one workflow scheme?** Yes. Pass the applicable scheme codes to `WithActor` or `WithActors`. Passing no scheme list, or an empty list, makes the predefined actor available to every scheme. **Which predefined actor delegates should I configure?** Configure `CheckPredefinedActorAsync` for single-identity authorization and `GetPredefinedIdentitiesAsync` for participant enumeration. Configure both when the application uses both runtime paths. **Why is the Predefined rule missing from the Designer rule list?** BasicPlugin excludes `Predefined` from ordinary rule choices because WorkflowRuntime assigns it to injected actor definitions. The rule remains registered for runtime authorization. **How are predefined actors different from CheckRole actors?** Predefined actors map application-defined names to identities through the two predefined actor delegates. `CheckRole` actors pass a role value to `UsersInRoleAsync`; see [Role-Based Authorization](https://docs.workflowengine.io/plugins/basic-plugin/role-based-authorization/) for that pattern.