Skip to content

The kernel and approvals

Every tool call, from any model and any loop, passes one function in Zyx’s kernel: decide(). It answers allow, refuse, or hold for a person. If it is unsure, it holds. The kernel is plain TypeScript with no AI framework inside it, so a change of model or runtime does not change the rules.

  1. Content (the privacy gate). Every outgoing payload is checked.
    • Passwords and keys are blocked. The token rules come from the open-source gitleaks rule set (220 rules), plus a rule for a random-looking string right after a word like “Passwort” or “Token”.
    • Personal data has Zyx’s own rules: labelled identity fields, IBAN, tax and ID numbers, addresses. Checksums (Luhn, IBAN) cut false alarms. Company register numbers and customer numbers pass.
    • Names in web calls. A small local model (GLiNER multi-PII) reads a web search’s query (the built-in web search and the Brave, Exa, Tavily, Perplexity and Firecrawl search tools), a web fetch’s URL and the URL the browser opens. A private name or address there becomes a card. If the model cannot answer, that is a card too.
  2. Private paths. Zyx’s own state, the secrets file, .ssh, .env files and similar are always refused, never asked.
  3. Folder confinement. A person, a schedule or a trigger reads and writes only the folders it may. A person’s read elsewhere is a card. A scheduled run’s read elsewhere is refused, because nobody is there to answer.
  4. Whose turn. A turn the owner did not start may use only the tools it was granted.
  5. The wall. Every shell command runs in a Docker sandbox, one per session, with nothing of the server in it and no credential. Files cross only through named copy steps. If Docker is down, the command is refused with the fix; there is no fallback to the server itself.
  6. The question: ask or not. Whether a call needs a person is judged per call, by risk.

Sending mail always asks. No rule, no standing approval and no routine turns this card off.

Always a card Judged per call Never allowed
Sending mail everything else that changes something reading keys, .ssh, Zyx’s own state
Anything on the company’s own ask-first list writing outside the allowed folders
A connected app’s tool that sends or pays
Pictures, video and sound from fal.ai (each call, with its price)
Moving a file where more people can read it (the card names them)
git push, merges, unknown GitHub writes
A tool the kernel has never judged
A change in a chat that outside content has reached

The risk judge is a small model. It fails closed: unsure or too slow means ask. The company’s ask-first list is a file the owner edits on the Permissions screen.

A card shows the exact call: what will run, with which input. The owner or the right person presses Approve, and that one call runs at most once. A mail card also offers “Hold, I read it first” and lets the person edit the subject and body before approving; the edited version is what runs. Before the send, the card warns about any address that no source in the chat names: the model may have made it up. A privacy mask such as [REDACTED:phone-de] is never sent; a call that carries one is refused, and the model writes the real value from its source or leaves it out.

Who may decide a card follows the company’s rules: a department’s card goes to its lead, a money threshold goes to the owner, nobody approves their own turn’s card, and a four-eyes class needs a second, different person.

decideResult() checks every tool result before the model sees it or the chat stores it: credentials are blocked, personal data is redacted, and every result from outside (a web page, a mail, an app) is marked as untrusted data. That marking is the defence against a page or a mail telling the model what to do.

Every action that changes something declares how it is undone: exactly, by a compensating action (with its cost shown), or not at all (with the reason shown). A change with no undo answer fails Zyx’s own tests. The History screen lists what can be undone. A sent mail cannot be undone: an approved mail offers no Undo, and its line says so.

Each kind of tool sits on a ladder: shadow, suggest, approve, audit. Clean approvals can promote it; one rejection, undo or bad vote demotes it at once. Sending mail, and anything on the never-auto list, never leaves “approve”. “Not now” on a mail card is no rejection of mail itself: it never switches mail sending off.

A coding job gets its own git worktree and branch, may write only there, and ends in a diff. Pushing is its own card. Zyx never merges; a person does.

Zyx can make a picture, a video or a sound with fal.ai and save it in the company folder. It first offers a free way (Pictures, video and sound). Every paid call is its own approval that shows the price, written as “about”. No standing approval covers it, in a chat or in a routine. A model without a price is refused, so nothing is spent on a guess. The owner sets a monthly budget on the Usage screen. A call that would cross it is refused before a card exists, and two cards approved at once cannot both pass. The prompt goes through the privacy gate first, so personal data never reaches fal.ai.