Workflow Steps
Workflow steps define the actions that are executed when a workflow is triggered. Each step has a specific type and configuration that determines what it does.
Step Types
Action Steps
Action steps perform operations such as sending commands, logging messages, or making HTTP requests.
RCON Command (rcon_command)
Executes an RCON command on the server.
Configuration:
command(required) - The RCON command to execute
Example:
{
"name": "Broadcast Warning",
"type": "action",
"config": {
"action_type": "rcon_command",
"command": "AdminBroadcast Player ${trigger_event.player_name} has been warned for teamkilling"
}
}Admin Broadcast (admin_broadcast)
Sends a broadcast message visible to all players.
Configuration:
message(required) - The message to broadcast
Example:
{
"name": "Welcome New Player",
"type": "action",
"config": {
"action_type": "admin_broadcast",
"message": "Welcome ${trigger_event.player_name} to our server! Please read the rules."
}
}Chat Message (chat_message)
Sends a private chat message to a specific player.
Configuration:
target_player(required) - Player ID (Steam ID or player name) to send message tomessage(required) - The chat message to send
Example:
{
"name": "Auto Reply to Help",
"type": "action",
"config": {
"action_type": "chat_message",
"target_player": "${trigger_event.steam_id}",
"message": "Hi ${trigger_event.player_name}! Type !rules for server rules."
}
}Kick Player (kick_player)
Kicks a player from the server.
Configuration:
player_id(required) - Player ID (Steam ID or player name) to kickreason(optional) - Reason for the kick
Example:
{
"name": "Kick Teamkiller",
"type": "action",
"config": {
"action_type": "kick_player",
"player_id": "${trigger_event.steam_id}",
"reason": "Repeated teamkilling"
}
}Ban Player (ban_player)
Bans a player from the server.
Configuration:
player_id(required) - Player ID (Steam ID or player name) to banduration(required) - Ban duration in days (0 = permanent)reason(optional) - Reason for the ban
Example:
{
"name": "Ban Cheater",
"type": "action",
"config": {
"action_type": "ban_player",
"player_id": "${trigger_event.steam_id}",
"duration": 7,
"reason": "Cheating detected"
}
}Warn Player (warn_player)
Sends a warning message to a specific player.
Configuration:
player_id(required) - Player ID (Steam ID or player name) to warnmessage(required) - Warning message
Example:
{
"name": "Warn Teamkiller",
"type": "action",
"config": {
"action_type": "warn_player",
"player_id": "${trigger_event.steam_id}",
"message": "Warning: Teamkilling is against server rules. Next violation will result in a kick."
}
}HTTP Request (http_request)
Makes an HTTP request to an external service.
Configuration:
url(required) - The URL to send the request tomethod(optional) - HTTP method (GET, POST, PUT, DELETE) - defaults to GETbody(optional) - Request body for POST/PUT requestsheaders(optional) - HTTP headers as key-value objectfail_on_error(optional) - Whether to fail the workflow on non-2xx status codes
Example:
{
"name": "Notify External API",
"type": "action",
"config": {
"action_type": "http_request",
"url": "https://api.example.com/events",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer ${webhook_token}"
},
"body": "{\"event\": \"player_joined\", \"player\": \"${trigger_event.player_name}\"}",
"fail_on_error": true
}
}Webhook (webhook)
Sends a webhook notification with workflow and event data.
Configuration:
url(required) - Webhook URLpayload(optional) - Custom payload data to include (merged with default data)headers(optional) - Custom HTTP headers
Default Payload Data:
The webhook automatically includes:
workflow_id- Current workflow IDexecution_id- Current execution IDserver_id- Server IDtrigger_event- Full trigger event datavariables- Current workflow variablesmetadata- Workflow metadatatimestamp- Unix timestamp
Example:
{
"name": "Discord Notification",
"type": "action",
"config": {
"action_type": "webhook",
"url": "https://discord.com/api/webhooks/...",
"payload": {
"content": "Player **${trigger_event.player_name}** joined the server!",
"custom_field": "additional_data"
},
"headers": {
"Authorization": "Bearer ${webhook_token}"
}
}
}Discord Message (discord_message)
Sends a formatted message to Discord via webhook.
Configuration:
webhook_url(required) - Discord webhook URLmessage(required) - Message content (supports Discord markdown)username(optional) - Custom bot usernameavatar_url(optional) - Custom bot avatar URL
Example:
{
"name": "Discord Admin Alert",
"type": "action",
"config": {
"action_type": "discord_message",
"webhook_url": "https://discord.com/api/webhooks/...",
"message": "🚨 **Admin Alert**: ${trigger_event.player_name} was kicked for teamkilling",
"username": "Squad Aegis",
"avatar_url": "https://example.com/bot-avatar.png"
}
}Log Message (log_message)
Writes a message to the server logs.
Configuration:
message(required) - Message to loglevel(required) - Log level (debug, info, warn, error)
Example:
{
"name": "Log Player Event",
"type": "action",
"config": {
"action_type": "log_message",
"message": "Player ${trigger_event.player_name} triggered workflow ${metadata.workflow_name}",
"level": "info"
}
}Set Variable (set_variable)
Sets or updates a workflow variable.
Configuration:
variable_name(required) - Name of the variablevariable_value(required) - Value to assign
Example:
{
"name": "Track Last Player",
"type": "action",
"config": {
"action_type": "set_variable",
"variable_name": "last_player_name",
"variable_value": "${trigger_event.player_name}"
}
}Lua Script (lua_script)
Executes a custom Lua script with full access to workflow data.
Configuration:
script(required) - Lua script codetimeout_seconds(optional) - Maximum execution time (default: 30)
Available Lua Functions:
- Logging:
log(message),log_debug(message),log_warn(message),log_error(message) - Variables:
set_variable(name, value),get_variable(name) - Utilities:
json_encode(table),json_decode(string),safe_get(table, key, default),to_string(value, default) - RCON Commands:
rcon_execute(command),rcon_kick(player_id, reason),rcon_ban(player_id, duration, reason),rcon_warn(player_id, message),rcon_broadcast(message) - Workflow Data:
workflow.trigger_event,workflow.metadata,workflow.variables,workflow.step_results - Results:
resulttable to store step output
Example:
{
"name": "Advanced Player Analysis",
"type": "action",
"config": {
"action_type": "lua_script",
"script": "-- Get player data\nlocal player_name = workflow.trigger_event.player_name\nlocal damage = workflow.trigger_event.damage or 0\n\n-- Log analysis\nif damage > 50 then\n log_warn(\"High damage teamkill by \" .. player_name .. \": \" .. damage)\n set_variable(\"high_damage_tk_count\", (get_variable(\"high_damage_tk_count\") or 0) + 1)\nelse\n log(\"Low damage incident by \" .. player_name)\nend\n\n-- Store results\nresult.player = player_name\nresult.damage = damage\nresult.severity = damage > 50 and \"high\" or \"low\"",
"timeout_seconds": 10
}
}Condition Steps
Condition steps evaluate expressions and can branch the workflow execution.
Configuration:
- Conditions are configured through the UI with field, operator, and value selections
Variable Steps
Variable steps perform operations on workflow variables.
Configuration:
variable_name(required) - Name of the variable to operate onvariable_value(required) - Value or operation to perform
Delay Steps
Delay steps pause workflow execution for a specified duration.
Configuration:
delay_ms(required) - Delay duration in milliseconds
Example:
{
"name": "Wait 5 Seconds",
"type": "delay",
"config": {
"delay_ms": 5000
}
}Lua Steps
Lua steps are similar to Lua Script actions but are designed for more complex logic and branching.
Configuration:
script(required) - Lua script codetimeout_seconds(optional) - Maximum execution time
Variable Replacement
In most text fields, you can use variable replacement syntax to access dynamic data:
Syntax
${trigger_event.field_name}- Access trigger event data${metadata.field_name}- Access workflow metadata${variable_name}- Access workflow variables
Common Trigger Event Fields
Chat Messages:
${trigger_event.player_name}- Player who sent the message${trigger_event.message}- Message content${trigger_event.chat_type}- Type of chat (ChatAll, ChatTeam, etc.)
Player Events:
${trigger_event.player_name}- Player name${trigger_event.steam_id}- Player's Steam ID${trigger_event.eos_id}- Player's Epic Online Services ID
Admin Events:
${trigger_event.player_name}- Target player name${trigger_event.message}- Admin message or reason
Metadata Fields
${metadata.workflow_name}- Current workflow name${metadata.workflow_id}- Current workflow ID${metadata.execution_id}- Current execution ID${metadata.server_id}- Server ID${metadata.started_at}- Execution start time
Error Handling
Each step can have error handling configuration:
- Action: What to do on error (continue, stop, retry)
- Max Retries: Maximum number of retry attempts
- Retry Delay: Delay between retries in milliseconds
Best Practices
- Use descriptive names for steps to make workflows easier to understand
- Test variable replacement with simple log messages before using in complex actions
- Set appropriate timeouts for Lua scripts and HTTP requests
- Use error handling for steps that might fail (HTTP requests, external services)
- Log important events to help with debugging and monitoring
- Keep Lua scripts simple and well-commented
- Use variables to share data between steps effectively
Example Workflow
Here's a complete example workflow that demonstrates multiple step types:
{
"version": "1.0",
"triggers": [
{
"name": "Teamkill Detection",
"event_type": "LOG_PLAYER_DIED",
"conditions": [
{
"field": "teamkill",
"operator": "equals",
"value": true,
"type": "boolean"
}
],
"enabled": true
}
],
"variables": {
"max_warnings": 3,
"warning_message": "Teamkilling is against server rules!"
},
"steps": [
{
"name": "Log Teamkill Incident",
"type": "action",
"enabled": true,
"config": {
"action_type": "log_message",
"message": "Teamkill detected: ${trigger_event.attacker_name} killed ${trigger_event.victim_name}",
"level": "warn"
}
},
{
"name": "Analyze Damage",
"type": "lua",
"enabled": true,
"config": {
"script": "local damage = workflow.trigger_event.damage or 0\nlocal attacker = workflow.trigger_event.attacker_name\n\nif damage > 75 then\n log_warn(\"High damage teamkill: \" .. damage)\n set_variable(\"action_required\", \"kick\")\nelse\n log(\"Low damage teamkill: \" .. damage)\n set_variable(\"action_required\", \"warn\")\nend\n\nresult.damage = damage\nresult.severity = damage > 75 and \"high\" or \"low\""
}
},
{
"name": "Warn Player",
"type": "action",
"enabled": true,
"config": {
"action_type": "warn_player",
"player_name": "${trigger_event.attacker_name}",
"message": "${warning_message} This was a ${action_required} offense."
}
},
{
"name": "Notify Discord",
"type": "action",
"enabled": true,
"config": {
"action_type": "discord_message",
"webhook_url": "https://discord.com/api/webhooks/...",
"message": "⚠️ **Teamkill Alert**\n**Attacker:** ${trigger_event.attacker_name}\n**Victim:** ${trigger_event.victim_name}\n**Damage:** ${trigger_event.damage}\n**Action:** ${action_required}"
}
}
]
}This workflow demonstrates:
- Logging for audit trail
- Lua script for complex logic
- Variable usage and setting
- Discord integration for notifications
- Variable replacement throughout
Common RCON Commands
AdminBroadcast <message>- Broadcast message to all playersAdminWarn <steam_id> <message>- Send warning to specific playerAdminKick <steam_id> <reason>- Kick player from serverAdminBan <steam_id> <duration> <reason>- Ban player (duration in minutes)AdminForceTeamChange <steam_id>- Force player to switch teamsAdminChangeMap <layer>- Change the current map layerAdminSetMaxNumPlayers <number>- Set maximum player countAdminSlowMo <multiplier>- Change game speed (admin testing)AdminAlwaysValidPlacement <0|1>- Toggle placement validationAdminDisbandSquad <team_id> <squad_id>- Disband a squad
Log Message Actions
Write messages to the server logs with different severity levels.
{
"name": "Log Workflow Event",
"type": "action",
"enabled": true,
"config": {
"action_type": "log_message",
"message": "Player ${trigger_event.player_name} triggered workflow at ${trigger_event.time}",
"level": "info"
}
}Available Log Levels
debug- Debug information for developmentinfo- General information about workflow executionwarn- Warning messages for unusual but non-critical eventserror- Error messages for failed operations
Variable Setting Actions
Set or update workflow variables for state tracking.
{
"name": "Update Help Counter",
"type": "action",
"enabled": true,
"config": {
"action_type": "set_variable",
"variable_name": "help_requests",
"variable_value": "${variables.help_requests + 1}"
}
}Variable Steps (variable)
Variable steps provide a dedicated way to manipulate workflow variables.
Basic Variable Setting
{
"name": "Initialize Counter",
"type": "variable",
"enabled": true,
"config": {
"action_type": "set_variable",
"variable_name": "player_count",
"variable_value": 0
}
}Complex Variable Operations
{
"name": "Track Last Player",
"type": "variable",
"enabled": true,
"config": {
"action_type": "set_variable",
"variable_name": "last_player_info",
"variable_value": {
"name": "${trigger_event.player_name}",
"steam_id": "${trigger_event.steam_id}",
"timestamp": "${trigger_event.time}"
}
}
}Delay Steps (delay)
Delay steps pause workflow execution for a specified duration.
Basic Delay
{
"name": "Wait 5 Seconds",
"type": "delay",
"enabled": true,
"config": {
"delay_ms": 5000
}
}Common Delay Patterns
Player Loading Delay
{
"name": "Wait for Player to Load",
"type": "delay",
"enabled": true,
"config": {
"delay_ms": 10000
}
}Rate Limiting Delay
{
"name": "Rate Limit Commands",
"type": "delay",
"enabled": true,
"config": {
"delay_ms": 2000
}
}Lua Script Steps (lua)
Execute custom Lua scripts for complex logic and data manipulation.
Basic Lua Script
{
"name": "Custom Player Processing",
"type": "lua",
"enabled": true,
"config": {
"script": "local player_name = workflow.trigger_event.player_name\nlog('Player ' .. player_name .. ' triggered workflow')\nworkflow.variables.processed_players = workflow.variables.processed_players + 1"
}
}Advanced Lua Script with Conditionals
{
"name": "Advanced Player Analysis",
"type": "lua",
"enabled": true,
"config": {
"script": "-- Get player info\nlocal player_name = workflow.trigger_event.player_name\nlocal steam_id = workflow.trigger_event.steam_id\n\n-- Check if this is a returning player\nif workflow.variables.known_players == nil then\n workflow.variables.known_players = {}\nend\n\nif workflow.variables.known_players[steam_id] then\n log('Returning player: ' .. player_name)\n set_variable('player_status', 'returning')\nelse\n log('New player: ' .. player_name)\n workflow.variables.known_players[steam_id] = player_name\n set_variable('player_status', 'new')\nend\n\n-- Set result for next steps\nresult.player_type = get_variable('player_status')\nresult.message = 'Processed player: ' .. player_name"
}
}Available Lua Functions
Logging Functions
log(level, message) - Log messages at specified level (debug, info, warn, error)
Variable Functions
set_variable(name, value)- Set a workflow variableget_variable(name)- Get a workflow variable value
Utility Functions
json_encode(table)- Convert Lua table to JSON stringjson_decode(string)- Parse JSON string to Lua table
Access to Workflow Data
workflow.trigger_event- Access to trigger event dataworkflow.variables- Access to workflow variablesworkflow.step_results- Access to previous step resultsworkflow.execution_id- Current execution IDresult- Table to store step results
Condition Steps (condition)
Note: Condition steps are a planned feature for future releases.
Condition steps will allow branching workflow execution based on runtime conditions.
Planned Condition Step Structure
{
"name": "Check Server Population",
"type": "condition",
"enabled": true,
"config": {
"condition": {
"field": "trigger_event.player_count",
"operator": "greater_than",
"value": 50
},
"true_steps": ["high-pop-action"],
"false_steps": ["low-pop-action"]
}
}Error Handling
Configure how steps handle failures and errors.
Step-Level Error Handling
Each step can define its own error handling behavior:
{
"name": "Potentially Failing Operation",
"type": "action",
"enabled": true,
"config": {
"action_type": "rcon_command",
"command": "AdminBroadcast ${trigger_event.player_name} joined!"
},
"on_error": {
"action": "retry",
"max_retries": 3,
"retry_delay_ms": 1000
}
}Available Error Actions
continue- Continue to the next step despite the errorstop- Stop workflow execution immediatelyretry- Retry the failed step with specified parameters
Workflow-Level Error Handling
Set default error handling for the entire workflow:
{
"error_handling": {
"default_action": "continue",
"max_retries": 3,
"retry_delay_ms": 1000
}
}Best Practices for Steps
Naming Conventions
Use clear, descriptive names for steps:
{
"name": "Broadcast Welcome Message to New Player",
"type": "action"
}Logical Grouping
Group related steps together and use consistent naming:
[
{
"id": "validate-player-input",
"name": "Validate Player Input"
},
{
"id": "process-player-command",
"name": "Process Player Command"
},
{
"id": "respond-to-player",
"name": "Send Response to Player"
}
]Error Handling Strategy
Always consider what should happen if a step fails:
- Critical Steps: Use
stopto prevent further execution - Optional Steps: Use
continueto proceed despite failures - Unreliable Steps: Use
retrywith reasonable limits
Variable Management
Keep variable names consistent and meaningful:
{
"config": {
"action_type": "set_variable",
"variable_name": "teamkill_warning_count_player_${trigger_event.steam_id}",
"variable_value": "${variables.teamkill_warning_count_player_${trigger_event.steam_id} + 1}"
}
}Performance Considerations
- Minimize Delays: Only use delays when necessary
- Efficient Lua Scripts: Keep Lua scripts simple and fast
- Conditional Execution: Use conditions to avoid unnecessary processing
- Variable Cleanup: Periodically clean up unused variables
Security Considerations
- Input Validation: Always validate data from trigger events
- Command Injection: Be careful with dynamic RCON commands
- Rate Limiting: Implement delays to prevent spam
- Admin Verification: Verify admin permissions for sensitive operations
Advanced Examples
Multi-Step Player Warning System
{
"steps": [
{
"name": "Check Player Warning Count",
"type": "lua",
"enabled": true,
"config": {
"script": "local steam_id = workflow.trigger_event.steam_id\nlocal warnings = workflow.variables['warnings_' .. steam_id] or 0\nwarnings = warnings + 1\nworkflow.variables['warnings_' .. steam_id] = warnings\nresult.warning_count = warnings\nresult.should_kick = warnings >= 3"
}
},
{
"name": "Send Warning to Player",
"type": "action",
"enabled": true,
"config": {
"action_type": "rcon_command",
"command": "AdminWarn ${trigger_event.steam_id} Warning ${step_results.check-warning-count.warning_count}/3: Please follow server rules!"
}
},
{
"name": "Kick Player if Max Warnings Reached",
"type": "lua",
"enabled": true,
"config": {
"script": "if workflow.step_results['check-warning-count'].should_kick then\n -- This would ideally be a conditional step\n log('Player ' .. workflow.trigger_event.player_name .. ' reached maximum warnings')\nend"
}
}
]
}Dynamic Server Management
{
"steps": [
{
"name": "Get Current Server Status",
"type": "action",
"enabled": true,
"config": {
"action_type": "rcon_command",
"command": "ShowCurrentMap"
}
},
{
"name": "Process Server Information",
"type": "lua",
"enabled": true,
"config": {
"script": "local player_count = workflow.trigger_event.player_count\nlocal peak_hours = workflow.variables.peak_hours or {19, 20, 21, 22}\nlocal current_hour = tonumber(os.date('%H'))\n\nlocal is_peak = false\nfor _, hour in ipairs(peak_hours) do\n if hour == current_hour then\n is_peak = true\n break\n end\nend\n\nresult.is_peak_time = is_peak\nresult.needs_map_rotation = (is_peak and player_count > 60) or (not is_peak and player_count < 20)"
}
},
{
"name": "Rotate Map if Conditions Met",
"type": "lua",
"enabled": true,
"config": {
"script": "if workflow.step_results['process-server-info'].needs_map_rotation then\n local maps = {'Gorodok_RAAS_v1', 'Yehorivka_RAAS_v2', 'Tallil_RAAS_v1'}\n local current_map = workflow.variables.current_map_index or 1\n local next_map = maps[current_map + 1] or maps[1]\n \n workflow.variables.current_map_index = (current_map % #maps) + 1\n result.next_map = next_map\n result.should_rotate = true\nelse\n result.should_rotate = false\nend"
}
}
]
}Last updated on