Custom Commands & Tags¶
Armory Bot's custom response system is powered by the /tag and /trigger command groups. Server-level tag settings live on the Tags dashboard page (/dashboard).
TagScript Is Advanced (Read This First)¶
Start with plain tags first
TagScript is intentionally powerful and can get complex fast.
If you are new, build 3-5 plain tags first, then add variables ({user}, {args}), then add logic ({if(...)}), and only then add action blocks ({embed(...)}, {redirect(...)}, etc.).
Suggested learning path:
- Plain text tags (
/tag create,/tag get) - Basic variables (
{user},{server},{args}) - Input handling (
{arg(1):fallback}) - Logic (
{if(...)},{or(...)},{and(...)}) - Actions and embeds (
{embed(...)},{react:...},{dm})
What You Get¶
- Reusable text responses (
/tag create,/tag get) - Alias names for tags (
/tag alias) - TagScript variables, logic, and actions (
/tag syntax) - Autoresponder triggers with six match modes (
/trigger create,edit,delete,list,info,toggle) - Server-level tag settings on the Tags dashboard page (ownership, mod-only creation, cooldown, prefix, limits, log channel)
- Ownership and moderation controls
- Import/export for backup and migration
Core Commands¶
Creation & Usage¶
/tag create <name> <content>/tag get <name> [args]/tag list/tag search <query>/tag random/tag top [limit]
Editing & Maintenance¶
/tag edit <name> <content>/tag editor <name>(modal editor for longer content)/tag append <name> <content>/tag raw <name>/tag info <name>/tag preview <name> [args]/tag delete <name>/tag enable <name>/tag disable <name>
Ownership, Access, Safety¶
/tag claim <name>/tag transfer <name> <new_owner>/tag nsfw <name> <enabled>/tag restrict <name> [allow_role] [deny_role] [allow_channel] [deny_channel] [clear]
Alias & Portability¶
/tag alias <alias_name> [target]/tag export/tag import_tags <file>
Triggers (Autoresponders)¶
A Trigger is a Tag that fires by itself: when a Member's message matches its pattern, the bot posts the response, with the full TagScript engine behind it. Triggers are checked on every message sent in a server channel (not bot messages or DMs).
- At most one Trigger fires per message. If several match, the best match wins; ties go to the more specific pattern, then to the one created first.
- Restrictions and cooldowns work as they do for Tags, including the default cooldown on the Tags dashboard page.
- Only the first 50 Triggers are checked against a message.
Commands¶
| Command | Description |
|---|---|
/trigger create <name> <content> [match_type] [case_sensitive] [threshold] [exclude] |
Create a Trigger. name is the pattern to match and content is the response. |
/trigger edit <name> <content> [exclude] |
Change a Trigger's response. exclude (regex Triggers only): leave it out to keep the current one, or pass an empty value to clear it. |
/trigger delete <name> |
Delete a Trigger |
/trigger list |
List the Server's Triggers with their match type and how often each has fired (shows the first 20) |
/trigger info <name> |
Match type, case sensitivity, enabled state, use count, creator, response length and any cooldowns |
/trigger toggle <name> <enabled> |
Turn a Trigger on or off without deleting it |
/trigger edit changes the response only. To change the pattern or match type, delete the Trigger and create it again.
Match types¶
match_type |
Fires when the message... |
|---|---|
| Contains (default) | has the pattern anywhere in it |
| Exact | is the pattern and nothing else |
| Starts with | begins with the pattern (the rest of the message is passed to the response as its arguments) |
| Ends with | ends with the pattern |
| Regex | matches the regular expression |
| Keywords (loose match) | contains enough of the pattern's important words, in any order |
Matching ignores case unless you set case_sensitive to true.
Keywords is for questions people phrase a hundred ways. The pattern how do I claim my bounty is reduced to its meaningful words (small words like "how", "do", "I" and "my" are dropped, and simple plurals are folded so reports matches report). threshold (1 to 100, default 100) is the percentage of those words the message must contain: at 100 all of them, at 50 half of them.
Regex patterns use a fast, safe engine that cannot be slowed down by a hostile message, so a few features are not available: no backreferences and no lookaround. Patterns are limited to 200 characters, and \w, \d and \b match ASCII characters only. Use exclude for "fire unless": a second regex that cancels the Trigger when it also matches.
Example¶
/trigger create name:"how do I claim my bounty" content:"Use /bounties to see the board, then press Claim." match_type:Keywords threshold:75
/trigger create name:"\bfree nitro\b" content:"{user}, that link is a scam." match_type:Regex exclude:"report"
/trigger toggle name:"free nitro" enabled:false
Permissions¶
The /trigger group is hidden from members without Manage Server, and every command needs the tags permission category (or Manage Server).
Tag Alias Behavior¶
Use /tag alias for both create and delete:
To remove an alias, call the same command without target:
Best-practice alias pattern:
- Keep one canonical tag name (
server_rules) - Add short aliases (
rules,r,policy) - Keep aliases stable and update the canonical tag only
TagScript & Variables¶
Use /tag syntax to view built-in TagScript help pages.
Syntax Rules That Matter¶
- Block:
{block} - Block with parameter:
{block(param)} - Block with payload:
{block:payload} - Dot syntax alias:
{user.id}is equivalent to{user(id)} - Nested blocks are allowed:
{if({argslen}>0):...|...} - Escape literal braces with
\{and\}
Runtime Safety Limits (Important)¶
- Max recursion depth:
15 - Max output length:
4000characters - Max block evaluations per run:
500 - Max execution time: about
200ms
If your tag gets cut off or behaves strangely, simplify nesting and reduce repeated blocks.
Top 100 TagScript Variables/Blocks¶
Open dictionary (100 entries)
This list is designed as a compact, in-page quick reference. Switch tabs to move through pages.
| # | Token | What it gives you | Typical use |
|---|---|---|---|
| 1 | {args} |
Full argument string | Free-form input |
| 2 | {arg(1)} |
First argument | Required first value |
| 3 | {arg(2)} |
Second argument | Optional second value |
| 4 | {arg(1):fallback} |
First arg or fallback | Safe defaults |
| 5 | {argslen} |
Number of args | Branch on input count |
| 6 | {user} |
Invoker display name | Basic greeting |
| 7 | {user(id)} |
Invoker user ID | Logging/tracking text |
| 8 | {user(mention)} |
User mention | Ping in responses |
| 9 | {user(name)} |
Username | Plain identity |
| 10 | {user(username)} |
Username alias | Legacy compatibility |
| 11 | {user(nick)} |
Guild nickname or name | Community-friendly naming |
| 12 | {user(nickname)} |
Nickname alias | Legacy compatibility |
| 13 | {user(discriminator)} |
User discriminator | Legacy formatting |
| 14 | {user(avatar)} |
Avatar URL | Embed thumbnails |
| 15 | {user(created_at)} |
Account creation timestamp | Trust/safety checks |
| 16 | {user(joined_at)} |
Guild join timestamp | Onboarding stats |
| 17 | {user(color)} |
Display color value | Visual metadata |
| 18 | {user(colour)} |
Color alias | Alias compatibility |
| 19 | {user(rolecount)} |
Role count (excluding @everyone) | Member profile cards |
| 20 | {user(top_role)} |
Highest role name | Rank display |
| # | Token | What it gives you | Typical use |
|---|---|---|---|
| 21 | {user(display_name)} |
Display name | Safer than raw username |
| 22 | {user(bot)} |
True/False string |
Bot/human split |
| 23 | {user(timestamp)} |
User creation unix time | Relative time math |
| 24 | {user(joinstamp)} |
Join unix time | Activity window checks |
| 25 | {user(roleids)} |
Space-separated role IDs | Debugging permissions |
| 26 | {user(boost)} |
Boost timestamp | Member perks messaging |
| 27 | {user(timed_out)} |
Timeout expiry timestamp | Moderation context |
| 28 | {user(banner)} |
User banner URL | Rich profile embeds |
| 29 | {target} |
Mentioned user (fallback: invoker) | Utility tags on others |
| 30 | {target(name)} |
Target username | Contextual responses |
| 31 | {author} |
Alias of {user} |
Template compatibility |
| 32 | {mention} |
Invoker mention | Fast ping shortcut |
| 33 | {server} |
Server name | Headers and intros |
| 34 | {server(id)} |
Server ID | Audit/debug output |
| 35 | {server(name)} |
Server name | Explicit server naming |
| 36 | {server(icon)} |
Server icon URL | Embed branding |
| 37 | {server(members)} |
Member count | Community stats |
| 38 | {server(member_count)} |
Member count alias | Compatibility |
| 39 | {server(creator)} |
Server creator display name | About tags |
| 40 | {server(created_at)} |
Server creation timestamp | History/timeline tags |
| # | Token | What it gives you | Typical use |
|---|---|---|---|
| 41 | {server(roles)} |
Number of roles | Config summary |
| 42 | {server(channels)} |
Number of channels | Server info cards |
| 43 | {server(boosts)} |
Boost count | Nitro progress messaging |
| 44 | {server(boosters)} |
Boost count alias | Compatibility |
| 45 | {server(boost_level)} |
Boost tier | Perk tier display |
| 46 | {server(description)} |
Server description | About cards |
| 47 | {server(timestamp)} |
Server unix creation time | Relative-time formatting |
| 48 | {server(humans)} |
Human member count | Bot/human ratio tags |
| 49 | {server(bots)} |
Bot count | Diagnostics |
| 50 | {server(vanity)} |
Vanity invite code | Promotion tags |
| 51 | {server(creator_id)} |
Creator user ID | Staff automation |
| 52 | {server(mfa)} |
MFA level value | Security summaries |
| 53 | {server(banner)} |
Banner URL | Embed hero image |
| 54 | {server(splash)} |
Invite splash URL | Visual cards |
| 55 | {server(discovery_splash)} |
Discovery splash URL | Discovery metadata |
| 56 | {server(random)} |
Random member display name | Fun/random tags |
| 57 | {channel} |
Current channel name | Scoped instructions |
| 58 | {channel(id)} |
Current channel ID | Debug text |
| 59 | {channel(mention)} |
Channel mention | Navigation prompts |
| 60 | {channel(topic)} |
Channel topic | Topic mirrors |
| # | Token | What it gives you | Typical use |
|---|---|---|---|
| 61 | {channel(created_at)} |
Channel creation timestamp | Channel history tags |
| 62 | {channel(timestamp)} |
Channel unix creation time | Relative time |
| 63 | {channel(nsfw)} |
NSFW state string | Conditional messaging |
| 64 | {channel(slowmode)} |
Slowmode seconds | Channel diagnostics |
| 65 | {channel(category_id)} |
Parent category ID | Routing/debugging |
| 66 | {channel(jump_url)} |
Link to the channel | Shareable references |
| 67 | {tag} |
Current tag name | Self-referential tags |
| 68 | {tag(name)} |
Current tag name | Explicit metadata |
| 69 | {tag(author)} |
Tag author user ID | Ownership display |
| 70 | {tag(uses)} |
Tag usage count | Popularity counters |
| 71 | {uses} |
Tag usage count | Shortcut stats |
| 72 | {unix} |
Current unix timestamp | Time-based logic |
| 73 | {let(name):value} |
Set variable | Save computed values |
| 74 | {=(name):value} |
Alias of let |
Legacy templates |
| 75 | {var(name)} |
Get variable | Reuse values |
| 76 | {var(name):fallback} |
Get variable or fallback | Error-proof templates |
| 77 | {if(a==b):then\|else} |
Conditional branch | Dynamic responses |
| 78 | {or(a\|b):then\|else} |
True if any condition is true | Multi-condition checks |
| 79 | {and(a\|b):then\|else} |
True if all conditions are true | Gate workflows |
| 80 | {not(value):then\|else} |
Invert truthiness | Negative checks |
| # | Token | What it gives you | Typical use |
|---|---|---|---|
| 81 | {any(x):a\|b\|c} |
true if x matches any item |
Whitelist checks |
| 82 | {all(x):a\|b\|c} |
true if x matches all items |
Strict equality checks |
| 83 | {break(condition):message} |
Stop execution with message | Guardrails |
| 84 | {stop(condition):message} |
Alias of break |
Compatibility |
| 85 | {choose:a\|b\|c} |
Random option | Random responses |
| 86 | {random:a\|b\|c} |
Alias of choose |
Compatibility |
| 87 | {50:text} |
50% chance output | Lightweight RNG behavior |
| 88 | {range(1-100)} |
Random integer in range | Dice rolls |
| 89 | {rangef(1-10)} |
Random float in range | Random decimal values |
| 90 | {math:1+2} |
Safe arithmetic evaluation | Numeric templates |
| 91 | {calc:1+2} |
Alias of math |
Compatibility |
| 92 | {round(2):3.1415} |
Rounded number | Currency/ratio formatting |
| 93 | {abs:-5} |
Absolute value | Normalizing numbers |
| 94 | {trunc:3.9} |
Integer truncation | Whole-number output |
| 95 | {lower:TEXT} |
Lowercased text | Case normalization |
| 96 | {upper:text} |
Uppercased text | Emphasis formatting |
| 97 | {title:some text} |
Title-cased text | Headline formatting |
| 98 | {replace(old,new):text} |
Replace substring | Cleanup/sanitization |
| 99 | {length:text} |
Text length | Validation-style checks |
| 100 | {slice(0,5):hello world} |
Substring extraction | Preview/snippet tags |
Action Blocks You Will Use After Variables¶
These are not included in the 100-item variable dictionary above, but they are critical for advanced tags.
| Block | Purpose |
|---|---|
{embed(title):...} |
Set embed title |
{embed(description):...} |
Set embed description |
{embed(color):#ff8800} |
Set embed color |
{embed(field):Name\|Value\|true} |
Add embed field |
{embed(author):Name\|IconURL\|URL} |
Set embed author |
{embed(footer):Text\|IconURL} |
Set embed footer |
{embed(image):URL} |
Set embed image |
{embed(thumbnail):URL} |
Set embed thumbnail |
{embed(url):URL} |
Set embed title URL |
{embed(timestamp)} |
Add current timestamp |
{react::smile:\|:fire:} |
Add reactions (up to 5) |
{delete} |
Delete invoking message |
{dm} |
Send output in DM |
{silent} |
Suppress text output |
{redirect(123456789012345678)} |
Send output to another channel |
{reply} |
Reply to invoking message |
{override:text} |
Replace entire output body |
{allowedmentions(everyone):false} |
Control mention scope |
{require(role_id):error} |
Require role before continuing |
{blacklist(role_id):error} |
Block role from continuing |
{cooldown(30)} |
Set per-user cooldown for this run |
{strf(%Y-%m-%d %H:%M)} |
Format current UTC time |
Best-Practice Implementation Patterns¶
- Start with text-only output, then add one advanced block at a time.
- Always provide fallbacks for inputs: use
{arg(1):default}and{var(name):fallback}. - Keep one tag responsible for one job. Split giant workflows into multiple tags + aliases.
- Prefer explicit checks (
{if({argslen}>=1):...|...}) over implicit truthiness. - Use
/tag previewafter each change, not after ten changes. - Keep content under readable limits. Move very long templates into
/tag editor. - Use
{break(...)}early to fail fast with useful error messages. - Build embeds incrementally (
title->description->fields) to simplify debugging.
Practical Examples¶
Welcome Tag¶
Rules Shortcut¶
Support Response with Arguments¶
/tag create helpdesk Hello {user}, your request is: {arg(1):No details provided}.
/tag get helpdesk args:"Need role access"
Role-Gated Tag¶
/tag create staffnote {require(123456789012345678):You need the Staff role.}Internal note for {user}.
Embed-Based Announcement¶
/tag create announce {embed(title):Server Update}{embed(description):{arg(1):No details provided}}{embed(color):#2e7d32}{silent}
/tag get announce args:"Maintenance starts in 10 minutes."
Randomized Fun Response¶
Permissions Model¶
- Tag creators can edit/delete their own tags.
- Moderators/admins can manage any tag.
- Access restrictions can be applied per role or per channel.
- NSFW tags are blocked outside NSFW channels.
Troubleshooting¶
Tag not found¶
- Verify the exact tag name.
- Check
/tag listand/tag search. - If using an alias, confirm it with
/tag info <name>.
Alias not resolving¶
- Recreate the alias with
/tag alias alias_name:<name> target:<tag>. - Ensure the target tag exists and is enabled.
Tag output is not what you expect¶
- Test with
/tag preview <name>. - Inspect source with
/tag raw <name>. - Check syntax with
/tag syntax. - Replace nested sections with static text, then re-add one block at a time.
Permission denied¶
- Confirm whether the tag has role/channel restrictions.
- Check whether your role can use restricted tags.
- If using
{require(...)}or{blacklist(...)}, verify role IDs are correct.
Output gets cut off or partially renders¶
- Reduce nested block depth.
- Reduce repeated block calls.
- Shorten output and split into multiple tags when needed.
Data Backup¶
Use /tag export regularly for backups, and /tag import_tags to restore or migrate tag sets.
Recommended backup routine:
- Export before large edits
- Export before moderation/staff handoff
- Keep periodic snapshots for rollback