Skip to main content

External Participants

External Participants enable customer stakeholders to participate in AI-driven processes without requiring full platform accounts, using secure magic link authentication.

Why External Participants?

Enterprise deployments involve people outside your organization:

  • Customer IT Admins - Approve SSO configurations
  • Customer CISOs - Sign off on security reviews
  • Customer HR Managers - Validate SCIM user mappings
  • Partners - Review integration configurations

External participants need:

  • Secure access without creating accounts
  • Limited, scoped permissions
  • Clear audit trail
  • Easy approval workflows

How It Works

┌─────────────────────────────────────────────────────────────┐
│ Process Instance │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. Agent reaches approval gate │
│ │ │
│ ▼ │
│ 2. System generates magic link │
│ │ │
│ ▼ │
│ 3. Email sent to external participant │
│ │ │
│ ▼ │
│ 4. Participant clicks link → lands on approval portal │
│ │ │
│ ▼ │
│ 5. Reviews context, artifacts, makes decision │
│ │ │
│ ▼ │
│ 6. Decision recorded, process continues │
│ │
└─────────────────────────────────────────────────────────────┘
const magicLink = await client.processes.createExternalParticipantLink({
processInstanceId: 'proc-inst-123',
participantId: 'customer_it_admin',
email: 'admin@customer.com',
name: 'John Smith',
expiresIn: '7d',
permissions: ['view', 'approve', 'comment']
})

// Returns:
// {
// url: 'https://app.meetloyd.com/external/p/proc-inst-123?token=eyJhbGc...',
// token: 'eyJhbGc...',
// expiresAt: '2024-01-22T10:00:00Z'
// }
await client.processes.sendParticipantInvite({
processInstanceId: 'proc-inst-123',
participantId: 'customer_it_admin',
email: 'admin@customer.com',
subject: 'SSO Configuration Review Required',
customMessage: 'Please review the SSO configuration for your Okta integration.'
})

Email template:

Subject: SSO Configuration Review Required - Acme Corp Deployment

Hi John,

You have been invited to review the SSO configuration for the
Acme Corp deployment.

[Review Configuration] <-- Magic link button

Your approval is required to proceed with the deployment.

This link expires in 7 days.

---
MeetLoyd Enterprise Deployment Team

Participant Portal

External participants access a secure, limited portal:

Portal Features

┌─────────────────────────────────────────────────────────────┐
│ Enterprise SSO Deployment - Acme Corp │
│ Status: Awaiting Your Approval │
├─────────────────────────────────────────────────────────────┤
│ │
│ 📋 Current Phase: Configuration │
│ ⏱️ Started: Jan 15, 2024 │
│ 📊 Progress: 45% │
│ │
├─────────────────────────────────────────────────────────────┤
│ Pending Approval │
│ ───────────────── │
│ SSO Configuration Review │
│ │
│ Please review the following configuration: │
│ │
│ 📄 SSO Configuration Summary │
│ 📄 Attribute Mapping Document │
│ 📄 Test Results │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Comments (optional) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ [Approve] [Request Changes] [Reject] │
│ │
├─────────────────────────────────────────────────────────────┤
│ Activity History │
│ ───────────────── │
│ Jan 18 - SSO configuration completed by SSO Agent │
│ Jan 17 - Requirements gathered │
│ Jan 15 - Deployment started │
│ │
└─────────────────────────────────────────────────────────────┘

Portal Permissions

PermissionDescription
viewView process status and artifacts
approveApprove pending approval requests
rejectReject and provide feedback
commentAdd comments to the process
uploadUpload additional documents

Defining External Participants

In Process Definition

const processDefinition: ProcessDefinition = {
// ...
humans: {
customer_it_admin: {
id: 'customer_it_admin',
name: 'Customer IT Administrator',
role: 'approver',
raidRole: 'approver',
description: 'Customer IT team member responsible for SSO configuration',
requiredApprovals: [
'sso_config_review',
'scim_provisioning_review',
'production_deployment'
],
notificationPreferences: {
email: true,
reminderIntervals: ['24h', '48h']
}
},
customer_ciso: {
id: 'customer_ciso',
name: 'Customer CISO',
role: 'approver',
raidRole: 'approver',
description: 'Security executive for final security sign-off',
requiredApprovals: [
'security_review',
'compliance_sign_off'
]
},
customer_hr_manager: {
id: 'customer_hr_manager',
name: 'Customer HR Manager',
role: 'informed',
raidRole: 'informed',
description: 'HR manager who needs visibility into user provisioning',
notifications: ['user_provisioning_complete', 'group_mapping_complete']
}
}
}

Assign to Process Instance

const instance = await client.processes.start({
processId: 'enterprise_sso_deployment',
name: 'Acme Corp SSO Deployment',
externalParticipants: [
{
participantId: 'customer_it_admin',
email: 'john.smith@acme.com',
name: 'John Smith',
title: 'Senior IT Administrator'
},
{
participantId: 'customer_ciso',
email: 'jane.doe@acme.com',
name: 'Jane Doe',
title: 'Chief Information Security Officer'
},
{
participantId: 'customer_hr_manager',
email: 'bob.johnson@acme.com',
name: 'Bob Johnson',
title: 'HR Director'
}
]
})

Approval Workflows

Request Approval

Agents request approval when reaching gates:

// Agent requests approval
await client.processes.requestApproval('proc-inst-123', {
taskId: 'sso_config_review',
title: 'SSO Configuration Review',
description: 'Please review the SSO configuration before we proceed to testing.',
approverIds: ['customer_it_admin'],
artifacts: [
{
name: 'SSO Configuration Summary',
key: 'sso_config_summary',
type: 'document'
},
{
name: 'Test Results',
key: 'sso_test_results',
type: 'report'
}
],
context: {
idpType: 'okta',
configuredAttributes: ['email', 'firstName', 'lastName', 'department'],
testStatus: 'passed'
},
expiresIn: '48h',
reminderAt: ['24h']
})

Handle Approval Response

// Listen for approval responses
client.processes.onApprovalResponse('proc-inst-123', (response) => {
if (response.approved) {
console.log('Approval received:', {
taskId: response.taskId,
approver: response.approverEmail,
timestamp: response.timestamp,
comments: response.comments
})
// Process continues automatically
} else if (response.status === 'changes_requested') {
console.log('Changes requested:', {
feedback: response.feedback,
requestedChanges: response.requestedChanges
})
// Notify agents to make changes
} else if (response.status === 'rejected') {
console.log('Approval rejected:', {
reason: response.reason
})
// Handle rejection
}
})

Approval States

                      ┌─────────────┐
│ pending │
└──────┬──────┘

┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌───────────┐ ┌─────────────┐ ┌──────────┐
│ approved │ │ changes_ │ │ rejected │
└───────────┘ │ requested │ └──────────┘
└──────┬──────┘


┌─────────────┐
│ pending │ (after changes)
└─────────────┘

Notifications

Email Notifications

// Configure notification preferences
await client.processes.updateParticipantPreferences('proc-inst-123', {
participantId: 'customer_it_admin',
preferences: {
email: {
enabled: true,
frequency: 'immediate', // 'immediate' | 'daily_digest' | 'weekly'
types: ['approval_required', 'status_update', 'completion']
},
reminders: {
enabled: true,
intervals: ['24h', '48h'],
escalateAfter: '72h'
}
}
})

Notification Types

TypeDescriptionTrigger
approval_requiredNew approval pendingApproval request created
reminderApproval reminderBased on configured intervals
escalationEscalated to backupTimeout reached
status_updatePhase completedPhase transition
completionProcess completedAll phases done

Custom Email Templates

await client.processes.setEmailTemplate({
processId: 'enterprise_sso_deployment',
templateType: 'approval_required',
template: {
subject: '{{process_name}} - Your Approval Required',
body: `
Hi {{participant_name}},

{{#if urgent}}
URGENT: Your approval is needed for {{task_title}}.
{{else}}
Your approval is needed for {{task_title}}.
{{/if}}

Process: {{process_name}}
Phase: {{current_phase}}

{{task_description}}

[Review and Approve]({{approval_link}})

This approval is due by {{due_date}}.

Best regards,
{{company_name}} Team
`
}
})

Security

Token Security

Magic link tokens are:

  • Single-use per session
  • Time-limited (configurable expiration)
  • Scoped to specific process and participant
  • Revocable at any time
// Revoke a participant's access
await client.processes.revokeParticipantAccess('proc-inst-123', {
participantId: 'customer_it_admin',
reason: 'Contact changed'
})

// Generate new link for replacement contact
const newLink = await client.processes.createExternalParticipantLink({
processInstanceId: 'proc-inst-123',
participantId: 'customer_it_admin',
email: 'new.admin@customer.com',
name: 'New Admin'
})

Access Logging

All external participant actions are logged:

const accessLog = await client.processes.getParticipantAccessLog('proc-inst-123', {
participantId: 'customer_it_admin',
limit: 50
})

for (const entry of accessLog.entries) {
console.log({
timestamp: entry.timestamp,
action: entry.action, // 'link_accessed', 'artifact_viewed', 'approval_submitted'
ipAddress: entry.ipAddress,
userAgent: entry.userAgent,
details: entry.details
})
}

IP Restrictions

Optionally restrict access by IP:

await client.processes.setParticipantRestrictions('proc-inst-123', {
participantId: 'customer_ciso',
restrictions: {
allowedIpRanges: ['10.0.0.0/8', '192.168.1.0/24'],
requireMfa: true,
maxSessions: 1
}
})

API Reference

Participant Endpoints

EndpointMethodDescription
/api/processes/:id/participantsGETList participants
/api/processes/:id/participantsPOSTAdd participant
/api/processes/:id/participants/:pid/linkPOSTGenerate magic link
/api/processes/:id/participants/:pid/invitePOSTSend invite email
/api/processes/:id/participants/:pid/revokePOSTRevoke access

External Portal Endpoints

EndpointMethodDescription
/external/p/:processIdGETPortal view
/external/p/:processId/approvals/:idGETApproval details
/external/p/:processId/approvals/:idPOSTSubmit response
/external/p/:processId/artifacts/:keyGETView artifact

Best Practices

1. Clear Participant Roles

Define specific responsibilities:

humans: {
customer_it_admin: {
requiredApprovals: ['sso_config', 'scim_config'], // Technical approvals
},
customer_ciso: {
requiredApprovals: ['security_review'], // Security approvals
},
customer_hr_manager: {
// No approvals, just informed
notifications: ['user_provisioning_complete']
}
}

2. Appropriate Timeouts

Set realistic deadlines:

// Technical review
await client.processes.requestApproval({
expiresIn: '48h',
reminderAt: ['24h']
})

// Security review (may need longer)
await client.processes.requestApproval({
expiresIn: '5d',
reminderAt: ['24h', '72h', '96h']
})

3. Provide Context

Include all information needed for decisions:

await client.processes.requestApproval({
artifacts: ['config_summary', 'test_results', 'security_scan'],
context: {
summary: 'Brief description',
impact: 'What this affects',
risks: 'Any considerations',
recommendation: 'Our recommendation'
}
})

4. Handle Escalation

Plan for non-responsive participants:

externalParticipants: [
{
participantId: 'customer_it_admin',
email: 'primary@customer.com',
escalateTo: {
email: 'backup@customer.com',
after: '72h'
}
}
]

Next: Learn about Audit Logs for tracking all process activities.