← Documentation index Architecture guide › planning engine

Metnos

Planning and reuse engine
Four layers sharing one control pipeline.

When a request arrives, Metnos first looks for a previously successful plan that can be reused safely. If it cannot find one, it builds a new plan. In the code, this internal plan is called a framework: a finite sequence of executors and links between their results. A model may propose it, but checks implemented in code decide whether it may run.

Contents

  1. Purpose
  2. What the engine receives and returns
  3. The four layers
  4. A turn's route
  5. The internal plan
  6. L0: fast path
  7. L1: autopath
  8. L2: validator
  9. L3: proposal, execution, and recovery
  10. Feedback and aging
  11. Using it from chat
  12. Limits of the guarantees
  13. Praxis console

1. Purpose

The engine turns a natural-language request into a finite sequence of admitted capabilities. It balances two requirements:

For example, you can ask: “Find PDFs changed this week under Projects, compute each file's SHA-256 hash, and create a spreadsheet with the name, date, and hash.” The first run may need a new plan. If you repeat the request, Metnos reuses that plan only when it is safe to cache and the executor and catalog signatures are still valid.

2. What the engine receives and returns

To plan a request, the engine receives the request, its recognized actions in order, the visible catalog, language, user, channel, destination, and any data already produced during the turn. It returns:

The catalog is the effective execution boundary. An absent or unadmitted executor does not become available merely because the model names it.

3. The four layers

LayerStateResponsibility
L0 — fast pathPersistentMaps a request to a plan that previously completed successfully and effectively.
L1 — autopathPersistentMaps groups of similar requests and intents to a generalizable plan.
L2 — validatorPer turnChecks names, schemas, required fields, and references before execution.
L3 — full enginePer turnProposes, finalizes, executes, classifies failures, and terminates.

L2 is not a separate lookup: it sits between a new proposal and execution. L0 and L1 plans still cross the current finalization pipeline, which applies guards, ordering, output policy, and consent gates.

4. A turn's route

  1. Routing builds a pool of relevant capabilities.
  2. L0 tries an exact match and then—only for generalizable plans—a semantic match.
  3. If L0 does not answer, L1 looks for an active champion compatible with the intent, object, and cluster.
  4. Without a valid reusable plan, the proposal component builds one or more candidates according to the active configuration.
  5. Structural guards and the validator inspect the candidate and, in admitted cases, request one corrective proposal.
  6. The shared execution engine runs the plan. If it fails without committed effects, recovery may try an alternative.
  7. The terminator presents the result, asks for input, or states an honest limit; an effective cacheable turn feeds L0 and L1 observations.

5. The internal plan, or framework

A framework describes the steps to run, each step's arguments, and how one result feeds the next step. Its format does not depend on the model that proposed it:

{
  "steps": [
    {"tool": "find_files", "args": {"base_path": "Projects", "pattern": "*.pdf"}},
    {"tool": "compute_signatures", "args": {"from_step": 1}},
    {"tool": "create_files_spreadsheet", "args": {"from_step": 2}},
    {"tool": "final_answer", "args": {}}
  ],
  "fillers": {},
  "final_message": ""
}

from_step and ${stepN.field} placeholders connect data without asking the model to copy it. The runtime can insert internal values through ${RUNTIME:key}. Configuration fields marked runtime_resolved, such as the default account or client, are not chosen by the proposer; the user context resolves them.

6. L0: fast path

L0 is created automatically after a successful, effective, cacheable turn. It does not require an approval button. Lookup has two forms:

Plans dependent on turn context—such as dialogs, consent, undo, and authenticated web sessions—are excluded. So are absolute time values that would become stale. Before replay, executor and candidate-family signatures must match. For mutations, discriminating argument values must also be grounded in the current request.

7. L1: autopath

L1 retains reusable plans together with recognized intents, semantic groups, timings, and feedback. Positive feedback can promote a plan to the active reference for its group. For long pipelines that succeed repeatedly, the runtime may create a shadow reference: it can be used under the same guards but remains distinct from a plan confirmed by the user.

Semantic matching respects canonical-object boundaries and a relevance floor. L1 also rejects request-specific plans and validates catalog signatures on every hit. Repeated negative feedback can demote a champion and create a temporary anti-autopath; later positive feedback can remove the corresponding exclusion.

8. L2: validator

The validator is enabled by default and uses no model. It checks:

If it finds an error, the proposal component may be called once with the invalid plan's fingerprint excluded. The new candidate then crosses the deterministic guards again.

9. L3: proposal, execution, and recovery

The component that proposes a plan is selected through configuration. Supported variants share the Proposer contract: some produce one candidate, while others compare several alternatives and return one. A grammar, when enabled, constrains output shape but does not make the model's semantic choice deterministic.

Before execution, the engine resolves references, data gathered through a dialog, and internal runtime values. It then checks each step's conditions and invokes the selected executor. Independent steps run in parallel only when their contracts and preflight admit it. External effects remain variable: networks, filesystems, providers, and content can change between executions.

Recovery separates structural from operational failures. It may change a plan for a wrong tool, wrong arguments, or missing input; it does not pretend to repair a network outage. If a step has already committed a mutation, the whole pipeline is not repeated, and the result reports the partial outcome honestly.

Deterministic corrections remain independent from domain and language. For example, one shared, translatable syntax vocabulary distinguishes a positive request such as “use the device” from its negation, “without using the device.” If a plan names an inverse action but omits its target, the engine may derive it only from a sealed undo contract produced by a preceding step, with an exact executor and a compatible schema; an explicit value is never replaced.

10. Feedback and aging

Feedback evaluates a turn outcome; it does not directly train the model. L0 may remove the rejected query's shortcut. L1 updates its observation, champion, and anti-autopath. Maintenance removes unused, demoted, expired, or dead-catalog rows.

This memory stores operational decisions and structured observations. It is not a biographical user profile and must not become a source of open-ended preferences injected into the planner.

11. Using it from chat

People do not need to know L0, L1, or executor names. They describe the desired outcome in natural language. For example:

For example: “Compare the files in the Quotes and Contracts folders and show those with identical content but different names.”

Inspecting or flushing caches instead requires the web chat: open Settings and choose Praxis. If the question starts on Telegram, Metnos must explain this path and state that the console is not part of the Telegram client.

12. Limits of the guarantees

The complete path is checked by logical certification outside the process under test. Twenty-four flows, each in Italian and English, verify planning, authority, consent, placement, effects, recovery, response, and postconditions. This is not a load test and does not replace non-destructive probes at real boundaries.

13. Praxis console

/admin/praxis shows the persistent layers: L0 fast paths, active or demoted L1 autopaths, observations, and anti-autopaths. It can delete an individual L0 row or flush L0, L1, or both. Flushing is an administrative, non-reversible operation: it removes accumulated operational capital and may slow requests until the caches are rebuilt.

The caches belong to the whole instance. L0 stores normalized request text and plan arguments; L1 stores plans, fingerprints, intents, and semantic vectors. They are not credential stores, but they may contain names, paths, or other data from a request and must therefore be treated as confidential. On every reuse, configured accounts, language, consent, destination, and authorization are resolved again in the current user's context.

Code references: