WhyThe principles and limits that make Metnos a particular kind of assistant.
→
What happensThe complete path of a turn, including denial, recovery and undo.
→
How it is builtCanonical component contracts: schemas, calls, authority and error conditions.
How to use this guide. Read straight through once. On a second pass, use the component links as trapdoors into implementation detail. The overview explains the promise; the component page defines the contract that keeps it.
Part I · Orientation
Know what you are looking at
Purpose first, then design bets, then the small vocabulary used throughout the rest of the guide.
1. What Metnos is
Metnos is a self-hosted architecture for a governed agent. Its
core does not define an application domain: it plans, applies policy, remembers,
synthesizes, isolates and audits. The admitted executor set
defines what a concrete instance can actually do. Executors are small signed
programs, generated or imported only inside a closed vocabulary and orchestrated
by a local-first LLM planner. Frontier models are optional consults, not the
residence of the system.
The name comes from mētis (cunning intelligence) +
noûs (mind). It lives on a machine under your physical and legal
control. The reference instance is reached through Telegram and
the browser (port 8770), and its current executor catalog covers
files, mail, photos, calendars, the web, GitHub and host operations. Those are
uses of that catalog, not limits of Metnos. Change the admitted executors and
enabled skills/backends, and the operational domain changes without changing the
governing architecture.
Metnos corePlanning, policy, memory, synthesis, sandbox, placement and audit. It governs action but does not choose a domain.
+
Admitted executor setThe signed verbs and objects the instance can execute, together with the skills and backends that are enabled.
=
Concrete Metnos instanceHome operations, GitHub maintenance, research, remote systems — or another bounded domain expressed by its catalog.
Scope rule. Mail, photos and calendars do not belong to Metnos itself. They belong to executors in the reference catalog. Maintaining Metnos through GitHub is already a different use of the same architecture.
Figure 1 — Metnos at a glance. The process lives on your machine: channels receive, the mind plans through configured tiers, guards filter, and executors act on enabled backends. Remote providers and the frontier tier are explicit choices.
The identity card
Item
Actual state
Shape
Python ≥ 3.12 process, executor-based microarchitecture, and constrained one-shot planning in the Mētis engine (ch. 5).
Tools
Signed executors in the catalog, plus those synthesized on the fly and those imported behind a gate (ch. 7). All are vectorized: list in, list out. The domain reference provides the user view; current names and counts live in the generated catalog.
Brain
Compatible local or remote LLM endpoints; five abstract tiers fast / middle / wise / creative / frontier (ch. 8). Frontier = cloud opt-in.
Channels
Telegram (outbound long-poll, no open ports) + web on port 8770 (chat and admin dashboards), ch. 11.
Devices
A controlled part of the catalog can run on registered PCs in the same network through metnos-client: the server remains the point of policy, selection, signing and audit; the device runs only executors declared compatible. Detail: remote executors.
Senses
In-process image pipeline: semantics + faces + EXIF in one unified index (ch. 10).
Language
Context per user and per request. Prompts, manifest descriptions, visible messages, and the input lexicon have declared sources and fallbacks. Italian and English are fully supported; adding another language requires translation and testing across all four areas.
License / status
AGPL-3.0; pre-1.0. Public repository: github.com/brunialti/metnos — the public distribution of code and release materials.
2. The three bets
The whole project rests on three architectural bets. They are deliberate
positions, not optimizations: each one reverses a widespread habit of
agent frameworks.
Figure 2 — The three bets. Each one reverses an agent-framework habit: skills imported on trust, cloud-first design, the LLM as an oracle re-rolled every turn.
The comparison, with no discounts
Typical agent framework
Metnos
Tools
Hand-written, imported or generated free-form, then run as-is with the assistant's privileges
Synthesized at runtime too — but from a closed, audited vocabulary: signed, aged, smoke-tested and screened before they can ever run
Safety
Trust the author of the package
Don't trust the package: the package must pass the checks (7-layer gate, ch. 7)
LLM
Often cloud-first
Local first; frontier opt-in
Routing
The model may choose freely among ungoverned tools
A typed pool, grammar, validator, and validity signatures constrain the proposal. A valid cache hit is reproducible; a new LLM proposal may vary (ch. 8)
Output
Free-form, different per tool
Uniform: list in / list out, pipeable between steps (ch. 6)
Undo
Rare or best-effort
First-class: a closed catalog of reverse patterns, moves = COPY-then-DELETE, honest ok_count (ch. 12)
Language
English only, strings in code
Per-user language; prompts, manifests, messages, and lexicon are distinct validated data
Where determinism lives
Metnos does not present model prose as evidence. Prefiltering, grammar,
validation, admission gates, execution, and cache-validity checks are
controlled components under test. When a request has a stored plan that is
still valid, the fast path reuses it without a new model call. When a plan must
be generated, the proposal remains probabilistic but bounded and observable
(ch. 9).
3. The key concepts, in seven cards
Seven words carry the whole document. Defining them now saves you half an
hour of confusion thirty lines from here; each one has its implementation
contract in the component atlas below.
executor — an executable capability: a small program that does
one thing well (read files, send an email, move messages, search photos).
It accepts lists as input and produces lists as output, carries a
manifest that describes it, an Ed25519 signature that authenticates it and a
sandbox profile that confines it. It is the only class of things that
act in the system.
closed vocabulary — every executor is named
verb_object[_qualifier[_descriptor]], composing governed sets of
canonical actions and objects plus qualifiers in four families. It is not an
aesthetic convention: it is the boundary of what the system can name —
and therefore synthesize. New terms enter only through explicit governance
(necessary · general · understandable).
manifest — the TOML identity card of an executor: a description
in prescriptive chapters (SCOPE / PATTERN / NOT / OUT), the argument schema,
affinity keywords, the reversibility pattern, the code digest. It is not
documentation for humans: it is the tool's prompt, written so that a
mid-size LLM uses it well (ch. 6).
synt — the process that brings into existence what the pool cannot
do yet: a cascade of strategies ordered by cost that first composes existing
executors and only as a documented exception generates new code, in five
stages plus a semantic check (ch. 7). It proposes; the human approves.
vaglio — (Italian for «sifting») the filter that always sits
before execution: a deterministic guard (forbidden paths, unrecoverable
commands) followed by a judge that weighs grey-zone operations and, above
threshold, asks the user for explicit confirmation with buttons on the
channel (ch. 12).
mnest · mnestome — a mnest is the thread linking two
executors that were activated together: it is born from context, reinforced
by use, and decays if not reused. The mnestome is the graph of all
mnests: the system's associative memory, on SQLite, curated by a nightly
process (the ager). It gives the planner the intuition of «which
executor usually follows which» (ch. 9).
skill ↔ backend — two orthogonal axes: a skill decides
whether a group of capabilities is active, trusted and configured
(dormant until its prerequisite appears); a backend decides how an
action runs against a concrete service (calendar = local ICS or Google),
chosen by configuration — never by the LLM. The planner never sees the
provider.
The anatomy of a name
The closed vocabulary is the project's most fertile idea: it makes names
composable (the planner can predict what a capability it has never seen
is called), filterable (the prefilter reasons over verb and object) and
synthesizable (synt cannot name anything outside the grammar).
Figure 3 — The anatomy of a name. Four positional levels, the last two optional; the five producer verbs are distinguished by their primary input, so the planner never has to choose among synonyms.
Part II · A request in motion
Follow one turn from words to effects
The layers are easier to understand after watching data, decisions and authority move through them.
4. The layered architecture
Metnos is an onion: the outside talks to the world, the inside executes.
Each layer trusts only the one beneath it, and privileges shrink as you move
toward the core. A request — whether from a user or from a scheduled
task — crosses all of them, in order.
Figure 4 — The seven real layers, with the modules that implement them. The cognitive engine (layer 3) is the heart of chapter 5; the guards (layer 4) sit always between the plan and the effect.
Channels — a channel is an adapter: it converts an external interface (Telegram, browser) into messages and replies. Adding one does not touch the core (ch. 11).
Turn runtime — the shell that measures and orchestrates: per-phase telemetry (intent_ms, prefilter_ms, vaglio_ms, exec_ms), safety caps, logs.
The Mētis engine — plans once, executes deterministically, recovers with judgment, and when there is no way out, says so (ch. 5).
Guards — no bare subprocess, ever: every effect passes through policy, vaglio and sandbox (ch. 12).
Executors and backends — who acts and against what: the skill↔backend separation keeps the provider out of the planner's head; placement then decides whether the executor stays on the server or runs on a registered device (ch. 3 and 6).
Tissues — what survives between turns: associative memory, learned shortcuts, undo history, audit.
5. Anatomy of a multitool turn
If you read only one chapter, read this one. We follow an example request
— «find the spam mails and move them to the trash»
— from entry to answer: four tools chained together, one structured
proposal, and every step measured and annotated.
5.1 The cascade, step by step
The ground rule: the model is the last resort, not the first.
Memory is tried first without an LLM. For a new request, the proposer asks the
model for the whole structured plan. The number of calls depends on candidate
and grammar configuration; execution of the validated plan follows
deterministic rules.
Figure 5 — The anatomy of a multitool turn. Valid shortcuts are tried first; for a new request, the Proposer asks the model for a structured plan and the Validator checks it before execution. Vaglio precedes every step that requires it; the right side shows targeted recovery and the declared dead end.
Literal shortcuts. A closed table recognizes the most common phrases («what time is it») in microseconds. Here: no match.
Intent. One call to the fast tier (reasoning off, ~0.4 s) extracts the canonical verb, the object and keywords. Compound requests become an ordered list of clauses, each with its own pool.
Plan memory. Fastpath L0 reuses an automatically recorded success; Autopath L1 reuses a generalized skeleton confirmed by positive feedback. Both check catalog and pool signatures before a hit. Here: miss, because this is the first time.
Prefilter. The catalog shrinks to the relevant pool for the clause: verb+object match, qualifier bonus, and — to break ties among siblings — the curated affinity bonus (cap +3). All deterministic: same query, same pool, same order.
Mētis Proposer. The wise tier produces the whole structured plan: steps, links, and final message. Depending on configuration it may generate one or more candidates; the GBNF grammar limits available names and deterministic ranking selects the candidate to validate.
Validator. A typecheck of the plan before running it: existing tools, well-formed args, real references. A trivial error costs one re-proposal, not one wrong execution.
Execution. Pure mechanics: for every step the runtime resolves the placeholders, passes through the vaglio, invokes in the sandbox, accumulates the observation. Caps: 12 steps per turn, same executor max 3 times in a row.
Closing. The final message is composed from actual results. If the turn succeeds and is cacheable, L0 records its plan; L1 stores an observation and requires positive feedback before promoting the generalized skeleton.
5.2 The plan: what the model actually proposes
The Proposer does not produce prose: it produces a structured object —
steps, slots to fill (fillers), final message. This is the real plan
for our request:
{
"steps": [
{"tool": "find_messages",
"args": {"folder": "INBOX", "query": "is:unread"}},
{"tool": "classify_entries",
"args": {"from_step": 1, "dimension": "spam"}},
{"tool": "filter_entries",
"args": {"from_step": 2, "where_field": "spam", "where_value": "spam"}},
{"tool": "move_messages",
"args": {"from_step": 3, "dst_folder": "${FILLER:trash_folder}"}}
],
"fillers": {
"trash_folder": {
"prompt": "What is the trash folder called for this account?",
"default": "Trash",
"tier": "fast"
}
},
"final_message": "Moved ${step4.ok_count} mails to the trash."
}
Worth noting: the model does not know the account's trash folder name
— and does not make one up. It declares a slot
(${FILLER:trash_folder}) that the runtime will fill at the right
moment with a cheap micro-call (cached) or with the default.
5.3 Data piping: how the steps talk to each other
Placeholder
What it does
from_step: N
Take the entries produced by step N (1-based) and pass them whole to this step. Lists travel only this way: never pasted back into the prompt.
${stepN.field}
Extract a scalar field from step N's result (nested paths supported). Used mostly in the final message.
${FILLER:name}
A slot filled on the fly by a micro-call to the fast tier (cached) or by the declared default.
${RUNTIME:key}
Turn context, resolved by the runtime: actor (who is speaking), lang, channel.
Figure 6 — The plan of Figure 5 seen as a data flow. Lists stream between steps via from_step; scalars, slots and context pass through typed placeholders that the executor resolves deterministically.
Partial results and limits
If a limit truncates a result by entries, bytes, or steps, the executor
declares it through truncated, used, and
available_total when its contract provides those fields, and the
runtime makes the limit visible in the answer. It may offer to widen a limit
only when technically possible, and never widens it on its own. Presenting a
partial result as complete is an error.
Part III · Acting
Small programs, explicit authority
Executors do the work. Manifests limit it. Policy and placement decide where the work may happen.
6. Executors: vectorized by construction
Every executor accepts a list and returns a
list — even when the list has zero or one element. There is
no *_batch anywhere: the batch version is the executor. It is
the decision that keeps plans short and results composable.
Figure 7 — The vectorized contract. Zero, one or a thousand elements cross the same code; caps are explicit arguments and truncation is declared in the fields, never hidden.
Three conventions follow from the contract, and you will see them everywhere:
entries vs results — whatever enriches or reads a list returns entries (the record schema is preserved, the pipeline can continue); whatever transforms (move, write, delete) returns results (the schema changes: outcomes, not records).
Robustness at the natural-language boundary — 0 as a placeholder means «no limit»; comparisons are case-insensitive by default; on open text domains values with */? are globs, on closed domains (ids, slugs, scopes) matching is strict and exact. LLM biases never turn into silent failures.
Honest counting — ok_count counts the elements that were actually processed. Never declare an outcome that does not match reality.
The manifest: the tool's prompt
Every executor carries a TOML manifest. It is not courtesy documentation:
it is what the planner reads when it decides whether and how to
use the tool — written for a mid-size local LLM, not for a frontier
model. Short sentences, literal examples, defaults spelled out; the
description follows four prescriptive chapters:
The same manifest also declares where the executor may run. The
platforms and [placement] fields prevent sending to Windows
a tool written only for Linux, or running on a PC an executor that has not been
audited for the device. When the chat names a paired PC, the runtime uses those
declarations to choose server or device execution; if the target is not
reachable, the outcome is honest, not a silent fallback.
[description]
en = "SCOPE: search files by pattern in directory.
PATTERN: find_files(base_path=\"/\", patterns=[\"*.jpg\"]).
NOT: list_dirs+filter_entries; get_files (ID lookup).
OUT: entries=[{path,name,type,mime,kind,size,mtime}]."
Figure 8 — One manifest, four consumers: prefilter, planner pool, grammar and undo each read different fields of the same TOML. The digest binds the manifest to the signed code.
One execution policy
Every executor call, local or remote, crosses the same execution engine. In one
place the runtime applies metrics, backpressure, per-resource limits and a cap
derived from the hardware. The default deliberately remains serial and the
cross-executor pool is off: adopting the infrastructure does not change the
order, inputs, outputs or capabilities of existing executors.
Default for every existing and generated executor.
1
Moderate concurrency.
Only after verified equivalence; always within engine and hardware limits.
2
High concurrency.
3
Controlled maximum.
The class measures only a budget: it grants no authority and does not
mean read-only. A future executor that creates or mutates objects may
run concurrently, but it must declare an isolation key, provide the resource
identity, and pass equivalence, collision, idempotency and postcondition tests.
If any evidence is missing, the loader reduces it to class 0.
All three executor-generation paths — Synt proposals, reactive synthesis
and skill generation — also consume one central contract. The local model
may design a rich implementation, but it cannot rewrite identity, lifecycle,
I/O or the initial execution policy. When it parallelizes independent entries,
the worker count comes from the engine and results must return in input order.
Preservation rule. An executor stays serial until it explicitly declares parallel eligibility and passes equivalence testing. Changing the central policy propagates limits and observability to all executors; it never promotes one implicitly.
Remote authority: declared once, consumed three times
A provider name in an argument is data, not permission. For a conforming
executor, remote access exists only when the manifest declares an effective
provider:access capability. A closed when condition can
make that capability active only for the selected backend. Invalid or
non-matching conditions grant nothing.
Final typed invocationclient = "google_workspace" The planner may select a value; it cannot create authority.
One decision, three effectsMount the provider home read-write, enable network, keep execution on the server.
Authority rule. The same effective binding governs credentials, network and placement. Names, suffixes and arbitrary arguments are never independent permission paths for conforming executors.
Execution on the server or on a registered PC
The normal shape remains simple: the plan selects an executor, the runtime sends
it through policy and vaglio, then invokes it in the server sandbox.
Remote executors add one controlled detour: for selected
executors declared portable, the execution point may be a registered PC in the
same LAN or overlay network.
This is not a new channel and not a generic backend. The channel is still
Telegram or web; the backend is still files, mail, calendar or another service.
The remote executor is the place where the small signed program runs.
Metnos keeps on the server the executor choice, policy checks, device registry,
payload signing, timeout and audit.
Figure 8b — A remote executor does not move the mind: it moves only the execution of an admitted executor. The server remains the authority that decides, signs, waits and records.
The choice does not depend on the browser IP address. In the web UI, the
machine opening the page may be the server, another PC on the network, or a
browser behind a proxy; from Telegram there is no local browser at all. Metnos
therefore uses the name of the paired device and anchors it in
the request language: “on the laptop” is a target, “the laptop”
alone is not.
The remote client does not receive general freedom. It polls the server instead
of exposing ports; verifies the server signature before execution; downloads
only signed and compatible executors; writes the result to a local spool before
delivery. If the server is not reachable, it retries delivery without rerunning
the work already done.
The remote client is contained by construction: on Windows the Job Object bounds
duration, memory and process trees; on Linux the sandbox uses bwrap when present.
Remote executors can also perform file-changing operations on the device —
write, move, and delete — under the required safeguards: idempotency, audit,
and device-aware reversibility (deterministic reverse patterns and blob backups
queued to the same device for undo; the known gap being that blob-restore is not
remotable). Executors whose dependencies cannot be resolved on the device stay
server-only.
The operational details — PC pairing, UI installation, heartbeat, signed
queue, per-OS sandboxing and current limits — live in the
remote executors component contract.
7. Synt: the tool factory
When the pool cannot do something, the planner does not improvise code in
the middle of the turn: it hands over to synt, the process that
brings into existence what is missing. It first tries to compose
existing executors; only as a documented exception does it generate a
new one — in five stages, each with its own contract.
Figure 9 — The synthesis pipeline: four procedural stages on the middle tier, the code on the top tier, then independent semantic verification, signature and birth tests. The multi-stage design converges where the single prompt failed.
Two triggers, one cascade
Mode
Trigger
Timing
Reactive
During a turn: the planner finds no executor that satisfies the request.
Synchronous — the user is waiting; composition of existing executors is tried first.
Introvertive
At night, the ager walks the mnestome and finds recurrences and overlapping traces.
Asynchronous, in homeostasis: it currently proposes deduplication only; generalisation and specialisation are not active generators.
In both cases the same rule holds: synt proposes, the human
approves. No self-modification without a filter; every proposal comes
with its rationale, and is reversible.
The 7-layer gate
The same funnel applies to synthesized code and to skills imported
from outside: no package runs on trust.
Figure 10 — The 7-layer gate, identical for synthesized and imported executors: signature, vocabulary, usage quarantine, sandbox, smoke test, semantic verification, audit. Only at the end of the funnel does a package become a trusted executor.
8. Five tiers, governed routing
Tiers are abstract roles, not pinned models:
fast / middle / wise / creative are assignments you bind to whatever endpoint
you have, and frontier is the optional cloud role. Several tiers may
share one endpoint or use separate endpoints: the planner always sees the role.
Tier
Role
Constraint
fast
Short structured decisions: intent, fillers, and bounded reductions.
Configured endpoint; short replies. Mandatory.
middle
Procedural work and intermediate judgments: extraction, classification, and synthesis stages 1-3.
The role's deterministic policy.
wise
The planner and high-fidelity synthesis: whole plans, code, and verification.
The role's deterministic policy.
creative
Divergent proposals and editorial text, including synthesis stage 4.
Separate policy with temperature 0.35.
frontier
An external consult when explicitly requested (e.g. analyzing an issue).
Cloud API, opt-in, with managed fallback if the key is absent.
A tier is not a model
Tiers describe roles and requirements, not a specific model. A GPU or NPU
is not mandatory: an administrator can bind a tier to a CPU endpoint, an
available local model, or an external service where the role permits one. The
quality of the selected model affects planning quality, not installation
validity.
Three controls on variability
An LLM at temperature zero does not automatically make new planning
reproducible. Metnos reduces variability and, more importantly, separates the
probabilistic proposal from deterministic controls before and after it:
Figure 11 — Tiers are roles bound to configured endpoints; controls reduce variability and prevent a structurally invalid proposal from being executed.
Controlled structure
The proposer requests a structured object, uses grammar when configured,
and still applies balanced parsing followed by validation. Unreadable or
non-conforming output is not executed.
Part IV · What surrounds action
Memory, senses, channels and safeguards
These tissues make the executor system useful over time, visible to the user and safe enough to operate.
9. The memory that speeds things up
Metnos trains no models: no fine-tuning, no RLHF. Everything it learns is
inspectable data — plans, traces, shortcuts — and anything
learned can be read, corrected, deleted. The practical effect: the more you
use it, the less it calls the model.
Figure 12 — Reuse without training: L0 records cacheable successes, L1 promotes a generalization after positive feedback, co-activations feed the mnestome, and proposed changes remain under the decision lifecycle.
10. The senses: the image pipeline
To search your photos, Metnos ships nothing to anyone: three
in-process extractors turn every image into three signals —
what is seen, who is there, where and when — fused into one unified
index queried through the ordinary vocabulary.
Figure 13 — The image pipeline uses configured roles for scene semantics and faces, and reads EXIF for place and time. The three signals converge into a unified index queried through an ordinary executor.
A search arrives from the channel like any other request: the planner
composes find_images_indices with the criteria extracted from the
sentence, and the channel shows inline previews. Building the index is a
background job, incremental and restartable, started with a sentence
(«index the photos in…»).
11. The channels: Telegram and web
A channel is an adapter: it converts an external interface into messages
and replies, plus one optional capability — rendering buttons for
confirmations and choices. Two channels come with the install; adding more
does not touch the core.
Figure 14 — The two channels. The browser talks directly to the server on 8770 (streaming chat + dashboards); Telegram works by outbound long-poll, so no open ports and no public IP. Below, the pairing that decides who may speak.
Channel
What it offers
Web :8770
Chat in the browser with streaming replies (SSE), image previews, feedback badges; admin dashboards for proposals, executors, runs, safety and turns. The same API answers JSON or HTML depending on Accept. Admin key auto-created on first start, file with 0600 permissions.
Telegram
Your personal bot: messages, photos, inline buttons for vaglio confirmations and multiple-choice inputs. Pairing via the /pair command and a signed, expiring code.
The Tutor: explaining without executing
Explicit questions about how to use Metnos are intercepted at the shared
HTTP/Telegram boundary, before the planner and without consuming a pending
dialog. The first pass distinguishes explanations, actions, mixed requests,
and intents that are still uncertain. A page name, relative path, or canonical
URL may identify a published source directly; otherwise the configured
embedder compares the question with units in the signed SQLite catalog.
After retrieval, the authenticated principal filters the sources. A signed
source may request only registered, bounded, read-only observations: admitted
executors, services, devices owned by the user, and that user's scheduled
tasks. The local model composes the answer exclusively from this evidence; it
receives no tools and crosses the central llm slot in the serial
class.
If a request also contains a separable action, Tutor answers the informational
part, preserves the operational clause verbatim, and asks whether to hand it to
the ordinary Metnos engine. The handoff is single-use, bound to the user and
conversation, and occurs only after confirmation. Tutor does not execute the
action. Feedback may improve retrieval for that person alone without changing
the planner or its plan caches.
The Tutor boundary
The runtime governs identity, audience, source integrity, the observation
registry, and action handoff. Semantic classification, retrieval, and
composition are used where language variety would make a phrase table brittle.
An invalid catalog, a weak match, or insufficient context produces an explicit
outcome, never an invented capability.
12. Safety and reversibility
Safety is not a module: it is a chain of independent guards, and an action
must pass all of them. And since even the best guard makes mistakes,
the last defense is being able to go back: honest undo, by construction.
Figure 15 — Five guards in series (pairing, policy, vaglio, sandbox, signature+audit) and, below, the safety net: an undo with a closed catalog of reverse patterns, verified copies before any deletion, and honest counts.
Administrative capabilities and their boundary
With the corresponding executor set, a Metnos instance can administer a
machine through the shell, sudo, packages, and mounts. Every
privileged action passes through the vaglio and applicable authorization,
uses the available containment layers, and is recorded. The system skill can
be disabled, preventing Metnos from using these operating-system
capabilities.
Part V · Open the machine
From promises to component contracts
The overview and the implementation model meet here: one map, one worked request and one catalog of deeper contracts.
13. Component atlas
The architecture above says what the system promises. This atlas shows which component owns each promise and where its exact contract lives.
13.1 From overview to component contracts
Metnos architecture has two levels of zoom. The upper level describes the
system as a whole: its layers, organs, laws and ends. It is the path you have
just followed from chapter 1.
The lower level is the set of component deep dives linked below: one HTML
document per component, with the detail needed to write the code without
guessing. Decisions here are not opinions — they are contracts:
data schemas, function signatures, sandbox flags, error conditions. When
the code and the document drift apart, the document wins and the code is
adjusted; or the document is corrected on the spot — never «later».
The rule of life is short: a component is not implemented until
its HTML exists, has been approved, and speaks the same language as the
code already in place.
Check. Before you read on, two points should be obvious:
(a) Level 1 explains what, Level 2 explains how;
(b) Level 2 documents are contracts, not drafts. If either is unclear,
re-read the previous paragraph before continuing.
13.2 Four nouns, now as implementation contracts
Everything in Metnos revolves around four nouns. Defining them now saves
half an hour of confusion thirty lines down.
executor
An executable capability: a small program that does one
thing well (read files, send mail, compute a hash, OCR a PDF, discover
fresh URLs on a site). Every executor takes lists in and returns lists
out; it has a manifest that describes it, an Ed25519 signature that
authenticates it, and a sandbox profile that confines it. Product membership,
origin, and transport remain separate axes. GitHub executors maintained by
Metnos are builtin with handcrafted origin, not imports; the
generated catalog is the single source
for the source-tree domain breakdown.
mnest
The thread that links two executors when the planner has
fired them together. It is not a code pointer, it is a trace: born from
context, reinforced by repetition, decayed when unused.
mnestome
The emergent graph of all mnests. It is the system’s
associative memory: it lives on SQLite, is curated by a nightly process
(the ager), and gives the planner the intuition for «which
executor usually follows which». The Italian counterpart of the term
is mnestoma.
agent runtime
The turn runtime: it receives the request, extracts intent, tries L0/L1
plan memory, and asks the Mētis engine for a structured one-shot plan when
needed. After validation it runs executors in sequence, collects observations,
and applies Vaglio, policy, and sandbox controls to each step.
Check. Try to finish these sentences out loud:
«An e-mail is sent by an…»,
«When two executors often work together, between them a… is born»,
«All these threads together form the…»,
«Who decides the order of the steps is the…».
If you answer executor, mnest, mnestome, agent runtime, you may
proceed.
13.3 The component map
The documented components are organized by role. The diagram
below groups the main nodes by role: thick black border for the central engine,
green shapes for the «services» the engine consults, blue
shapes for the «tissues» that hold state, bronze shapes for
the peripheral organs facing the user and the environment. Arrows show
who calls whom.
Component map. Solid arrow: direct call. Dashed arrow: orientation or read.
Three observations to read the diagram well.
Telos is a soft signal: it guides the components where
it is wired without replacing the request, policy, or capabilities. The
workspace file declares ends and weights; it grants no authority.
Vaglio always runs before execution, never after.
Once an executor has fired, going back is not free: undo exists,
but it costs history and backup blobs.
The executor pool is extensible but governed: Synt first
tries to compose existing capabilities and, when genuinely needed, can
generate a new executor. Naming, manifest, tests, signature, and admission
lifecycle remain mandatory.
13.4 A second worked request
To pin the map down, let’s follow a simple request from inbox to
reply: «move to ~/Archive/2026 the invoice PDFs that
arrived this week».
Channel. Telegram receives the user message. The
daemon checks that the sender is paired with sufficient
authorisation; otherwise the message is silently dropped. Pairing means
«channel + sender ID recognised»: it is obtained by replying
to a signed Ed25519 code with a TTL.
Agent runtime — planning. The runtime extracts
the intent (canonical verb: move; object:
files; criterion: invoice-attached PDFs in the «last
week» window), asks the prefilter to narrow the catalog to relevant
executors, requests a structured plan from the proposer, and validates it
before the first step runs.
Vaglio — guard + judge. Before the executor
fires, Vaglio checks two things: that the path is not forbidden, that
the shell command is not unrecoverable (rm -rf and
friends). For grey-zone operations, policy and the judge determine whether a
human decision is required. If so, the channel shows a localized proposal
that makes the action, target, and relevant consequences recognizable.
Sandbox + executor. The runtime invokes
read_messages inside bwrap with the flags
derived from the manifest. The output comes back as a list of
entries; each entry is a dict with the PDF path and metadata.
Pipe. The next step is move_files; it
takes the previous step’s list via from_step: N.
Ground truth lives in the scratchpad: the planner sees not the whole
list, but a synthetic view large enough to decide.
Mnest + mnestome. The pair
read_messages → move_files reinforces an
existing trace in the graph; if absent, it creates one. The nightly
ager will do upkeep: decay, merges, drops.
Reply. The runtime answers the user via Telegram
with the number of files moved and the first reason for skipping if
any have been left out. The final_answer includes a truncation
marker if the input list had been capped.
Check. Without looking back: who talks to the user?
who decides the sequence? who fires the executors? who checks the
operation is allowed? who remembers that two capabilities went hand in
hand? If your answers are channel, agent runtime, agent runtime,
vaglio, mnestome, the map is yours.
13.5 Canonical component deep dives
Below, the documents are grouped by role. All have an Italian
counterpart at
/it/architecture/.
The engine that plans and executes. Fastpath L0 reuses cacheable successes recorded automatically; Autopath L1 reuses generalized skeletons confirmed by positive feedback. Catalog and pool signatures are checked before every hit. For a new plan, the Proposer produces one or more structured candidates according to configuration, the Validator checks them, the Executor runs the admitted plan, and recovery or termination reports the outcome without inventing it.
Turn orchestration: channel and identity, intent extraction, dispatch to the one-shot engine, data flow between steps (from_step: int for lists and placeholders for scalars), suspended dialogs, scratchpad, telemetry, and mnestome hooks.
GBNF-constrained generation when enabled: a discriminated union of name and arguments, recursive schema, and contextual pool filter. The post-decode validator remains mandatory and rejects inconsistent combinations.
Two layers before the proposer. L0 stores the complete plan of a successful turn: a fingerprint serves the same request, while the configured embedder may match only generalizable frameworks. L1 stores a related cluster's skeleton and becomes active after positive feedback. Both validate current world signatures; requests with content-specific arguments remain exact-match only.
Local pre-planner guide: compiles admitted manifests, runtime registries, published documentation, and curated procedures into a signed catalog. It also recognizes public sources by filename, may add typed current observations, and hands an action clause to the engine only after confirmation. Feedback refines retrieval for one user without entering plan caches.
Configuration of IMAP/SMTP mailboxes, including non-Google providers: encrypted bindings, multiple accounts, env-file compatibility, and the boundary with Gmail-specific features.
Unified change lifecycle: one change_intent object, one state machine, and the /admin/changes UI. Active adapters are telos, introspective, synt, and user feedback. The daily materializer deduplicates sources; the applier processes accepted records every ten minutes; the daily observer measures effects and finalizes or rolls them back according to kind.
How Metnos assigns the llm, embedder, and vlm roles to providers configured through {llm,embedding,vlm}_tiers.toml. Consumers request a function rather than a concrete brand or model, so local or HTTP backends can change without rewriting the planner or Tutor.
Anatomy of an executor: TOML manifest, Ed25519 signature, sandbox profile, lifecycle, and vector contract (list-in, list-out). The current count lives in the generated catalog rather than this prose.
Inventory generated from signed manifests: every first-party executor grouped by canonical domain, with purpose, criticality, platforms, and source location.
How a controlled part of the executor catalog can run on registered devices: metnos-client, device pairing, manifest placement, per-OS sandboxing, UI installation and explicit Windows/Linux limits.
Narrow-mandate agents behind a regular executor contract: bounded adaptive loops, deterministic resolvers before models, unchanged authority, and verifiable postconditions. login_sites is the first example.
How new executors are born: a five-stage pipeline (naming, signature, tests, description, code), a reactive cascade (compose → generate), and introspective maintenance currently limited to deduplication.
Acquires local, agentskills.io, or GitHub skills and turns them into Metnos executors through parsing, closed-vocabulary translation, generation, admission, signing, and registration. The skill_vocab_map.json table and verb boundary guide translation; commands are metnos-skills import|list|uninstall|status|evaluate.
Why skills and backends are two orthogonal axes: the backend says HOW you run a verb_object (configuration, backend_resolver, invisible to the LLM), the skill says WHETHER/WHICH capabilities are unlocked (activation, dormancy, sandbox). Three tiers (core / first_party / imported), multi-provider architecture transparent to the planner, promotion with a one-off frontier.
bwrap profile derived from the manifest: read-only mount of the code, network isolation if no capability requires it, graceful fallback if bwrap is missing. Landlock deferred.
Common channel adapter (Protocol with send / poll) and the TelegramChannel implementation, with long polling, persistent last_update_id, a daemon, and a systemd user unit. Multi-user delivery uses send_to(chat_id, OutboundMessage); /start <token> pairs a guest.
Second HTTP server (port 8770): uniform agent channel on POST /agent/turn (SSE + JSON), /admin dashboard in htmx + Jinja2 + uPlot, user management, introvertiva proposals, scheduler runs. Auth via admin key (7-day cookie) or device Bearer.
Two paths: /pair with TTL-bound signed Ed25519 codes for technical devices, and /start <token> short-lived for family/guests (multi-user). Registry users.db with host + guests, user_channels, resolve_recipients. Host bootstrap on first run.
Confirmation flow in web chat and Telegram. Its public contract is semantic rather than a fixed number of lines or buttons: it identifies the action, purpose, and relevant consequences; preserves the user's language and identity; and never turns one confirmation into an implicit persistent grant.
Static HTML dashboard aggregating Metnos’s data sources (mnestome, pairings, turns, Vaglio decisions, scheduler). Generated on demand: no live server, no JavaScript.
The user’s ultimate ends, the alignment function, the bother budget with scheduler quotas, the non-renunciation telos (t.coltivazione_strumenti) and the stop clause. The TELOS.md file lives in the workspace.
13.6 Vocabulary and primitives
The closed vocabulary stands at 26 actions
(read, write, move, delete, create, find, list, filter, sort,
group, classify, get, set, send, describe, render, extract, compress,
compute, compare, change, order, share, open, login, act) and
27 objects
(files, dirs, packages, messages, events, contacts,
places, processes, urls, numbers, images, signatures, texts, proposals,
persons, tasks, inputs, approval, credentials, issues, pulls, calendars,
entries, lists, skills, sites, preferences). Qualifiers come in four
families: format/encoding, modality, safety policy, and provider (for
specific non-default backends like _google_workspace).
Centralised in runtime/vocab.py.
The planner currently exposes nine consumers for lists of entries. The five
structural or numeric operators are
filter_entries,
filter_lists, sort_entries,
group_entries, and compute_entries. The four
in-process semantic helpers are
classify_entries,
compare_entries, extract_entries, and
describe_entries. The first group filters one list, combines
two lists, sorts, merges/deduplicates, or computes an aggregate; the second
classifies, compares semantically, extracts structured records, or summarizes.
The list is checked against the runtime registry and signed manifests.
Concrete user example: «Is
there an HLT appointment that overlaps with an MNM one in the next 3
months?» → the planner builds in six steps
read_events → filter HLT → filter MNM →
filter_lists(op=overlap) → final_answer.
In extraction, dates come out as ISO 8601 when day, month, and year are
written in the text. Many sites omit the year on recent rows: there the value
carries the current year with a leading asterisk (*2026-05-29),
which states that the year was assumed rather than read. The field stays empty
only when no date can be derived at all: a visible date never becomes an empty
field.
This guide does not copy a changing executor count into prose. The
generated catalog is rebuilt from signed
manifests and provides the current inventory. The Composer sees the same
contract for every executor and does not select by transport. Five orthogonal producer verbs
(find for patterns, get for ids/state,
read for blobs from a source, list for
containers, filter for reduction).
13.7 How to read the contracts
The pages linked from this guide distinguish what the system provides today
from what remains proposed. Read them with these rules:
a capability described as active must be supported by code, loaded
manifests, or automated tests; a future proposal is labelled as such;
changing inventories and counts come from generated pages rather than
numbers copied into narrative prose;
names in monospace are technical identifiers, not necessarily
words shown in the interface;
natural-language examples show how to ask for a capability; the technical
references that follow explain how it is implemented;
links to the interface guide show where a
function is found in web chat.
14. The principles, in eight cards
If you remember only eight sentences from this document, make it these.
Everything else — code, prompts, conventions — follows from here.
1Vectorized by construction. Every executor accepts a list and returns a list, even a degenerate one. The batch version is the executor: *_batch does not exist.
2A closed, governed vocabulary. Everything that acts has a composable name inside a closed grammar. A new term enters only if necessary, general and understandable.
3No silent failure. Counts reflect what actually happened; truncation is declared, not hidden; a partial result presented as complete is a bug.
4Deterministic > LLM. Where an automaton or a table suffices, the model is not used. The LLM enters where an equipotent parser would genuinely be too complex — and it enters constrained.
5Never an implicit delete. Every move is copy → check → delete; never DELETE without a confirmed COPY.
6Reversibility with a rationale. Every evolutionary act (synthesis, merge, archive) is reversible and motivated. Saying yes costs less when you can go back.
7i18n by construction. Every user-facing string and prompt is per-language data: a new language is a translation pack, not a fork of the code.
8Understandability as a duty. If the user does not understand the system, the system is useless. Simplicity is not aesthetics: it is the criterion that selected everything else.
15. What Metnos is NOT
Half of the design lives in the no's. Every temptation to add an item from
this list must be resisted.
Not a permissionless plug-in framework. The core is domain-independent, but every concrete instance has a bounded, admitted executor set and explicit policies. A new domain is expressed through governed executors and skills, not by letting arbitrary packages inherit the agent's privileges.
It does not run third-party skills as-is. Drop-in formats are execution of someone else's code with your privileges. Here every package passes the 7-layer gate, or it does not run (ch. 7).
It trains no models. No fine-tuning, no RLHF. Growth is inspectable memory + synthesis behind the human filter (ch. 7 and 9).
Not a cloud agent. It runs at home; the frontier is an explicit consult, never the residence. No opening you did not choose.
Not an IDE nor a dev assistant. It does not write code in other projects on your behalf; at most it analyzes with read-only executors.
Not a home-automation replacement. It can ask a home-automation system; it does not duplicate it.
Not multi-channel at all costs. Two channels done well; the others when truly needed.
16. Where to go next
You now have both levels: the system from above and the map of its component
contracts. Use the atlas for implementation detail, or continue with the tour,
the domain reference, and the interface guide.