Flags
State bits that filter actions and contexts, settable from actions, events, and scripts.
Flags are named booleans that track the current state of a chat. Simple strings: is_thirsty, wears_hat, door_closed. You set them from actions, events, or scripts; you read them from conditions on actions and contexts.
A character with the flag wears_hat set will:
- Have the
wear_hataction filtered out (it's a no-op — they already wear it). - Have the
{{ char }} is wearing a hatcontext render in every prompt.
That's the core loop. Everything else is variations.
Setting and unsetting
A flag is set by including its name. Prefix with ! to unset:
wears_hat # set
!wears_hat # unsetYou can do both in the same effect — e.g. an action that takes off a hat and reveals a hairstyle might set !wears_hat, ponytail_visible.
Enum flags (mutually exclusive)
Some flags are mutually exclusive — a character can be standing OR sitting OR dancing, but not all three. Manually unsetting "all the other poses" every time you change is tedious. Voxta solves this with dot-syntax enum flags:
pose.standing
pose.sitting
pose.dancingSetting pose.dancing automatically unsets pose.standing and pose.sitting. The pose. prefix means "all flags starting with pose. are mutually exclusive."
Unsetting enums
!pose.standing— unsets onlypose.standing. Otherpose.*flags untouched.!pose— unsets allpose.*flags. Useful for resetting a category.
Flag conditions
Conditions are mini JS-like boolean expressions used on actions and contexts.
| Expression | Meaning |
|---|---|
pose.standing | Active only if pose.standing is set. |
!pose.standing | Active only if pose.standing is NOT set. |
pose.standing && !door.closed | Both must hold. |
hold.empty_bottle || hold.empty_glass | Either holds. |
(a || b) && !c | Use parens to group. |
Setting from a script
import { chat } from "@voxta";
export function trigger(e) {
// Set a flag
chat.setFlag('wears_hat');
// Unset
chat.unsetFlag('wears_hat');
// Equivalent:
chat.setFlag('!wears_hat');
// Enum
chat.setFlag('pose.sitting'); // auto-clears pose.standing etc.
// Multiple at once
chat.setFlags('wears_hat', 'pose.standing', '!is_drenched');
// Check
if (chat.hasFlag('wears_hat')) { /* ... */ }
}See Scripting for the full chat-state API.
Expiring flags
Set a flag that auto-clears after a duration:
// Expires after 10 conversation messages
chat.setFlag('cooldown', { messages: 10 });
// Expires after 2 minutes of chat time
chat.setFlag('cooldown', { seconds: 120 });Useful for cooldowns, "just happened" markers, and short-lived emotional states.
Patterns
Once-ever events
Use the Once checkbox on an action — Voxta auto-generates an invisible _action_name flag and an !_action_name condition. Fires once per chat.
State machines
Use enum flags for state machines. state.intro, state.investigation, state.confrontation — only one is set at a time, and transitions are explicit.
Looping events
Set a flag from an event, then use since flag <flag> on the same event with a message-count delta. The event fires, sets its own flag, re-arms, fires again.