Flow Studio
User Lookup Node
Resolving a user by email, employee ID, or username — the UserLookupNode config, output shape, and how to use the result in downstream expressions.
Node Configuration
{
"nodeType": "UserLookup",
"name": "fetchApprover",
"config": {
"lookupBy": "email",
"value": "$output.fetchInvoice.managerEmail",
"includeRoles": true,
"failOnNotFound": true
}
}
Configuration Fields
| Field | Values | Description |
|---|---|---|
lookupBy | email | employeeId | username | userId | The identifier type to search by |
value | string / expr | The lookup value. Expressions evaluated against execution context. |
includeRoles | bool | Whether to include the user's role array in the output. Default: false. |
failOnNotFound | bool | If true, routes to error port when user not found. If false, outputs null. Default: true. |
Node Output
{
"userId": "usr-a1b2c3",
"email": "alice@acme.com",
"displayName": "Alice Kowalski",
"username": "alice.kowalski",
"employeeId": "EMP-0042",
"isActive": true,
"roles": ["approver", "finance-manager"],
"managerId": "usr-mgr001",
"department": "Finance"
}
Using Output in Downstream Nodes
// In an ApprovalNode actor field:
"actorId": "$output.fetchApprover.userId"
// In a SendSlackMessage channelId:
"channelId": "@$output.fetchApprover.username"
// In a condition expression:
"$output.fetchApprover.roles.includes('finance-manager')"
// In a ForEach items field to iterate over roles:
"items": "$output.fetchApprover.roles"
UserLookupExecutor
public class UserLookupExecutor : BaseNodeExecutor<UserLookupConfig>
{
private readonly IPassportClient _passport;
protected override async Task<NodeExecutionResult> ExecuteAsync(
UserLookupConfig config,
NodeDataContext ctx,
CancellationToken ct)
{
var lookupValue = _evaluator.Evaluate<string>(config.Value, ctx);
var request = new UserLookupRequest
{
LookupBy = config.LookupBy,
Value = lookupValue,
IncludeRoles = config.IncludeRoles,
TenantId = ctx.TenantId
};
var user = await _passport.LookupUserAsync(request, ct);
if (user == null)
{
if (config.FailOnNotFound)
return NodeExecutionResult.Fail(new IdentityNotFoundException(
$"User not found by {config.LookupBy}: {lookupValue}"));
return NodeExecutionResult.Success(null);
}
return NodeExecutionResult.Success(new
{
user.UserId,
user.Email,
user.DisplayName,
user.Username,
user.EmployeeId,
user.IsActive,
Roles = config.IncludeRoles ? user.Roles : null,
user.ManagerId,
user.Department
});
}
}
Caching: The
IPassportClient implementation caches user lookups for 60 seconds within an execution to avoid repeated Passport API calls for the same user. If a workflow queries the same user in multiple nodes, only the first call hits the network.