Ask Metnos with a request like this example: “Find the PDF files modified today.” If you repeat the request, Metnos may reuse the plan that already succeeded; you do not select or enable the fastpath manually.
Before calling the planner, Metnos tries to recognise the request. If a reusable plan exists and is still valid, it runs that sequence of executors. If the context or catalogue has changed, it treats the entry as invalid and returns to normal planning.
Planning is needed when a request is new or requires a new composition of
capabilities. Repeating it when the system already holds a valid plan adds work
and variability without improving the result. For example, a request already
solved with get_urls and describe_entries can reuse
that sequence, provided its arguments are derived from the current request.
What remains is to recognise a known request — and to judge when one that is merely similar sits close enough to be handled the same way. Two reuse layers handle this distinction. They recognise different degrees of similarity, but share one purpose: run a known plan without asking the planner to build it again.
The two layers differ in how much of the path they recognise. L0 recognises all of it, arguments included: the same request as before, with the same concrete values. L1 recognises the path alone — the skeleton of the solution, stripped of its arguments — and so it holds for a whole family of related requests.
| Layer | What it recognises | How |
|---|---|---|
| L0 | An already solved request. Exact matching may retain a request-specific plan; semantic matching is limited to plans that are safe to generalise. | Deterministic fingerprint (0a), then similarity through the configured embedder (0b) |
| L1 | A family of requests. Reuses a general plan associated with a complete intent and semantic cluster. | Intent, semantic cluster, and deterministic champion ordering |
The order is fixed: L0 first; if it finds nothing, L1. If both miss, the request reaches the planner (the engine), as always.
The planner does not disappear: L0 and L1 are controlled shortcuts. A new or ambiguous request, a turn with attachments, or a request without a valid match continues through the normal engine.
fastpath.py)
The first layer lives in runtime/engine/fastpath.py and keeps the
plans it has already run in a SQLite database (fastpaths.sqlite).
The entries appear on their own: whenever a turn succeeds — a fresh plan
from the engine, the reuse of an L1, a promotion from cosine 0b — Metnos
notes down the canonical query, its hash, the embedding produced by the
configured model, the whole plan (the skeleton, or framework) and the
intent: the verb and the object of the
request. No approval involved: the chains are built from executors already
vetted and tested.
The search runs in two phases:
An L0 entry removed because it aged, became invalid, or received negative feedback can be recreated by the next successful turn. Removing it does not remove the underlying capability.
undo_last_turn,
get_inputs, get_approval, and authenticated browsing
tools produce no fastpath, because their meaning or session identifier depends
on the current turn.since_iso="2026-06-11") is not recorded: replaying it on
another day would open a time window already frozen in the past. Relative dates
(time_window="today") are kept, because each replay works
them out afresh.autopath.py)
The second layer lives in runtime/engine/autopath.py. It does not
look for the same wording. It finds a semantic family, checks that the intent
object matches, and reuses only plans without literal arguments tied to the
original request. Variable arguments are derived again from the current
request before execution.
An autopath can arise in two ways. Positive feedback promotes a successful plan once it reaches the configured threshold, which is one confirmation by default. Alternatively, two successful runs of the same intent can seed a shadow autopath when the latest plan contains at least four steps. A shadow is usable but remains distinct from a confirmed plan; the first positive rating confirms it. This second path reduces the cost of recurring requests without presenting a non-human signal as human approval.
The boundary is deliberate: L0 favours repetition of the same request; L1 generalises to an intent group and may derive either from explicit feedback or from the shadow seeding described above. L0 comes first in the cascade, but both layers must pass the same validity, argument-grounding, and safety checks before execution.
Every stored plan carries two signatures: one for the executors it uses and one for the candidate family available for that intent. The signature also incorporates the version of routing and presentation rules. Metnos recomputes them before reuse: a changed or removed executor, a new competing capability, or a routing change turns the entry into a miss. The system replans instead of executing a decision made in a different operational context.
These signatures are user-agnostic and contain no profiles, affinities, or personal preferences. L1 therefore remains a shared cache of plan decisions with deterministic keys. Effects authorised for the user and final presentation — language, tone, length, and format — are applied outside the plan key.
The candidate family comes from the canonical vocabulary, including the
relationships between specialised content and filesystem carriers. For
example, a new files capability may change a plan operating on
images or texts. Query words and manifest affinities
do not enter the signature: invalidation follows catalogue semantics without
making L1 specific to a user or to one phrasing.
L0 fastpaths are retained or retired by fixed rules, with no model in the
loop. Each night the task_state_reaper process applies three aging
rules and four retirement conditions.
| Rule | Criterion | Default | Env |
|---|---|---|---|
| Never reused | Created more than N days ago but never served a second time | 14 days | METNOS_FASTPATH_GRACE_DAYS |
| Stale | Last use more than N days ago | 30 days | METNOS_FASTPATH_STALE_DAYS |
| LRU cap | Total entries above the cap; least recently used are pruned | 500 | METNOS_FASTPATH_MAX |
| Code | Cause | Transfers usage |
|---|---|---|
| C1 | A tool in the plan no longer exists in the catalogue (retired, renamed, archived). Replay would fail. | No |
| C2 provenance | The fastpath was promoted to a synthetic executor (see §9) and that executor is now in the catalogue. | Yes |
| C2 name | An executor named {verb}_{object} matching the intent exists, but no tool in the plan belongs to that family. The fastpath would shadow the executor. | Yes |
| C2 pre-filter | For multi-step plans: the deterministic routing pre-filter on the canonical query shows that a single executor now covers the intent (even under a different name). | Yes |
When a fastpath is retired because an executor superseded it (the C2
conditions), its usage count (n_uses) passes to that executor
through the lifecycle statistics store. Previously observed usage is therefore
not reset.
Pruning removes a stored route, not its executors. If the same request returns and succeeds, L0 can record the updated plan again.
Recognising the request is half the work. The other half is drawing out its
concrete values: which paths, which URLs, which date, which threshold. A
rule-based extractor (args_extractor.py) handles this, again with
no model:
https://...), path (~/... or /..., with
the “home” shortcut becoming ~/), email, numbers, file
extensions (“PDF file” → *.pdf), dates (today,
yesterday, tomorrow, the day after — in Italian and English —
turned into ISO format), and time windows (“this week”, “last
24 hours”, “last 7 days”).
Fastpath and autopath thresholds are read from the Metnos process environment;
when a variable is absent, the module default applies. The former
[fast_path] and [multi_tool_fast_path] sections in
~/.config/metnos/runtime.toml have been retired and are ignored.
The Praxis page can inspect and flush the caches, but it does not edit these
thresholds. A persistent override therefore belongs in the service
configuration; constants read at import time require a process restart.
| Variable | Default | Meaning |
|---|---|---|
METNOS_FASTPATH | 1 | Enables L0; setting it to 0 disables the layer |
METNOS_CLUSTER_COSINE_HIGH | 0.90 | Base semantic threshold; L0 matching uses this value plus 0.02 |
METNOS_FASTPATH_STALE_DAYS | 30 | Calendar days after which an unused entry is pruned |
METNOS_FASTPATH_GRACE_DAYS | 14 | Grace days for never-reused entries |
METNOS_FASTPATH_MAX | 500 | Maximum rows (LRU cap) |
| Variable | Default | Meaning |
|---|---|---|
METNOS_AUTOPATH | 1 | Enables L1; setting it to 0 disables the layer |
METNOS_AUTOPATH_MIN_OBS | 1 | Minimum positive observations to promote an autopath |
METNOS_AUTOPATH_FLOOR | 0.87 | Minimum similarity on the exact-intent fallback |
METNOS_AUTOPATH_TTL_ANTI | 2592000 (30 d) | Anti-autopath duration in seconds |
METNOS_AUTOPATH_TTL_REPEAT | 3600 (1 h) | Temporary exclusion after a repeat request |
METNOS_AUTOPATH_KEEP_OBS | 5000 | Maximum recent observations without a verdict to retain |
METNOS_AUTOPATH_STALE_DAYS | 90 | Inactivity period before an active autopath is removed |
METNOS_AUTOPATH_DEMOTED_TTL_DAYS | 30 | Retention period for a demoted autopath |
METNOS_SEED_STEPS | 4 | Minimum step count for shadow seeding |
METNOS_SEED_REPEAT | 2 | Successful observations of the same intent required for shadow seeding |
| Variable | Default | Meaning |
|---|---|---|
METNOS_FP_PROMOTE_MIN_CLUSTER | 3 | Minimum distinct fastpaths in the group |
METNOS_FP_PROMOTE_MIN_USES | 15 | Minimum cumulative usage |
METNOS_FP_PROMOTE_MIN_AGE_DAYS | 30 | Minimum group age |
METNOS_FP_PROMOTE_MAX_PER_NIGHT | 3 | Maximum new proposals per night |
METNOS_FASTPATH_AUTOPROMOTE | off | Enables Mode 2 auto-promotion (no human approval) |
METNOS_FP_AUTOPROMOTE_MIN_CLUSTER | 5 | Minimum distinct fastpaths for auto-promotion |
METNOS_FP_AUTOPROMOTE_MIN_USES | 50 | Minimum cumulative uses for auto-promotion |
METNOS_FP_AUTOPROMOTE_MIN_NIGHTS | 3 | Nights on which the same proposal must have been observed |
When several recurring L0 fastpaths share the same plan structure (the skeleton
hash) and the same intent, each night the task_fastpath_promotion
process weighs them as candidates to become a synthetic executor in their own
right. What it weighs is the group, never the single instance: at least three
distinct fastpaths, fifteen uses in all, and thirty days of age. And only
multi-step shapes are promoted: single-step ones already have an executor, and
there the fastpath only saves the LLM call, not the plan.
Why from L0 and not from L1. The analysis looks at the L0 fastpaths, not the L1 autopaths, because evidence of concrete requests lives in L0: how many distinct requests recur, how often, and for how long (the three numbers above). L1 is already general and arises from user feedback or shadow seeding, but it does not retain that count of distinct requests. Generalisation therefore happens here by grouping L0 fastpaths with the same plan shape and intent.
For candidates whose family is free, Metnos records the source fastpath
identifiers and fingerprints in the promotions table. Once the new
executor enters the catalogue, the nightly process uses that link to retire
exactly the entries that produced it. Composition candidates do not receive
this automatic provenance because their final name depends on the
human-selected qualifier; their L0 entries remain manageable under
Settings > Memory > Praxis.
© 2026 Roberto Brunialti · Metnos documentation