Skip to main content

Audit Logs

Comprehensive activity logging for security, compliance, and debugging.

What's Logged

Every significant action is recorded:

CategoryExamples
AuthenticationLogin, logout, MFA events, failed attempts
AuthorizationPermission changes, role updates
AgentsCreate, update, delete, execute
ConversationsStart, message, end, delete
UsersInvite, update, remove
TeamsCreate, update, membership changes
IntegrationsConnect, disconnect, tool execution
API KeysCreate, rotate, revoke
SettingsConfiguration changes

Viewing Audit Logs

Via Dashboard

  1. Go to SecurityAudit Logs
  2. Filter by user, action, date range
  3. Export to CSV/JSON

Via API

const logs = await client.audit.list({
// Filters
userId: 'user-123',
action: 'agent.create',
severity: 'warning',
resourceType: 'agent',
resourceId: 'agent-456',

// Date range
startDate: '2024-01-01',
endDate: '2024-01-31',

// Search
search: 'delete',

// Pagination
limit: 100,
offset: 0
});

for (const log of logs.data) {
console.log({
id: log.id,
action: log.action,
severity: log.severity,
userId: log.userId,
resourceType: log.resourceType,
resourceId: log.resourceId,
description: log.description,
metadata: log.metadata,
ipAddress: log.ipAddress,
userAgent: log.userAgent,
timestamp: log.timestamp
});
}

Log Entry Structure

interface AuditLogEntry {
id: string;
tenantId: string;

// Who
userId: string;
userName?: string;
ipAddress: string;
userAgent: string;

// What
action: string;
severity: 'info' | 'warning' | 'critical';
resourceType: string;
resourceId: string;
description: string;

// Details
metadata: Record<string, any>;

// When
timestamp: string;
}

Action Types

Authentication Actions

ActionDescription
auth.loginUser logged in
auth.logoutUser logged out
auth.login_failedFailed login attempt
auth.mfa_enabledMFA was enabled
auth.mfa_verifiedMFA code verified
auth.password_changedPassword was changed
auth.password_resetPassword reset requested
auth.session_revokedSession was terminated

Agent Actions

ActionDescription
agent.createAgent created
agent.updateAgent configuration changed
agent.deleteAgent deleted
agent.chatChat message sent to agent
agent.tool_executedAgent executed a tool

User Actions

ActionDescription
user.inviteUser invited
user.joinedUser accepted invite
user.updateUser profile updated
user.role_changedUser role changed
user.deleteUser deleted

Team Actions

ActionDescription
team.createTeam created
team.updateTeam settings changed
team.deleteTeam deleted
team.member_addedMember added to team
team.member_removedMember removed from team

Integration Actions

ActionDescription
integration.connectedIntegration connected
integration.disconnectedIntegration revoked
integration.tool_executedIntegration tool called
integration.refreshOAuth token refreshed

API Key Actions

ActionDescription
api_key.createdAPI key created
api_key.rotatedAPI key rotated
api_key.revokedAPI key revoked

Severity Levels

LevelDescriptionExamples
infoNormal operationsLogin, create agent
warningPotentially concerningFailed login, permission denied
criticalSecurity-relevantUser deleted, bulk operation

Filter by Severity

// Get only security-relevant events
const criticalLogs = await client.audit.list({
severity: 'critical'
});

// Get warnings and above
const warningsAndCritical = await client.audit.list({
severity: ['warning', 'critical']
});

Search and Filter

By User

const userLogs = await client.audit.list({
userId: 'user-123'
});

By Action

// Single action
const createLogs = await client.audit.list({
action: 'agent.create'
});

// Multiple actions
const modifyLogs = await client.audit.list({
action: ['agent.update', 'agent.delete']
});

// Pattern matching
const allAgentLogs = await client.audit.list({
action: 'agent.*'
});

By Resource

const agentLogs = await client.audit.list({
resourceType: 'agent',
resourceId: 'agent-123'
});

By Time Range

const recentLogs = await client.audit.list({
startDate: '2024-01-15T00:00:00Z',
endDate: '2024-01-15T23:59:59Z'
});
const searchResults = await client.audit.list({
search: 'production agent delete'
});

Statistics

Get aggregated audit data:

const stats = await client.audit.getStats({
startDate: '2024-01-01',
endDate: '2024-01-31'
});

console.log({
totalEvents: stats.total,
bySeverity: stats.bySeverity,
byAction: stats.byAction,
topUsers: stats.topUsers,
failedLogins: stats.failedLogins
});

Security Alerts

Configure alerts for suspicious activity. Alerts trigger when a specific action pattern occurs more than a threshold number of times within a time window.

Create Alert

await client.audit.createAlert({
name: 'Multiple Failed Logins',
description: 'Alert when multiple login failures occur', // optional
condition: {
action: 'auth.login_failed', // action pattern to match
threshold: 5, // number of occurrences
window: '5m' // time window: 5m, 1h, 24h, etc.
},
notify: ['security@company.com'], // email recipients (required)
notifyWebhook: 'https://slack.com/...', // optional webhook URL
severity: 'high' // low, medium, high, critical
});

Schedule-Based Alerts (SOX Compliance)

For SOX compliance, you can configure alerts that only trigger during or outside specific hours. This is essential for monitoring after-hours access.

// Alert when admin actions occur OUTSIDE business hours (after-hours monitoring)
await client.audit.createAlert({
name: 'After-Hours Admin Activity',
description: 'Alert when admin actions occur outside business hours',
condition: {
action: 'admin.*',
threshold: 1,
window: '5m'
},
timeWindow: {
mode: 'exclude', // 'exclude' = alert OUTSIDE these hours, 'include' = alert DURING these hours
start: '09:00', // Business hours start (HH:MM)
end: '18:00', // Business hours end (HH:MM)
daysOfWeek: [1, 2, 3, 4, 5], // Mon-Fri (0=Sun, 6=Sat)
useUserTimezone: true, // SOX: evaluate in acting user's local timezone
timezone: 'America/New_York' // Fallback if useUserTimezone is false
},
notify: ['security@company.com', 'compliance@company.com'],
severity: 'critical'
});

// Alert for weekend access
await client.audit.createAlert({
name: 'Weekend System Access',
condition: {
action: 'auth.login',
threshold: 1,
window: '1h'
},
timeWindow: {
mode: 'include', // Alert only DURING these times (weekends)
start: '00:00',
end: '23:59',
daysOfWeek: [0, 6], // Sat-Sun only
useUserTimezone: true
},
notify: ['security@company.com'],
severity: 'high'
});

Time Window Options

FieldDescription
mode'always' (24/7), 'include' (only during hours), 'exclude' (only outside hours)
startStart time in HH:MM format (e.g., '09:00')
endEnd time in HH:MM format (e.g., '18:00')
daysOfWeekArray of day numbers: 0=Sun, 1=Mon, ..., 6=Sat
useUserTimezonetrue = evaluate in acting user's timezone (SOX recommended)
timezoneIANA timezone fallback (e.g., 'America/New_York', 'Europe/Paris')
SOX Compliance

For SOX compliance, set useUserTimezone: true. This ensures that "after-hours" is evaluated based on each user's local timezone:

  • NY user logging in at 8pm NY time → After hours → Alert triggers
  • Tokyo user logging in at 8pm Tokyo time → After hours → Alert triggers

This is more accurate than using a fixed timezone for global organizations.

List Alerts

const response = await client.audit.listAlerts();

for (const alert of response.data) {
console.log({
id: alert.id,
name: alert.name,
description: alert.description,
condition: alert.condition, // { action, threshold, window }
timeWindow: alert.timeWindow, // { mode, start, end, timezone, daysOfWeek, useUserTimezone }
notify: alert.notify, // email array
notifyWebhook: alert.notifyWebhook,
severity: alert.severity,
enabled: alert.enabled,
triggeredCount: alert.triggeredCount,
lastTriggeredAt: alert.lastTriggeredAt,
createdAt: alert.createdAt,
updatedAt: alert.updatedAt
});
}

Update Alert

await client.audit.updateAlert('alert-123', {
enabled: false, // disable the alert
condition: {
threshold: 10 // increase threshold
},
timeWindow: {
mode: 'exclude',
start: '08:00',
end: '19:00' // extend business hours
}
});

Delete Alert

await client.audit.deleteAlert('alert-123');

SOX Compliance Features

MeetLoyd provides comprehensive SOX compliance features for audit logging:

1. Tamper-Proof Hash Chain

Every audit log entry includes a cryptographic hash that chains to the previous entry, creating an immutable, verifiable audit trail.

// Each log entry contains:
{
id: "log_abc123",
hash: "a1b2c3d4...", // SHA-256 hash of this entry
previousHash: "x9y8z7...", // Hash of previous entry (blockchain-like)
sequenceNumber: 42, // Monotonic sequence for verification
// ... other fields
}

Verify Hash Chain Integrity

const result = await client.audit.verifyIntegrity();

console.log({
valid: result.valid, // true if no tampering detected
totalLogs: result.totalLogs, // number of logs verified
firstLog: result.firstLog, // timestamp of first log
lastLog: result.lastLog, // timestamp of last log
errors: result.errors, // any integrity errors found
message: result.message // human-readable summary
});

2. Immutable Logs

Configure logs to become immutable after a specified time period:

await client.retention.update({
auditLogsImmutable: true, // Enable immutability
auditLogsImmutableAfterHours: 24, // Logs become immutable after 24 hours
auditLogsHashChainEnabled: true, // Enable hash chain verification
});

3. Segregation of Duties (SoD) Alerts

Detect when the same user performs conflicting actions that should require separate individuals:

// Create SoD alert to detect self-approval
await client.audit.createSodAlert({
name: 'Self-Approval Prevention',
description: 'Alert when same user requests and approves',
conditionType: 'segregation',
segregation: {
firstAction: 'approval.request',
secondAction: 'approval.approve',
window: '24h' // Check for both actions within 24 hours
},
notify: ['compliance@company.com'],
severity: 'critical'
});

Get SoD Presets

MeetLoyd provides common SoD conflict presets:

const presets = await client.audit.getSodPresets();

// Available presets:
// - approval_self_approve: Same user requests and approves
// - agent_create_delete: Same user creates and deletes an agent
// - user_invite_remove: Same user invites and removes a team member
// - api_key_lifecycle: Same user creates and revokes an API key
// - settings_audit: Same user modifies settings and exports audit logs

4. User Timezone Tracking

Each audit log entry captures the actor's timezone for accurate time-based compliance analysis:

// Log entry includes:
{
actorId: "user_123",
actorEmail: "john@company.com",
actorTimezone: "America/New_York", // User's timezone at action time
createdAt: "2024-01-15T14:30:00Z",
// ...
}

SIEM Integration

Export logs to your security information and event management system:

Webhook Export

await client.audit.configureSiemExport({
type: 'webhook',
url: 'https://siem.company.com/ingest',
headers: {
'Authorization': 'Bearer ${secrets.SIEM_TOKEN}'
},
format: 'json', // json, cef, leef
filters: {
severity: ['warning', 'critical'],
actions: ['auth.*', '*.delete']
},
realtime: true
});

S3 Export

await client.audit.configureSiemExport({
type: 's3',
bucket: 'company-audit-logs',
prefix: 'meetloyd/',
region: 'us-east-1',
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY
},
format: 'json',
schedule: 'hourly'
});

Supported SIEM Platforms

PlatformFormatMethod
SplunkJSON/CEFWebhook/S3
DatadogJSONWebhook
ElasticJSONWebhook
Azure SentinelCEFWebhook
IBM QRadarLEEFWebhook

Log Formats

JSON (Default)

{
"id": "log-123",
"timestamp": "2024-01-15T10:30:00.000Z",
"severity": "warning",
"action": "auth.login_failed",
"userId": "user-456",
"userName": "john@company.com",
"ipAddress": "203.0.113.50",
"userAgent": "Mozilla/5.0...",
"resourceType": "auth",
"description": "Failed login attempt",
"metadata": {
"reason": "invalid_password",
"attemptCount": 3
}
}

CEF (Common Event Format)

CEF:0|MeetLoyd|Platform|1.0|auth.login_failed|Failed login attempt|5|src=203.0.113.50 suser=john@company.com cs1=invalid_password

LEEF (Log Event Extended Format)

LEEF:2.0|MeetLoyd|Platform|1.0|auth.login_failed|src=203.0.113.50	usrName=john@company.com	reason=invalid_password

Retention

Log retention varies by plan:

PlanRetention
Starter7 days
Pro30 days
Business90 days
EnterpriseCustom (up to 7 years)

Configure Retention

// Enterprise only
await client.audit.setRetention({
defaultRetention: '365d',
criticalRetention: '7y', // Keep critical logs longer
archiveAfter: '90d',
archiveDestination: 's3://audit-archive/'
});

Export Logs

CSV Export

const csv = await client.audit.export({
format: 'csv',
startDate: '2024-01-01',
endDate: '2024-01-31',
columns: ['timestamp', 'action', 'userId', 'description']
});

JSON Export

const json = await client.audit.export({
format: 'json',
startDate: '2024-01-01',
endDate: '2024-01-31'
});

Best Practices

1. Regular Reviews

Schedule regular audit log reviews:

// Weekly security review
const weeklyReview = await client.audit.list({
severity: ['warning', 'critical'],
startDate: weekAgo(),
endDate: now()
});

2. Set Up Alerts

Don't just log—alert on suspicious patterns:

// Alert on bulk data access
await client.audit.createAlert({
name: 'Bulk Data Access',
condition: {
action: 'data.export',
threshold: 5,
window: '1h'
},
notify: ['security@company.com'],
severity: 'high'
});

// SOX: Alert on after-hours admin activity
await client.audit.createAlert({
name: 'After-Hours Admin Activity',
condition: {
action: 'admin.*',
threshold: 1,
window: '5m'
},
timeWindow: {
mode: 'exclude',
start: '09:00',
end: '18:00',
daysOfWeek: [1, 2, 3, 4, 5],
useUserTimezone: true // Evaluate in each user's local time
},
notify: ['security@company.com'],
severity: 'critical'
});

3. Integrate with SIEM

For enterprise, send logs to your security team:

await client.audit.configureSiemExport({
type: 'webhook',
url: 'https://siem.company.com/ingest',
realtime: true
});

4. Archive for Compliance

Keep logs for compliance requirements:

await client.audit.setRetention({
criticalRetention: '7y' // SOX, HIPAA requirements
});

Next: Explore the Store for pre-built agent templates.