1 Which agent are you putting up?
Three ways in. All of them end at the same place: one .alive.json package your site will host.
From the shelf
A ready Alive Agent Avatar, already packaged.
Your own package
A .alive.json you exported from a studio.
A joined agent
An .nsv-agent-1.json — face, mind and voice in one document.
+ Choose a tier
The tag has a fifth attribute: tier. It picks how much face you get —
three rungs, from a drawn face to a full 3D body. It is a different door from the two lines
in step 4: a tier’d tag mounts a standard face at that rung and will not wear a package —
set both and the package is refused with remove tier to wear a package. It outranks
type the same way. Leave tier off and nothing changes: a tier-less tag runs
the exact path it always ran and loads nothing new.
light
A lightweight drawn face — head and shoulders in vector art, animated entirely in code. This rung is complete on its own: paste it and a neutral drawn avatar appears.
<script type="module" src="/alive-site/alive-element.js"></script> <netshow-alive tier="light"></netshow-alive>
mid
Live eyes, brows and mouth painted over a base portrait — more lifelike than a drawn face, but the portrait itself only travels inside a package, so read the note below before you paste.
<script type="module" src="/alive-site/alive-element.js"></script> <netshow-alive tier="mid"></netshow-alive>
3d
A full 3D avatar body — the heaviest rung, and the body file it needs also only travels inside a package, so today this one answers with a refusal instead of a face.
<script type="module" src="/alive-site/alive-element.js"></script> <netshow-alive tier="3d"></netshow-alive>
The honest part: what a tier can show depends on the package
Each rung draws on things an avatar package carries — and a tier’d tag takes no package at
all. So today: light works completely, with a neutral face rather than your agent’s.
mid mounts its live features, but the portrait they paint over comes only from a package,
so the features arrive with no photograph behind them. 3d does not mount: the 3D body file
must arrive as package evidence, the box stays empty, and the tag says why in JavaScript —
el.packageStatus reads refused — the ‘3d’ tier (‘live-vrm’)
would not mount here. Nothing above is a prediction; we mounted all three on this build
and watched.
Spelling is exact: lowercase light, mid or 3d. Anything
else — LIGHT, gold, a typo — is not a tier, and the tag quietly behaves
as though the attribute were not there: you get the stock face, and no error tells you so.
measured on this build — three tags mounted in a real browser, plus the two misspellings
+ Remember the viewer’s tier choice
Optional, and off until you paste it. A tag with no tier attribute can
let each visitor pick a rung once and get it back on every page of your site. The tag already knows
how to remember; it only remembers when your own control asks it to — there is no floating
picker, no query string, and nothing writes on its own. Copy this and change the ids to taste:
Want to see it work first? Try the working example — this same control already on a page: pick a face, reload, forget it. Nothing is remembered there until you choose.
<script type="module" src="/alive-site/alive-element.js"></script>
<netshow-alive id="viewer-face"></netshow-alive>
<label>Face:
<select id="tier-pick">
<option value="">— pick a rung —</option>
<option value="light">light</option>
<option value="mid">mid</option>
<option value="3d">3d</option>
</select>
</label>
<button id="tier-forget" type="button">forget my choice</button>
<output id="tier-note"></output>
<script type="module">
await customElements.whenDefined('netshow-alive');
const el = document.getElementById('viewer-face');
const pick = document.getElementById('tier-pick');
const note = document.getElementById('tier-note');
const show = () => {
const c = el.tierChoice; // { source, tier } — the same answer the tag mounts with
pick.value = (c.source === 'stored' || c.source === 'session') ? c.tier : '';
note.textContent =
c.source === 'stored' ? 'remembered for this site: ' + c.tier :
c.source === 'session' ? 'chosen for this page only (this browser would not store it): ' + c.tier :
c.source === 'opt-out' ? 'tier memory is switched off here' :
c.source === 'attribute' ? 'the tier attribute on the tag wins; no choice is consulted' :
'no remembered choice — the default face';
};
pick.addEventListener('change', () => {
if (!pick.value) return show();
const r = el.chooseTier(pick.value);
if (!r.ok) { note.textContent = 'refused: ' + r.reason; return; }
if (!r.stored) { note.textContent = 'applied for this page only — this browser would not store it: ' + r.tier; return; }
show();
});
document.getElementById('tier-forget').addEventListener('click', () => {
const r = el.forgetTier();
if (!r.ok) { note.textContent = 'refused: ' + r.reason; return; }
show();
});
show();
</script>
What you are agreeing to when you paste it
The choice is per site, not per avatar. It lives in the visitor’s own browser under one
key for your whole origin (nsv.tier.choice.v2), so every tier-less
<netshow-alive> on every page of your site follows it. Other sites never see it;
yours cannot see theirs.
A written tier attribute always wins. Any tag that carries tier="…"
— even empty or misspelled — ignores the remembered choice completely. Pin a rung on a tag
and no visitor can move it.
Switching it off: put data-nsv-no-tier-memory on a tag to stop that tag reading
and writing the choice, or on <html> to stop every tag on that page. Under
opt-out chooseTier() answers { ok: false, reason } and writes nothing.
stored: false means this page only. In a private window, a sandboxed frame or a
full quota the browser may refuse the write; the tag still shows the chosen rung for the life of
that page and says so in the return value, but the next page will not remember. The example above
prints that case rather than pretending.
A remembered 3d grants nothing. It walks the same door as
tier="3d": without body evidence it refuses exactly the way the authored attribute
refuses. Memory recalls a preference; it never unlocks a renderer.
Only light, mid and 3d are ever stored; anything else is
refused before a write. This example uses a tag without src: the remembered rung
mounts the standard face at that rung. To see what this browser will do with your tag, paste
your lines into the Snippet Checker — it now says
which rung it remembers, and why.
this exact snippet, pasted verbatim, was driven in a real browser on this build — choose, reload, forget, opt-out, denied storage and a junk value
+ A second door — the branded-base widget
Steps 1–4 ship a sealed package: one .alive.json that
carries a whole appearance and travels anywhere. There is a second path, and it has been
live on four sites for weeks: alive-hybrid-widget.js mounts a
registered branded base by id — no package file at all. Use this one when the
face is yours and lives on this estate; use the package door when the face has to
travel. Both are real; neither replaces the other.
+ A third door — the orb face
Steps 1–4 wear an agent package; the widget wears a registered base. The third
door wears nothing you have to host on this estate: <alive-orb-face> is a
self-contained face that reads one verified .face.zip handed to it in
JavaScript. It creates no session, opens no network, keeps no timer — it is a face and a
volume meter, and it says refused instead of guessing when the package is wrong. Below is the
real element, running on this page.
Until a kit is applied, the element shows its built-in fallback and reports
No local face package applied. Build the starter kit or drop your own
.face.zip and the face wears it right here.
Get the kit
A starter .face.zip (format alive-face-pack-1), built in your browser from the
default theme, verified, then downloaded — the same bytes are applied to the face above.
Or wear your own
Made one with the CLI? Drop it here. The element verifies the archive before it wears it.
Build kits offline
The same packer, on your machine, from a build config
(alive-face-pack-build-1): writes the archive, its manifest and a sha256 beside it.
npm run kit:orb-face -- --config my-face.json --out my-face.face.zip
Your lines for this door
The orb face does not define itself on import, so line 1 is a short module that defines it. Paste both,
then hand the tag your kit: document.querySelector('alive-orb-face').apply(bytes).
<script type="module">
import { defineAliveOrbFaceElement } from "/alive-site/sdk/orb-face/orb-face-element.js";
defineAliveOrbFaceElement();
</script>
<alive-orb-face></alive-orb-face>
Before you ship the two lines from step 4 — check them
Partners paste, and a typo costs an afternoon. The snippet checker runs the estate’s own package gate over your two lines and your JSON in your browser, and names the rule that would refuse them — nothing you paste leaves the page.