Concepts
Village and invite codes
A Village is one instance of AgentsVille. Everything a Player creates — NPCs, Conversations, Skills, Memories, MCP Servers, Connectors — lives in exactly one Village, and Village-wide settings apply to every NPC inside it.
There is no second Village on the same deployment. One deployment, one Village, one
Operator, one .env file. If you want two, you run two.
One Village, not many
AgentsVille deliberately does not do multi-tenancy. There is no tenant routing, no
cross-Village isolation to configure, and no per-tenant keys to manage. That is
what makes the self-hosted story simple: the provider keys in the .env file
are the keys every NPC on the instance runs on, and the person who holds that
file is the person who carries the bill.
What is shared across the Village:
- The default Provider and Model, which any NPC can inherit or override.
- The Party hop limit.
- Templates, which ship with the instance.
What is not shared: a Player's NPCs, Conversations, Skills and Memories, which belong to the Player who created them. A "Village-scoped" Skill or Memory means "every NPC I own", not "every NPC on the instance".
Invite codes
Registration is closed by default. To register, a person must present an
Invite Code. The first is a secret the Operator sets in the root .env
file:
It must be at least sixteen characters. Generate one rather than inventing one; it is the only thing standing between a public deployment and open registration.
That code is always among the Village's codes, as a row that cannot be deleted. It works without limit until the Operator caps it. Setting its limit to 0 turns it off.
The Operator can make more from Settings, Invite codes. Each has a label, an optional limit on how many people may register with it, and an optional expiry date. A new code is shown once, when it is made; afterwards only its last four characters are kept. A code can be given a new limit later, or deleted, which stops it working for future registrations and leaves the accounts made with it alone.
A person who presents a code that has run out or expired is told so, and to ask the Operator for a new one. A registration that fails for another reason gives its use back.
The code is checked in a preHandler in front of the authentication handler, not
inside it, by looking up a keyed hash (HMAC, keyed with BETTER_AUTH_SECRET) of
the presented code. POST /api/auth/sign-up/email carries its own tight rate
limit of 5 attempts a minute precisely because of that — a secret with unlimited
guesses is not a gate — and any other request on a sign-up path is refused. See ADR 0002
for why the check sits where it does, and
ADR 0036
for the limits.
The code is never stored against a Player
This is the part with consequences.
The Invite Code is presented once, at registration, and then discarded. It is not written to the Player's record, it is not in any session, and it is not recoverable from the database. A code is kept only as a keyed hash and a four-character hint.
That means:
- A code is shared, not personal. Everyone given the same code can register with it until its limit is reached, so give each group its own code and a limit.
- There is no revoking one person's invite. Once a person has registered, the code has done its job. Removing their access means deleting that Player.
- Rotating the
.envcode is an.envchange plus a restart. Existing Players keep their sessions and their work; only future registrations are affected.
Rotate it whenever you have handed it to someone who should no longer be able to bring a friend, and after any Village you suspect has leaked it. See Rotating secrets.
Sharing it
Send the Village's address and the code together, out of band — the same way you would send anyone a password. The person registering enters it on the sign-up form alongside their name, email and password.
The first person to complete registration on a new instance becomes the Operator, so register yourself before you send the code to anybody else.
Next
- Operator and Player — who the first registration makes you.
- Configuration — every variable the
.envfile reads. - Quick start — getting an instance up.