Kharat Bot Docs

KAL state

Durable per-script memory: STATE GET/PUT/APPEND/INCREMENT/DECREMENT/DELETE, size limits and rollback semantics.

KAL scripts get durable state β€” a small key/value store that survives restarts and is private to your script on your server. It is the memory that turns one-shot reactions into systems: counters, queues, per-user records.

The six statements#

kal (fragment)
STATE GET "key" INTO target;      // read (also usable as an expression)
STATE PUT "key" = <value>;        // write any JSON-able value
STATE APPEND <value> TO "key";    // push onto a stored array
STATE INCREMENT "key" BY <n>;     // numeric += (missing key counts as 0)
STATE DECREMENT "key" BY <n>;     // numeric -=
STATE DELETE "key";               // remove

Note the word order on APPEND: value first, then TO the key.

A working counter#

kal
KAL VERSION 2.0;
AUTOMATION member_counter {

    CONFIG {
        log_channel: CHANNEL [
            label: "Log channel",
            description: "Where membership changes are posted",
            required: true
        ];
    }

    WHEN EVENT member_join {
        STATE INCREMENT "joins_total" BY 1;
        DECLARE total = STATE GET "joins_total";
        SEND MESSAGE "Member #" + ("" + total) + " joined!" TO config.log_channel;
    }
}

Storing structures#

State values are JSON-able: strings, numbers, booleans, arrays and maps.

kal
KAL VERSION 2.0;
AUTOMATION queue_demo {

    WHEN COMMAND queue_add (item AS STRING) {
        STATE APPEND item TO "queue";
        DECLARE queue = STATE GET "queue";
        REPLY "Queue now holds " + ("" + LENGTH(queue)) + " items.";
    }

    WHEN COMMAND queue_reset {
        STATE DELETE "queue";
        REPLY "Queue cleared.";
    }
}

Limits#

RuleValue
Value size2,048 bytes each (JSON-serialised)
Keys per script100
Total per script512 KiB
Key length≀ 256 characters

Exceeding a limit raises a state error at runtime; the write is refused, not truncated.

Scoping and lifetime#

  • State is scoped per server and per script β€” two scripts never see each other's keys, and the same script on two servers has separate state.
  • State survives restarts, toggles and version updates.
  • Deleting or uninstalling the script deletes its state.
  • Kharat itself writes two convenience keys after successful sends: last_message_id and last_channel_id.

Rollback semantics#

Each run's state writes are committed as a unit. If a run crashes β€” budget exceeded, unhandled error β€” the state changes of that run are rolled back. State is never left half-written by a failed run.

Reading with defaults#

A missing key reads as null. Combine with EXISTS/NOT_EXISTS or the increment shortcut:

kal (fragment)
IF NOT_EXISTS(STATE GET "seen:" + member.id) THEN {
    STATE PUT "seen:" + member.id = NOW();
}