Repository navigation
Admin panel and settings
The backend serves a web admin panel, Allay Room, at /admin. There you change every setting, manage admin accounts, and see what the backend does. On a self-hosted backend its sidebar links the project's source, issues, discussions, and releases.
- Questions, cost, players, servers, errors and cancellations, answer times, tokens, web searches, the cost of a question, models, tools, and the busiest players, by day.
- Each run's numbers and the shape of its trace: steps, models, tools and whether they worked, tokens, and timings, with the player and the server it ran on. Since 6.9 the words in a trace are sealed; an owner opens one run with Show text on its page to look into a reported problem, after a confirmation, and every look lands in the audit log.
- The audit log, filtered by area (accounts, settings, players, licenses, payments, opened runs) and by who, with each change as its old and new value.
- With billing on: licenses, payments, revenue, refunds, budgets granted by hand, and blocked licenses. “Refund and revoke” on a license's page returns every payment through the bot, stops its subscription, tells the payer in Telegram, and revokes the license for good: its key answers
LICENSE_INVALID, and the server takes a new license with/allay link. Telegram refunds only whole payments, so there is no partial refund. Delete removes a license and its budget windows; its payments stay. A paid license without a refund sends you to “Refund and revoke” first, and only an owner may delete it anyway, after a warning about the payer's rights and a second agreement.
Nobody sees what players asked, what Allay answered, what tools were given and returned, or what Allay remembers about a player. The backend never sends those to the browser, whatever the role. Since 6.4 the panel names players with the name and UUID of their last question and shows their faces (see Security and privacy).
Statistics come from a runs collection, one document per run with numbers only, kept 730 days, plus daily rollups whose sums stay forever and whose lists of players go after 730 days.
The Servers page lists each Minecraft server with its name (server.name in the plugin's config, Allay 6.5; unique on the backend), its domain (server.address, Allay 6.4), its license, the game software and the plugin's version (Runtime), questions, and when it was last used. Admins also see the IP it connects from; one marked internal reaches the backend over a private network they share, like a plugin on the same machine. Tables never show a MOTD.
Clicking a server opens its page (GET /api/admin/servers/{tenant}/{server id}): its details, its MOTD line by line in a block of its own (the only place the panel shows a MOTD), its license as a button, every player who asked there, and its newest runs. A run names its server as a button too.
With billing on, the Licenses page lists each license by the name its owner gave a server behind it (server.name), else the name the license got at /allay link, else its id, its server and domain, status, plan, paid period, and a budget bar that fills as money goes: a full bar means the limit is spent. A license's page shows its plan (a hand-given budget of Infinity's size counts as Infinity), the paid date with the days left, what's left of the budget now, when it resets with how many days it lasts at the open windows' average spend a day, its details (a budget given by hand stands in for a payment on a license nobody paid for), the servers behind it as cards that open their pages, its budget windows with the same bars, and its payments. Actions are grouped: Budget (grant, extend, and for owners Grant Infinity), Access (block, refund and revoke), and Delete. An owner edits the license's stored name, shown only while none of its servers has a name of its own, and the language the bot writes in (PATCH /api/admin/licenses/{id} with name and language).
Notify license holders, an owner's button on the Licenses page, sends one text through the bot to every license's Telegram chat, 20 a second (POST /api/admin/licenses/notify with { text, licenses? }, up to 3000 characters, optionally only the listed licenses). It answers how many got it, failed, or have no chat yet, and the audit log keeps the counts, not the text. Use it for a breach notice the servers' owners must get without delay (GDPR art. 33(2)).
The Players page lists players with their face, name, servers, questions, errors, tokens, average answer time, cost, language, and first and last question. Players who last asked before 6.4 show their pseudonym until their next question. The search is a dropdown: it takes the start of a name, a UUID, or a pseudonym, picking a player opens them, and Enter filters the table. A player's page adds their UUID, operator status, every server they asked on with their own numbers there, questions by day and by hour, and their kinds of runs, models, and tools.
A player's page has Actions for admins, on one server the player asked on:
-
Clear session: Allay forgets the conversation so far, as after the player's own
/allay new. Memories stay. -
Block and Unblock: a blocked player gets
PLAYER_BLOCKEDon that server until someone unblocks them. Blocked players on the Players page lists every block, erased players too. - Erase: memories, deaths, the player's state, session, agents' threads, and traces go, and runs keep only numbers.
The backend finds who a pseudonym is in the player directory (everyone who asked since 6.4), among the players who agreed to the notice on that server (since 6.1), or among those with memories there. When none knows them, there's no session to clear, and erasing removes what's left: their runs' ties and traces. Erase a player under the list picks the player by name from every server's players, with face, UUID, and server, and still takes a UUID or a pseudonym typed in, with the server to erase them on. Every action lands in the audit log under the pseudonym.
On a self-hosted backend (SELFHOSTED=1, with PLUGIN_TOKEN set in the backend and the plugin):
- In the game, as an operator, run
/allay init. - The plugin shows a link that works once, for 30 minutes. A new
/allay initreplaces a pending link. - Open it: the setup page makes you the panel's owner.
A backend with billing on prints a setup code to its log at start instead.
With ADMIN_USERNAME and ADMIN_PASSWORD (or ADMIN_PASSWORD_HASH) in the environment, that account is the owner, setup is off, and the panel goes straight to sign-in.
- On a self-hosted backend that already has an account, run
/allay initagain. - This time the link opens a recovery page, with the same rules: once, for 30 minutes.
- Enter your name and a new password. Every other session of that account ends, and the audit log notes it.
An owner can also set a new password for anyone on the Accounts page, typed or made with Generate (20 random characters, shown and copied to give to the person). On a backend with billing on, that's the only way back. The environment's admin is the last resort: its password lives in ADMIN_PASSWORD or ADMIN_PASSWORD_HASH, never in the panel.
- Owners do everything, other accounts included.
- Admins change settings and billing, and clear, block, and erase players.
- Viewers only read: pseudonyms and numbers, without players' names, faces, or ids (since 6.9), and without payers' Telegram ids.
Every change lands in the audit log with its old and new value, secrets masked, kept 730 days (365 before 6.9). The API shows only the last four characters of a secret.
A session lasts 7 days from its last use, in an HttpOnly, SameSite=Strict cookie. Sign-in locks for 15 minutes after 5 wrong passwords for one name, or 10 from one address (an IPv6 /64 counts as one). Behind a proxy, set TRUSTED_PROXIES, or every visitor shares the proxy's address.
Each setting shows a plain name next to the name of the environment variable it was before 5.7. Changes apply to the next run, except those marked “after a restart”. A self-hosted backend hides the billing and Telegram groups. The model field marks the recommended model and offers it in one click. The environment card shows where the secrets key comes from with its last four characters, never more.
| Setting | What it does | Default |
|---|---|---|
OPENROUTER_API_KEY |
OpenRouter key for runs on this backend's own key | required for answers |
OPENROUTER_API_URL |
OpenRouter API address | https://openrouter.ai/api/v1 |
OPENROUTER_API_MODEL |
The agent's model; ~anthropic/claude-haiku-latest is the recommended one. It must support tool calling: perplexity/sonar* won't do |
~anthropic/claude-haiku-latest (since 6.9) |
OPENROUTER_REASONING_EFFORT |
How hard a model that reasons thinks: low, medium, high, or unset, which sends nothing, so OpenRouter leaves it to the model and Claude models don't reason at all |
medium (since 6.9) |
OPENROUTER_DATA_COLLECTION |
deny routes requests only to providers that don't store or train on them; allow lets OpenRouter pick any |
deny (since 6.9) |
API_NAME |
The name OpenRouter shows for this backend's requests | allay |
| Setting | What it does | Default |
|---|---|---|
PERPLEXITY_API_KEY |
Perplexity's Search API for web search on the backend's own key | unset, so SEARCH_MODEL searches |
SEARCH_MODEL |
Online model for web search without a Perplexity key, and for servers with their own key | perplexity/sonar |
OPENROUTER_API_CTX |
Search context size of the online model: low, medium, high
|
medium |
| Setting | What it does | Default |
|---|---|---|
TOOL_TIMEOUT_MS |
How long to wait for the plugin's tool result | 15000 |
MAX_AGENT_STEPS |
Model calls per question |
26 (since 6.9) |
MAX_TASK_STEPS |
Model calls per wake of an automation agent |
32 (since 6.9) |
MAX_ACTIVE_RUNS |
Streaming questions at once | 200 |
SSE_PING_MS |
Ping interval that keeps proxies from closing the stream | 15000 |
MEMORY_MAX |
Memories a player may keep, places included. Since 6.9 | 200 |
DEATHS_MAX |
Deaths kept per player, newest first. Since 6.9 | 100 |
CALC_TIMEOUT_MS |
How long exact_calculations gives one expression |
1000 |
| Setting | What it does | Default |
|---|---|---|
CHAT_TTL_SECONDS |
How long a chat session lives after the last question |
2592000, 30 days (since 6.9) |
PUBLIC_CHAT_TTL_SECONDS |
How long a server's thread of public questions lives after the last one | 7200 |
TASK_CHAT_TTL_SECONDS |
How long an automation agent's thread lives after its last wake | 7200 |
CHAT_FOLD_TOKENS |
A session folds into its summary past this many tokens | 32000 |
CHAT_KEEP_TOKENS |
About how many tokens of the newest exchanges stay verbatim after a fold | 12000 |
CHAT_MAX_TOKENS |
Past this many tokens, a session folds before the answer | 42000 |
| Setting | What it does | Default |
|---|---|---|
TRACE_SAMPLE |
The share of runs traced; 0 turns tracing off. After a restart | 1 |
TRACE_DAYS |
How long traces stay, in days. After a restart |
30 (since 6.9) |
| Setting | What it does | Default |
|---|---|---|
PLAN_WEEK_STARS, PLAN_MONTH_STARS, PLAN_YEAR_STARS
|
Prices in Stars. PLAN_STARS=week=1,month=1,year=1 from before 5.7 still sets all three, for a test payment you refund |
150, 500, 10000
|
PLAN_WEEK_BUDGET, PLAN_MONTH_BUDGET, PLAN_YEAR_BUDGET
|
What a period's runs may cost, in US dollars (a year's per 30 days) |
0.75, 3, 6
|
PLAN_INFINITY_BUDGET |
What Infinity's 366 days may cost in all, in US dollars. Never sold: an owner grants it on a license's page. Since 6.9 | 1000 |
BYOK_PER_MINUTE, BYOK_PER_DAY, BYOK_CONCURRENT
|
Limits for a server with its own key, per license |
20, 2000, 4
|
BYOK_ACTIVE_RUNS |
Questions at once from all servers with their own key together, so free servers can't take every slot from paying ones | 100 |
STAR_USD |
What a Star brings in US dollars, for the revenue estimates | 0.013 |
| Setting | What it does | Default |
|---|---|---|
TELEGRAM_BOT_TOKEN |
The payment bot's token; without it there are no payment links | unset |
TELEGRAM_ADMIN_IDS |
Telegram user ids, comma-separated, that may /refund <charge id> in the bot |
unset |
TELEGRAM_WEBHOOK_SECRET |
The webhook's secret token | derived from the bot token |
SUPPORT_CONTACT |
Who to contact for more than the plans give, like @name or an email; the bot shows it under the plans. Since 6.9 |
unset |
TELEGRAM_POLLING |
Take updates by long polling instead of the webhook, for local runs | off |
TELEGRAM_API_URL |
A Bot API server of your own | https://api.telegram.org |
TELEGRAM_TEST_ENV |
Talk to Telegram's test environment | off |
| Setting | What it does | Default |
|---|---|---|
API_URL |
The backend's public address; the Telegram webhook goes to API_URL/api/telegram/webhook
|
https://allay.chat |
PUBLIC_URL |
Where people reach the backend in a browser, with any path prefix. /allay init links and the panel start here |
API_URL |
| Setting | What it does | Default |
|---|---|---|
PLUGIN_TOKEN |
Self-hosted: the token every plugin sends as Authorization: Bearer (server.token in its config.yml), at least 24 characters. Without it the backend answers no plugin |
unset |
TRUSTED_PROXIES |
Addresses and CIDR ranges of the reverse proxies in front of the backend, comma-separated; only their forwarding headers count | unset: nobody |
CLIENT_IP_HEADER |
The header a trusted proxy puts the client's address in: x-forwarded-for, x-real-ip, or cf-connecting-ip
|
x-forwarded-for |
Next: Who pays for the model