AI assistant
The AI Assistant in an account's panel is an agent that works inside that account, with shell and file access as the account's own user and the panel's operations through its MCP server, and asks the account holder before it changes anything. AI Assistant in the account docs describes what the account holder sees; here is where the model comes from, who pays, and how to turn it off.
The pieces
| Piece | What it is |
|---|---|
| The agent | elpan-ai-agent, a daemon running as its own system user. The panel talks to it over a unix socket; every command and file edit it makes runs as the account's user, in a sandbox, so it can do nothing the account holder could not. |
| The LLM proxy | An OpenAI-compatible endpoint the agent calls for every model request. It decides which real model answers, with which provider key, at what price. The agent never names a model: it asks for one of four aliases by purpose (elpan/main, elpan/summarizer, elpan/classifier, elpan/condenser). |
| The panel | Holds each account's budget, debits the cost the agent reports, stops a conversation when the budget runs out, records every action in the account's audit trail. |
elpan-ai-agent is one of the components a server can be without;
Sizing profiles says which profile leaves it out
and how to add or remove it. Without it the panel shows no Assistant
anywhere. On the tiny and small profiles the agent starts on demand and
exits after 15 minutes idle; the first answer then takes a few seconds.
Connect the proxy
The server's whole LLM configuration is two lines in
/etc/elpan/ai-agent/env:
LLM_BASE_URL=https://<proxy>
LLM_API_KEY=<this server's key>
The base URL is the bare origin, without /v1. The key is this server's
own key on the proxy, never the proxy's master key: one key per server, so
it can be revoked and budgeted on its own. After a change:
systemctl restart elpan-ai-agent.service
The file is root's, readable by the agent, and survives upgrades. The agent refuses to start without a base URL.
The account holder never sees the key: it lives in the daemon's memory and in this file, and the sandbox hides both from the account's user. What a leak exposes is one revocable key with a budget on the proxy, not a provider account.
elpan-llm-proxy
elpan-llm-proxy is a reference implementation of the proxy, not part of the platform: one LiteLLM behind Caddy on a small VPS, with Postgres for its keys and spend. Anything that serves the OpenAI-compatible API with the four aliases, the cost of each reply and a model catalogue works in its place.
On that proxy, ./llmctl key create <server> prints the two lines for a
server's env file; key list shows each server's spend, key revoke
cuts one off, and config.yaml maps each alias to a real model and its
price. Prompts and replies are never logged there. If the proxy is down,
the assistant is down on every server, and nothing else is.
The budget
Each account has an AI cost budget: how much the assistant may spend
for it, in a rate-limiter notation whose tokens are microdollars.
fixed:500000/PT3H,fixed:5000000/P7D is $0.50 every 3 hours and $5 every
7 days. The proxy prices each call; the panel debits the account and
pauses the conversation when the budget is spent, until the window
refills.
An account has no budget until you give it one, and no budget means the assistant is off for that account.
elpanctl account:edit <username> --ai-rate-limit "fixed:500000/PT3H,fixed:5000000/P7D"
elpanctl account:edit <username> --ai-rate-limit default
elpanctl account:edit <username> --ai-rate-limit disabled
elpanctl account:edit <username> --reset-ai-budget
default is fixed:10000/PT24H, one cent a day. disabled bars the
account from the AI features. --reset-ai-budget clears the current
window's usage now, without waiting for it to expire. In the admin app the
same budget is the AI cost budget field of the account form; an empty
field bars the account. See Limits.
Independently of the budget, the agent stops any single run that costs more than $3; the account holder can continue the conversation.
Conversations
The panel keeps every conversation's message log; the agent keeps its own
event history under /var/lib/elpan/ai-agent/persist/, readable by the
daemon only. Both are pruned: the panel deletes conversations with no
activity for two months, nightly, and a daily timer of the agent removes
its history older than 60 days.
elpanctl assistant:conversation:list --account <username> --since "-7 days"
elpanctl assistant:conversation:view <conversation-id>
elpanctl assistant:conversation:view <conversation-id> --payload
elpanctl assistant:conversation:message:view <message-id>
list filters by account, time window (--since, --until) and
--limit; view shows a conversation with a one-line summary of each
event, or the full event payloads with --payload;
message:view shows one message with its payload. What the assistant did
in an account is also in that account's audit trail, like any other
action.