Skip to content

Your own users

The workspace is the operator’s console. A personal licence admits one address there, and a business licence admits several — but neither is how your users reach you.

For that you branch off a runner: a second agent, with its own engine, that serves outside callers. Through it, unlimited users authenticate for free. No per-user charge, no cap.

your users your app your login, your UI names the user runner agent its own identity the work unlimited users · free · the agent’s licence is the only one

A person can arrive through either, and both derive the same identity. Someone who signs in with your password today and a HexaEight Authenticator tomorrow is the same user to your application — same token, same isolation, same quota.

BYOA — bring your own authalt-auth
who authenticates the personyou do, exactly as you do todaythe HexaEight Authenticator
what you buildyour own frontend and backend, any auth you likea front door against the alt-auth library
what your users donothing newinstall the Authenticator (free) and type a code
what you keepClerk, Auth0, Cognito, your own password tablenothing to keep

Neither needs a licence of its own. The only licence in play is the one your agent already has. There is no per-user cost on either door, and the Authenticator is free for everyone.

The real difference is who carries the friction: with BYOA your users notice nothing and you own the auth; with alt-auth you write almost no auth code and every user installs an app.


This is the first step for most people, and it changes nothing your users can see. Your login, your user records, your sessions, your UI: untouched.

One thing changes. Instead of your backend calling a model provider with a provider key, it calls your agent and names the user:

BEFORE your backend a provider API key the model the key lives in your code

AFTER your backend names the user your agent a route router → model

Two consequences worth being concrete about:

  • The provider key leaves your codebase. It lives in the router instead.
  • Your work gets a per-user identity it can meter and isolate on, without you building one.

The agent verifies your backend. Your backend vouches for the user. That split is the whole mechanism: you are already the authority on who your users are, so nothing asks you to prove it again.

Anything you like. A web app, a mobile app, an internal tool — with whatever login you already have.

The part that holds an identity stays on the licensed machine. That is the whole shape of BYOA, and it is worth drawing before the code:

where it runswhat it is
your licensed machineyour identity agent, the runner branched off it, and the small caller that speaks to the runner. All three share one identity by hardlink, so this is one licence
anywhere you likeyour front end — web app, mobile app, internal tool — with whatever login you already have. It holds no identity and needs no licence. It takes a question and hands it to the caller

So your front end never authenticates to an agent. It collects a question, and the caller on the licensed machine runs the runner once per question, naming the user as it goes. That naming is a vouch, and it is what keeps one person’s conversation out of another’s.

That first hop is yours. How your front end reaches the caller — an HTTP call, a queue, a socket — is ordinary plumbing you write and secure yourself. HexaEight begins at the caller, where an identity exists. If your front end and the caller are on different networks, protect that hop the way you would any other internal API: it carries your users’ questions.

an identityonly on the licensed machine: the agent, the runner and the caller, sharing one set of files
a separate paid licenceno, as long as the identity-holding parts sit on the machine you already licensed
an SDKno. The call is made with the agent binary’s client mode — see Other software calling it

Identity files do not travel. env-file and hexaeight.mac are bound to the machine that activated them, and a hardlink cannot cross machines. If you were to put an identity-holding component on a second server, that server would need its own activation and therefore its own licence. Keeping the runner and its caller on the licensed machine is what avoids that, and it is the arrangement these docs describe throughout.

The caller holds nothing about your users. Your front end passes it the question and who asked, and it calls the runner:

{ "ask": "the user's question", "on_behalf_of": "<sha512 of their email>" }

That is the whole integration. The runner answers; your front end renders it however you want.

No extra licence. Your backend is not separately licensed — the agent’s identity licence, which you already have, is the only one. Nothing about BYOA is charged per user.

Two things to get right:

  • Name the user per request. on_behalf_of is what gives each person their own isolated session, so one user’s conversation never leaks into another’s.
  • The serving agent must be told your backend may speak for that subject. That is a vouch — see Trust and permission.

alt-auth — no password reaches you at all

Section titled “alt-auth — no password reaches you at all”

The second door. A user signs in with the HexaEight Authenticator and you never handle a credential.

You still build the front end. The page has to derive a key and seal a body, so there is a reference browser client that does that part. It is not published yet — coming soon, so until it is, implement the protocol below, which is all it does.

your page POST /external/auth {email} → {session_id, challenge, expires_in: 120}
the agent seals a one-time code to that address
their Authenticator decrypts it and shows it
they type it into your page
your page POST /external/incoming → sealed under a key both sides derived independently

Both calls are made by the page in the browser, to your runner agent. What the client handles is the cryptography; you handle the two fields and the screen.

The protocol, if you are implementing it:

key = SHAKE256("hexaeight.external.v1|" + session_id + "|" + CODE) 32 bytes
body = AES-256-GCM(key, fresh 96-bit nonce) tag appended

Both directions are sealed under the same key, so opening the reply proves the agent derived the identical key — not merely that it accepted yours. Never reuse a nonce, and keep the key non-extractable (crypto.subtle with extractable: false) so a script on the page cannot lift it.

The agent successfully opening the request is the authentication. There is no password to check, because there is no password.

Every alt-auth user needs the HexaEight Authenticator — it is how the code reaches them. It is free for everyone, and there is no per-user cost, but it is a real step to ask of your users. That is the trade against BYOA, where they install nothing.

What that buys, precisely:

propertyconsequence
no cookies, everauthentication is the sealed body, so there is no ambient credential a cross-site request could ride. CSRF is structurally absent, not mitigated
sealed both directionsopening the reply proves the agent derived the same key, not merely that it accepted yours
120-second code, three attemptsan unspent code dies fast; three wrong keys end the session permanently
one error for “wrong key” and “no such session”a stranger cannot probe whether a session is live

It does not stop XSS, and nothing in a browser does. What it changes is the blast radius: a script on your page can act as the signed-in user while the tab is open — it could do that anyway by driving the page — but it cannot extract a reusable credential, because there is not one.

Admit one address, or a whole domain:

Terminal window
# one person
hexaeight-activate front-door-policy allow --self --subject [email protected]
# everyone at a domain — this is the one you usually want
hexaeight-activate front-door-policy allow --self --subject '*@yourcompany.com'

--self says the rule is for this agent acting on behalf of the user who signed in — the agent does the work, vouched for that person, rather than the person reaching anything directly. --subject is who may sign in: one address, or a glob for a whole domain.

Until you add a rule, alt-auth is closed and the agent says so at startup:

[frontdoor] NO sign-in rules — alt-auth is CLOSED.

The Authenticator your users install is the HexaEight one. A white-labelled app under your own brand is possible and is an enterprise arrangement — it carries a cost, so contact support if you need it.

The agent token is a different thing. It lets a browser app authenticate to your agent, and it is created in the Authenticator under a resource — see The Authenticator. alt-auth authenticates a person. If you are letting people in, you want alt-auth.


Both doors need an agent to arrive at, and it should not be your workspace agent. A runner is a second agent with its own ports, its own policy store, and one sealed engine — so a caller can ask it to work and cannot ask it for anything else.

Terminal window
hexaeight-activate add-external-agent \
--from /home/you/my-agent \
--dir /home/you/my-runner \
--mission My_Workflow \
--license personal \
--base-port 8930
flagwhat it does
--fromsupplies the identity only — hexaeight.mac and env-file are hardlinked, never copied
--dirthe new runner’s folder
--missionthe one procedure this runner will serve
--base-portits own ports, so it can run beside your workspace agent

It gets its own engine, sealed to that one capability:

[hexaeight-agent] engine 'missionrun-external' runs ONE mission (sealed): My_Workflow
[external] enabled — authenticated:missionrun-external cleartext:OFF

That is the line that matters. If it is absent, the runner is not sealed and a caller can ask it to run whatever they like.

Why a separate agent, and not another engine on the one you have

Section titled “Why a separate agent, and not another engine on the one you have”
blast radiusthe runner’s policy store is its own; admitting a customer there admits them to nothing else
one capabilitya sealed engine serves one procedure. A caller chooses the question, never the method
its own ports and storeit starts, stops and is upgraded without touching your workspace
revocation is localremoving a customer is a rule in the runner’s store

Read this page first, then that one. This page is about letting people in — your users, through your app. Other software calling it is about letting another system call your agent machine-to-machine, and it carries the full provisioning detail, including the parts the tool does not do for you. Both use the same runner; only the caller differs.


Conversation threads do not follow a user across doors automatically. The same person arriving through BYOA and through alt-auth gets two conversations, because the thread id is minted by whoever runs the front end and the transcript is keyed on it.

If you want one thread across both doors, mint the id the same way on both — which you can, because the id is yours.