Skip to main content

Expressions

Kite supports performing calculations and transformations on data using expressions. Expressions are available in the Evaluate Expression block (which also supports multi-line input) and in every placeholder surrounded by {{ and }}.

Expression Syntax​

Expressions are powered by the Expr language, you can learn more about the features and syntax here.

Available Variables​

Kite provides the following variables in the expression environment:

user:
id: string
username: string
discriminator: string
display_name: string
avatar_url: string
banner_url: string
mention: string
is_bot: bool
created_at: int # When the account was created, as a Unix timestamp in seconds
role_ids?: []string
nick?: string
# Only filled inside a server
joined_at: int # When the user joined the server, as a Unix timestamp in seconds
top_role: # The highest role of the user, or @everyone without roles
id: string
name: string
mention: string
color: string # Like #5865f2, empty if the role has no color
hoist: bool # Whether the role is shown separately in the member list
mentionable: bool
role_mentions: string # Mentions of all roles of the user, highest first
role_names: string # Names of all roles of the user, highest first, separated by commas
role_count: int
color: string # Color of the highest role that has one, like #5865f2
is_booster: bool
boosting_since: int # Unix timestamp in seconds, 0 if the user isn't boosting
is_timed_out: bool
timeout_until: int # Unix timestamp in seconds, 0 if the user isn't timed out
is_owner: bool # Whether the user owns the server
is_admin: bool # Whether the user owns the server or has the Administrator permission
permissions: []string # Lowercased permission names, like ban_members or manage_messages

message?: # For message events
id: string
channel_id: string
content: string
author: # Same fields as user, empty for reactions and deleted messages
id: string
username: string

channel:
id: string
name: string
mention: string
type: string # text, voice, category, announcement, thread, stage, forum, media, dm, group_dm, or unknown for newer types
category_id: string # Empty outside of a category, for a thread the category of its channel
category_name: string

guild?: # For events and interactions inside a server, elsewhere guild is empty and so are its fields
id: string # The id of the server
name: string
icon_url: string # Empty if the server has no icon
member_count: int
boost_count: int
owner_id: string # The id of the user that owns the server
boost_level: int # 0 to 3
created_at: int # When the server was created, as a Unix timestamp in seconds
banner_url: string # Empty if the server has no banner
description: string
vanity_url: string # The custom invite link, empty if the server has none
role_count: int # Without @everyone
channel_count: int # Without categories and threads
emoji_count: int
rules_channel: # Empty if the server has no rules channel
id: string
name: string
mention: string
system_channel: # Where Discord posts join and boost messages, empty if turned off
id: string
name: string
mention: string

interaction?: # For commands and interactive components
id: string
value?: string # The value of the picked option in a select menu, or the ID of the picked user, role or channel
values?: []string # All picked values or IDs if the select menu allows picking more than one
components?: # For modal submissions, by input identifier
identifier:
value: string # What input('identifier') returns
values: []string # What inputs('identifier') returns

app:
user: # Access the underlying user of the app
id: string
mention: string

There are also a few special variables for accessing dynamic variables:

arg('name') # Access value of a command argument
input('identifier') # Access value of a modal input, the first one if several options were picked
inputs('identifier') # Access all picked options of a modal input as a list
picked('identifier') # Access the member, role or channel picked in a modal select, or the uploaded file, the first one if there are several
pickedAll('identifier') # Access all members, roles or channels picked in a modal select, or all uploaded files, as a list
result('id') # Access the result of a previous block

top_role, role_names, color, is_owner, is_admin and permissions need the roles of the server. They work for user, members from command arguments, and origin.user and previous.user in sub-flows. A member from result('id'), like the result of a Get Member block, or from a variable doesn't know its server, so using them there fails the flow instead of returning a wrong answer. They also fail in a server your app isn't in, where only user-installed commands run.

guild.member_count follows members joining and leaving while your app has a Member Join or Member Leave event listener. Without one, it's the count from when your app last connected to Discord.

In sub-flows, origin and previous give access to the interaction or event from before the sub-flow, e.g. origin.user.id.

Examples​

When using the Evaluate Expression block, you must omit the {{ and }} from the expression.

Get Command Argument​

This will return the value of the myarg argument passed to the command.

{{ arg('myarg') }}

Get User Display Name​

This will return the display name of the user who clicked the button or triggered the command or event.

{{ user.display_name }}

Get Message Content​

This will return the content of the message that was sent.

{{ message.content }}

Check Reaction Emoji​

In a Reaction Add or Reaction Remove event listener, this will return true if the reaction was a 👍. For a custom emoji, compare emoji.id instead.

{{ emoji.name == "👍" }}

Check if User Has Role​

This will return true if the user has the role with the ID 123.

{{ "123" in user.role_ids }}

Get Selected Option​

This will return the value of the option that the user picked in a select menu.

{{ interaction.value }}

If the select menu allows picking more than one option, this will return true if the user picked the option with the value option-a.

{{ "option-a" in interaction.values }}

In a user, role, mentionable or channel select, the values are IDs. This mentions the channel that was picked:

<#{{ interaction.value }}>

Welcome a New Member​

This will greet a member with the name of the server and their member number.

Welcome to {{ guild.name }}, {{ user.mention }}! You're member #{{ guild.member_count }}.

Check Picked Modal Options​

If a modal input with the identifier colors allows picking more than one option, inputs('colors') returns all picked values as a list. This will return true if the user picked red.

{{ 'red' in inputs('colors') }}

This will return how many options were picked.

{{ len(inputs('colors')) }}

And this will list them separated by commas, e.g. red, blue.

{{ join(inputs('colors'), ', ') }}

Use Picked Members, Roles and Channels​

For a user, role, mentionable or channel select in a modal, input(...) and inputs(...) return IDs. picked(...) returns the picked member, role or channel itself, with the same fields as user, a role or channel, and pickedAll(...) all of them as a list. On its own it shows as a mention. If a modal has a user select with the identifier reported, this will name the reported member.

{{ picked('reported').display_name }} was reported by {{ user.display_name }}.

This will list the names of all picked roles, separated by commas.

{{ join(map(pickedAll('roles'), #.name), ', ') }}

For a file upload in a modal, picked(...) returns the uploaded file, which shows as its URL. This will name the file uploaded with the identifier image and its size in bytes.

{{ picked('image').filename }} ({{ picked('image').size }} bytes)

Check User Creation Date​

This will show when the user's account was created, as a Discord timestamp.

<t:{{ user.created_at }}:f>

This will return true if the account is less than 7 days old, which is useful for anti-raid checks. user.joined_at works the same way for how long someone has been in the server.

{{ user.created_at > now().Unix() - 7 * 86400 }}

Only Run in a Category​

This will return true if the command was used in a channel of the category named Tickets. Use channel.category_id instead to keep working when the category is renamed.

{{ channel.category_name == "Tickets" }}

This will return true inside a thread.

{{ channel.type == "thread" }}

Check if User Owns the Server​

This will return true if the user is the owner of the server.

{{ user.is_owner }}

Check the Permissions of a User​

This will return true if the user is allowed to ban members. The names are the permission names of Discord in lowercase.

{{ "ban_members" in user.permissions }}

user.permissions are the permissions the roles of the user give them in the server. Permissions a single channel grants or denies aren't included. Administrators and the owner of the server have every permission, and user.is_admin is true for them.

Point to the Rules Channel​

This will mention the rules channel the server has set in its settings, and is empty if it has none.

Please read {{ guild.rules_channel }} before posting.

Show the Roles of a User​

This will mention the highest role of the user, and then all of their roles.

{{ user.top_role.mention }}
{{ user.role_mentions }}

Do Some Math​

This will return the result of the expression.

{{ 1 + 1 }}

Decode JSON Response​

This will return the value of the somefield field in the JSON response of an HTTP request block with the id owlspush.

{{ result('owlspush').data().somefield }}

Timestamps​

Discord timestamps are shown in the local timezone of whoever reads the message. Wrap a Unix timestamp in <t:...:style> and pick one of the styles below.

<t:{{ now().Unix() }}:t> # Short time, like 5:36 PM
<t:{{ now().Unix() }}:T> # Long time, like 5:36:12 PM
<t:{{ now().Unix() }}:d> # Short date, like 01/02/2026
<t:{{ now().Unix() }}:D> # Long date, like January 2, 2026
<t:{{ now().Unix() }}:f> # Short date and time, like January 2, 2026 5:36 PM
<t:{{ now().Unix() }}:F> # Long date and time, like Friday, January 2, 2026 5:36 PM
<t:{{ now().Unix() }}:R> # Relative time, like 2 minutes ago

This will show a countdown that ends one hour from now.

<t:{{ now().Add(duration("1h")).Unix() }}:R>