Skip to main content

MeTTa

MeTTa, Hyperon's AGI language, based on PeTTa semantics with significant extensions.

If you are an LLM, read llms.txt for the language and every surface, with exact return shapes and no prose to guess at.

sudo apt install swi-prolog          # macOS: brew install swi-prolog
                                     # Windows: winget install SWI-Prolog.SWI-Prolog

Architecture

One engine, in Prolog and C. Everything else reaches it through a declared seam, so each piece is built, versioned and published on its own.

Component Repository What it is
the engine engine/ translator, matcher, spaces, catalog, extension points, the C half
the libraries MeTTa-Library-Pack 61 libraries, written in MeTTa over the primitives
the examples MeTTa-Examples 360 executable programs, the semantics documentation
C CMeTTa a C program opens the engine in its own process
a storage backend MeTTa-MORK spaces on MORK's Rust trie

The four ways in

To add You So that
a surface speak the wire codec a surface is a consumer of the one engine, never an engine of its own
a backend claim your space names and FAIL for the rest the next provider's clause gets to answer
an integration register a row against a declared point the core names no third-party library at all
a library write MeTTa over the primitives it survives the engine being replaced

Extension points

engine/ext_points.pl declares every point in four kinds, and clauses_from/2 fixes who may contribute each.

clauses_from(event,       extension).
clauses_from(ownership,   extension).
clauses_from(declaration, extension).
clauses_from(service,     engine).

A backend claims the names it owns and fails for the rest, which is the whole protocol:

seam:foreign_space('&catalogs').
seam:foreign_capability('&catalogs', match).
seam:foreign_capability('&catalogs', enumerate).
seam:foreign_atoms('&catalogs', Row) :- package_catalog_row(Row).

The catalog

Everything the engine knows about itself is atoms you can query, including what each library is and where it came from.

!(import! &self (library lib_package))
!(test (size-atom (collapse (match &catalogs (package $name $path) $name))) 61)

The language

Atoms

Four kinds, and that is the whole representation.

!(test (get-metatype Tom) Symbol)                   ; a name that denotes itself
!(test (get-metatype $x) Variable)                  ; stands for anything
!(test (get-metatype 42) Grounded)                  ; a number, a string, a host object
!(test (get-metatype (Parent Tom Bob)) Expression)  ; atoms in order

Terms read and print as themselves.

!(test (repr 42) "42")
!(test (repr "42") "\"42\"")
!(test (repr (A (B C))) "(A (B C))")
!(test (repr (A (, B , C ,))) "(A (, B , C ,))")
!(test (repr 2025_12_12) "2025_12_12")
!(test (repr ()) "()")

Spaces and matching

A space is where a program lives, and match reads it.

(= (matchtrickery)
   (let* (($t1 (add-atom &self (foo a)))
          ($t2 (add-atom &self (foo b))))
         (match &self (foo $1) (bar $1))))

!(test (collapse (matchtrickery))
       ((bar a) (bar b)))

A pattern's head can be a constant, so the head is just another position.

(= (h (justdata haha $B) $C)
   (+ $B $C))

!(test (h (justdata haha 30) 40) 70)

Equations

An equation is an atom, so partial application and composition fall out of the same rule.

(= (mp) (+))

!(test (mp 1 1) 2)

(= (.. $f1 $f2 $arg) ($f1 ($f2 $arg)))

(= (plus1times2) (.. (* 2) (+ 1)))

!(test (plus1times2 1) 4)

Many answers

Nondeterminism is the default, and empty is the answer with no answers.

(= (y) (empty))

!(test (collapse (y))
       ())

once commits to the first.

(foo 1)
(foo 2)

(= (match-single $space $pat $ret)
   (once (match $space $pat $ret)))

!(let $x (match-single &self (foo $1) $1) (add-atom &self (bar $x)))

!(test (collapse (match &self (bar $1) (bar $1)))
       ((bar 1)))

Control flow

if takes a boolean and two branches.

!(test (if True 42) 42)

case dispatches on shape.

(= (casetest $x)
   (case $x ((4 42)
             ($otherpattern 44)
             ($otherother $45))))

!(test (casetest 5) 44)

chain sequences.

!(test (chain (+ 2 4) $n (* 3 $n))
       18)

!(test (chain (+ 1 3) $n (chain (* 2 $n) $m (+ $n $m)))
       12)

A cut commits to what has been found.

(foo 1)
(foo 2)

(= (match-single $space $pat $ret)
   (let* (($x (match $space $pat $ret))
          ($temp (cut)))
         $x))

!(let $x (match-single &self (foo $1) $1) (add-atom &self (bar $x)))

!(test (collapse (match &self (bar $1) (bar $1)))
       ((bar 1)))

Recursion under an explicit branch budget.

(= (fib $N)
   (if (< $N 2)
       $N
       (+ (fib (- $N 1))
          (fib (- $N 2)))))

!(test (with-pragma! ((max-stack-depth 100000000)) (fib 30)) 832040)

Data

Multiset operations over atoms.

!(test (unique-atom (a b c d d)) (a b c d))
!(test (union-atom (a b b c) (b c c d)) (a b b c b c c d))
!(test (intersection-atom (a b c c) (b c c c d)) (b c c))
!(test (subtraction-atom (a b b c) (b c c d)) (a b))
!(test (intersection-atom (a b c c) (b c d)) (b c))
!(test (intersection-atom (a a a) (a)) (a))
!(test (subtraction-atom (a a a) (a)) (a a))
!(test (intersection-atom (a b) ()) ())

Sequence variables

A pattern child that stands for a run of atoms. Upstream PeTTa has no such pattern, so this is the one part of the language below that a stock kernel will not parse, and the sixteen libraries listed under the library pack are written with it.

!(test (collapse (let ((:seg $pre) SEP (:seg $post)) (a b SEP c SEP d)
                      (pair $pre $post)))
       ((pair (a b) (c SEP d)) (pair (a b SEP c) (d))))

!(test (let (row (:seg $r)) (row) $r) ())
!(test (let (row (:seg $r)) (row a b c) $r) (a b c))

!(test (get-metatype (let (row (:seg $r)) (row a b) $r)) Expression)
!(test (size-atom (let (row (:seg $r)) (row a b) $r)) 2)
!(test (car-atom (let (row (:seg $r)) (row a b) $r)) a)

!(test (let (f (:seg $x) g (:seg $x)) (f a b g a b) $x) (a b))
!(test (collapse (let (f (:seg $x) g (:seg $x)) (f a b g c) $x)) ())
!(test (let (f (:seg $x) g (:seg $x)) (f 1 g 1.0) took) took)

!(test (collapse (let (f ... g ...) (f a g b c) done)) (done))

!(test (let (f (g ...) b) (f (g 1 2) b) nested) nested)
!(test (collapse (let (A ... D) (A b c E) never)) ())

!(add-atom &self (edge a b))
!(add-atom &self (edge b c d))
!(add-atom &self (tag b hot))
!(test (collapse (match &self (edge a ... $last) $last)) (b))
!(test (collapse (match &self (, (edge ... $mid) (tag $mid $heat)) ($mid $heat)))
       ((b hot)))

Numbers

!(test (exp-math 0) 1.0)
!(test (exp-math 1.0) 2.718281828459045)
!(test (< (abs-math (- (exp-math 2.0) (* 2.718281828459045 2.718281828459045))) 1.0e-12) true)
!(test (< (abs-math (- (log-math 2.718281828459045 (exp-math 3.0)) 3.0)) 1.0e-12) true)

(= (in-range $lo $hi $x) (and (<= $lo $x) (<= $x $hi)))
!(test (in-range 1 6 (random-int 1 6)) true)
!(test (in-range 0.0 1.0 (random-float 0.0 1.0)) true)
!(test (in-range 5 5 (random-int 5 5)) true)

Python as a notation

!(test (repr (py-call (str true))) "True")
!(test (repr (py-call (str false))) "False")
!(test (py-call (sorted (true false))) (false true))
!(test (py-call (len (true false true))) 3)
!(test (py-call (isinstance true (py-call (type false)))) true)
!(test (py-call (bool 1)) true)
!(test (py-call (bool 0)) false)
!(test (py-call (.bit_length true)) 1)
!(test (repr (py-call (.upper abc))) "ABC")

Types

Optional, and parametric.

(: apply (-> (-> $tx $ty) $tx $ty))
(= (apply $f $x) ($f $x))
!(apply not False) ; True
!(get-type (apply not False))
!(test (let (get-type apply) (-> (-> Bool Bool) Bool $result) $result)
       Bool)

Errors and refusals

A refusal names what went wrong rather than failing silently.

!(test (throw (my-ball 1)) (Error (throw (my-ball 1)) (my-ball 1)))
!(test (throw "text") (Error (throw "text") "text"))

!(test (if-error (throw oops) caught fine) caught)
!(test (if-error 42 caught fine) fine)
!(test (return-on-error (throw oops) carried-on) (Error (throw oops) oops))
!(test (return-on-error 42 carried-on) carried-on)

!(test (throw (Error (inner 1) because)) (Error (inner 1) because))
!(test (throw (throw first)) (Error (throw first) first))

(= (half $n) (if (== (% $n 2) 0) (/ $n 2) (throw (odd $n))))
!(test (half 10) 5)
!(test (half 7) (Error (throw (odd 7)) (odd 7)))
!(test (if-error (half 7) refused (half 7)) refused)

!(test (trace! "the answer" 42) 42)
!(test (+ 1 (trace! "adding one to" 41)) 42)
!(test (trace! (half 10) (half 10)) 5)

!(test (trace! (checking (odd 7)) ok) ok)

Testing

Every example checks itself, using the same forms you would.

!(import! &self (library lib_he))

(= (add 1 2) 3)

!(test (id 5) 5)

!(test (=alpha (Father $X) (Father $Y)) True)

!(test (=alpha (Father $X) (Son $X)) False)

!(test (if-equal 1 1 "Equal" "Not Equal") "Equal")

Seeing your program

!(import! &self (library lib_string))

!(test (> (current-time) 1700000000.0) True)

!(test (<= (current-time) (current-time)) True)

!(test (format-time "abc") abc)
!(test (== (format-time "abc") "abc") False)
!(test (string-length (format-time "a literal")) 9)
!(test (string-length (format-time "")) 0)
!(test (string-length (format-time "%%")) 1)

!(test (string-length (format-time "%Y")) 4)
!(test (string-length (format-time "%Y-%m-%d")) 10)
!(test (string-length (format-time "%H:%M:%S")) 8)

!(test (collapse (argv 999)) ())
!(test (collapse (argv -1)) ())

!(test (== (argv 0) (argv 0)) True)

(= (argument-or $index $default)
   (let $found (collapse (argv $index))
        (if (== $found ()) $default (car-atom $found))))
!(test (argument-or 999 no-such-argument) no-such-argument)
!(test (== (argument-or 0 no-such-argument) no-such-argument) False)

Events and standing queries

!(test (match &metta (vocabulary delivery $a $b $c) ($a $b $c))
       (at-most-once at-least-once per-write-exactly))
!(test (match &metta (vocabulary event-order $a $b) ($a $b))
       (ordered unordered))
!(test (match &metta (kind events $ctx $delivery $order) $delivery)
       (one-of delivery))

!(test (if-error (catch (add-atom &metta (events &feed eventually)))
                 refused admitted)
       refused)

!(add-atom &native-events (reading 1))
!(test (collapse (match &metta (events &native-events $d $o) declared)) ())

!(test (match &metta (vocabulary agenda-policy $a $b $c $d $e) ($a $b $c $d $e))
       (declaration recency specificity priority user))
!(test (match &metta (policy reaction-order $knob $default) ($knob $default))
       (agenda declaration))
!(test (match &metta (kind agenda $ctx $policy $fn) $policy)
       (one-of agenda-policy))

!(test (match &metta (kind on $ctx $pattern $op $priority) $priority)
       (optional integer))

Concurrency

!(add-atom &Point (: Point (-> Number Number Point)))
!(add-atom &Point (= (Point-x (Point $x $y)) $x))
!(add-atom &Point (= (Point-y (Point $x $y)) $y))

!(add-atom &Point
  (= (Point-norm (Point $x $y)) (sqrt-math (+ (* $x $x) (* $y $y)))))

!(add-atom &Point
  (= (Point-add (Point $x1 $y1) (Point $x2 $y2)) (Point (+ $x1 $x2) (+ $y1 $y2))))

!(add-atom &Point
  (= (Point-quadrant $p)
     (case $p (((Point 0 0) origin) ((Point 0 $y) axis) ((Point $x $y) plane)))))

!(add-atom &self (from &Point))

!(test (Point-norm (Point 3 4)) 5.0)
!(test (Point-add (Point 1 2) (Point 3 4)) (Point 4 6))
!(test (Point-quadrant (Point 0 0)) origin)
!(test (Point-quadrant (Point 0 4)) axis)
!(test (Point-quadrant (Point 3 4)) plane)
!(test (== (Point-add (Point 1 2) (Point 3 4)) (Point 4 6)) True)

Worlds and state

!(bind! state (new-state rest))
!(test (get-state state) rest)

!(test (change-state! state active) true)
!(test (get-state state) active)

!(test (get-type (new-state 5)) (StateMonad Number))
!(test (get-type (new-state "hi")) (StateMonad String))

!(test (let $cell (new-state 1)
            (let $_ (change-state! $cell 2) (get-state $cell)))
       2)

Performance

Memoisation is a library, not a keyword.

!(import! &self (library lib_memo))

!(memoize sq)
(= (sq $x) (* $x $x))

!(test (sq 9) 81)
!(test (sq 9) 81)
!(test (sq 9) 81)

Spaces backed by anything

A space of your own, inheriting what it does not answer.

!(add-atom &family-parent (edge a b))
!(add-atom &family-parent (parent-only kept))
!(add-atom &family-parent (layer parent))
!(new-space &family-child (inherits &family-parent))
!(add-atom &family-child (edge b c))
!(add-atom &family-child (child-only local))
!(add-atom &family-child (layer child))

!(test (collapse (match &family-child
                         (, (edge $x $y) (edge $y $z))
                         ($x $z)))
       ((a c)))

!(test (collapse (match &family-child (layer $x) $x)) (child parent))
!(test (space-atom-count &family-child) 3)

!(test (collapse (match &family-parent (parent-only $x) $x)) (kept))
!(test (collapse (match &family-child (parent-only $x) $x)) (kept))
!(test (collapse (match &family-parent (child-only $x) $x)) ())

Rows in a CSV file, queried as atoms.

!(import! &self (library lib_csv))
!(import! &self (library lib_file))

!(bind! &csv-path (temp-path! "metta-csv-example"))
!(write-file! &csv-path "id,amount\n001,12.50\n002,9\n002,9\n")
!(bind! &sales (csv-space &csv-path))

!(test (collapse (match &sales (row $id $amount) ($id $amount)))
       (("id" "amount") ("001" "12.50") ("002" "9") ("002" "9")))
!(test (match &sales (row "001" $amount) (parse-number $amount)) 12.5)

!(write-file! &csv-path "003,42\n")
!(test (collapse (match &sales (row $id $amount) ($id $amount)))
       (("003" "42")))
!(delete-file! &csv-path)

A reasoner

(= (myf $M)
   (and (and (member a $M)
             (member b $M))
        (== (size-atom $M) 2)))

!(test (if (once (myf $M)) $M)
       (a b))

Weighted answers

!(import! &self (library lib_pln))

(= (STV A) (stv 0.5 0.9))
(= (STV B) (stv 0.25 0.9))
(= (STV C) (stv 0.25 0.9))
(= (STV D) (stv 0.5 0.9))

(= (kb)
   ((Sentence ((Inheritance A B) (stv 0.25 0.9)) (1))
    (Sentence ((Inheritance A C) (stv 0.25 0.9)) (2))
    (Sentence ((Inheritance B D) (stv 0.5 0.9)) (3))
    (Sentence ((Inheritance C D) (stv 0.5 0.9)) (4))
   ))

!(test (with-pragma! ((max-stack-depth 100000000))
                     (PLN.Query (kb) (Inheritance A D)))
       ((stv 0.5 0.9473684210526316) (1 2 3 4)))
!(add-atom &self (= (fib $N)
                    (if (< $N 2)
                        $N
                        (+ (fib (- $N 1))
                           (fib (- $N 2))))))

!(test (with-pragma! ((max-stack-depth 100000000)) (fib 30)) 832040)

Extending the engine

A translator rule changes what a form compiles to.

(= (runtime42 $arg)
   (cons 42 $arg))

(= (compileeval42 $arg)
   (cons 42 $arg))

(= (compile42 $arg)
   (noeval (cons 42 $arg)))

!(add-translator-rule! compileeval42)
!(add-translator-rule! compile42)

!(test (runtime42 (43)) (42 43))
!(test (compileeval42 (43)) (42 43))
!(test (compile42 (43)) (42 43))

Prolog underneath, when you want it.

!(test (progn (translatePredicate (is $x 2))
              (translatePredicate (+ $x 40 $z)) $z)
       42)

MeTTa's own evaluator, written in MeTTa.

(: myinterpreter (-> Atom %Undefined%))
(= (myinterpreter $code)
   (let $temp (println! ("Runtime-interpreting code" $code))
        (eval $code)))

(= (w) 42)
(= (v) 43)

!(test (myinterpreter (if (== 1 1) (w) (v))) 42)
!(test (myinterpreter (if (== 1 2) (w) (v))) 43)

git-import! fetches and builds a library from source; see the example.

The library pack

Sixty-one libraries sit under lib/. None is loaded until a program names it, and every example below is run by the gate on a fresh space, so a line that stops being true fails the build instead of going stale on the page.

Sixteen of them are written in a language upstream PeTTa does not accept. They use the sequence variables above, (:seg $rest) and its anonymous ..., in their own definitions and signatures: lib_sets types union as (-> (:seg Expression) Expression) so it takes any number of sets, and lib_strategy types seq the same way. What they mean is PeTTa's; what they are written in is a superset of it, so these sixteen need this kernel:

lib_builtin_types, lib_combinatorics, lib_database, lib_datastructures, lib_encoding, lib_functional, lib_graph, lib_package, lib_pairs, lib_parsing, lib_random, lib_sets, lib_statistics, lib_strategy, lib_tabling, lib_uuid.

The other forty-four import and run on either. lib_gitimport is the sixty-first and has no MeTTa half at all: it is the Prolog backing lib_package calls to fetch a repository, reached through a package requirement rather than through import!.

One example each is what this page is for. Every head a library exports, with its own (@doc ...) text, is in website/reference/metta-libraries.md, generated from the live atoms by extensions/python/tools/libdoc.py; help! and get-doc answer the same atoms at the prompt.

lib_builtin_types

Declare the type surface of MeTTa's shipped builtins, its type-kind markers included, for engine reflection and optional live typed dispatch. Needs sequence variables.

!(import! &self (library lib_builtin_types))
!(test (format-args "{} and {}" ("only")) "only and ")

lib_cli

Declare typed command-line parsing, help and exact argument access.

!(import! &self (library lib_cli))
!(test (cli-types) (boolean integer float atom string metta))

lib_combinatorics

Finite choices and exact counts as MeTTa answer streams. Needs sequence variables.

!(import! &self (library lib_combinatorics))
!(test (choose2l (a b c)) ((a b) (a c) (b c)))

lib_compression

Declare compression and archive operations from native typed exports.

!(import! &self (library lib_compression))
!(test (compression-formats) (gzip zlib))

lib_conformance

Prove a foreign space provider before its users find out, for the tier that had no way to do it.

!(import! &self (library lib_conformance))
!(test (get-type check-space-provider) (-> Atom Expression))

lib_constraints

Expose SWI's clpq and clpb as MeTTa operations.

!(import! &self (library lib_constraints))
!(test (clpq (= (+ $x 1) 3)) True)

lib_crypto

Expose the native crypto declarations, types and help to MeTTa.

!(import! &self (library lib_crypto))
!(test (crypto-hash sha256 "") "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")

lib_csv

Lossless CSV text, streamed rows, live views and mutable snapshots.

!(import! &self (library lib_csv))
!(test (csv-parse "001,\"a,b\"\r\n002,9\r\n") (("001" "a,b") ("002" "9")))

lib_database

Declare independent persistent stores from the native typed exports. Needs sequence variables.

!(import! &self (library lib_database))
!(test (get-type database-open!) (-> %Undefined% Symbol %Undefined%))

lib_datastructures

Immutable maps, priority queues, functional queues and finger trees. Needs sequence variables.

!(import! &self (library lib_datastructures))
!(test (map-size (map-from-pairs ((a 1) (b 2)))) 2)

lib_datetime

Supply clocks, calendar records, parsing and explicit-zone arithmetic.

!(import! &self (library lib_datetime))
!(test (day-of-week 1766188800) Saturday)

lib_derived

The derived forms the engine keeps FUSED into its compiler, written out as translator rules, so a program that wants the smaller instruction set can have it and pay the difference knowingly. fused, written out as translator rules so a program can have the smaller instruction set and pay the difference knowingly. add-translator-rule! registers for every space and the rest of the session, so a program that only wanted it briefly gives it back.

!(import! &self (library lib_derived))
!(test (once (superpose (1 2 3))) 1)
!(remove-translator-rule! once)

lib_dict

A space used as a dictionary; the dict story, and it is the space.

!(import! &self (library lib_dict))
!(test (dict-size (dict-put (new-space) a 1)) 1)

lib_doc

Preserve the old lib_doc import path after its vocabulary moved into the engine.

!(import! &self (library lib_doc))
!(test (get-metatype (get-doc get-doc)) Expression)

lib_encoding

Compose UTF8/base64 host codecs with inspectable MeTTa hex recipes. Needs sequence variables.

!(import! &self (library lib_encoding))
!(test (utf8-encode "hi") (104 105))

lib_file

Files, directories, paths, links, traversal, scopes and streams.

!(import! &self (library lib_file))
!(test (path-join "one" "two") "one/two")

lib_functional

Compose collection transformations and held control forms in MeTTa. Needs sequence variables.

!(import! &self (library lib_functional))
!(test (zip (1 2 3) (a b c)) ((1 a) (2 b) (3 c)))

lib_graph

Derive directed graphs from canonical relation and set expressions. Needs sequence variables.

!(import! &self (library lib_graph))
!(test (graph-topological-order ((a (b)) (b ()))) (a b))

lib_he

The hyperon-experimental compatibility surface.

!(import! &self (library lib_he))
!(test (unify (f a) (f $x) $x none) a)

lib_http

Declare the HTTP surface generated from its native typed exports.

!(import! &self (library lib_http))
!(test (http-methods) (delete get head post put patch options))

lib_import

Load Prolog support and expose source imports as queryable data.

!(import! &self (library lib_import))
!(test (get-metatype use-module!) Grounded)

lib_json

JSON documents whose objects are queryable spaces.

!(import! &self (library lib_json))
!(test (json-decode "[1,2,3]") (1 2 3))

lib_logging

Structured host messages, topic controls and explicit handlers.

!(import! &self (library lib_logging))
!(test (log-levels) (debug informational warning error))

lib_markup

XML and HTML as expressions, with a selector language over them.

!(import! &self (library lib_markup))
!(test (markup-text (markup-parse-xml "<p>hi</p>")) "hi")

lib_math

Compose exact number operations over the shared numeric providers.

!(import! &self (library lib_math))
!(test (math-gcd (12 18)) 6)

lib_measure

Weighted-superposition operations for normalization, ranking, sampling, aggregation, and expectation.

!(import! &self (library lib_measure))
!(test (get-metatype measure) Symbol)

lib_memo

Expose the resident automatic and explicit memoization controls.

!(import! &self (library lib_memo))
!(test (get-metatype memo) Symbol)

lib_mm2

Five operators as a notation over &mork, the on-demand half of a seat whose provider is extensions/mork.

!(import! &self (library lib_mm2))
!(test (get-type +) (-> Atom %Undefined%))

lib_nars

Provide NARS truth functions, inference rules, and bounded derivation.

!(import! &self (library lib_nars))
!(test (get-metatype nars) Symbol)

lib_observe

Make execution observations queryable with match and get-atoms.

!(import! &self (library lib_observe))
!(test (get-type observe-source) (-> SpaceType String String SpaceType))

lib_package

Document the default package interpreter and its explicit setup door. Needs sequence variables.

!(import! &self (library lib_package))
!(test (size-atom (collapse (match &catalogs (package $n $p) $n))) 61)

lib_pairs

Read ordinary (Key Value) pairs as a relation through collection operations. Needs sequence variables.

!(import! &self (library lib_pairs))
!(test (pairs-lookup ((a 1) (b 2)) b) 2)

lib_parsing

Prepare grammar data as ordinary nondeterministic MeTTa functions. Needs sequence variables.

!(import! &self (library lib_parsing))
!(test (grammar-parse (lit "ab") "ab") "ab")

lib_patrick

lib_patrick's four idioms: composition and iteration.

!(import! &self (library lib_patrick))
!(test (get-type compose) (-> Atom _ _))

lib_pln

Probabilistic logic network truth functions, confidence and weight.

!(import! &self (library lib_pln))
!(test (Truth_w2c 1) 0.5)

lib_pln2

An isolated, assumption-explicit truth-value library for Beta and moment formulas that are independently checked rather than inherited from legacy lib_pln policy.

!(import! &self (library lib_pln2))
!(test (get-metatype pln2) Symbol)

lib_process

Run a program with an argument vector, capture what it wrote, and start, watch, signal and wait for one that outlives the call.

!(import! &self (library lib_process))
!(test (process-run! "echo" ("hi")) (process-result 0 "hi\n" ""))

lib_random

Construct inspectable sample programs and select distinct occurrences. Needs sequence variables.

!(import! &self (library lib_random))
!(test (random-shuffle! ()) ())

lib_redis

Shared spaces over Redis, SWI's own library(redis) underneath, plugged into the engine's foreign-space seam.

!(import! &self (library lib_redis))
!(test (get-metatype redis-open!) Symbol)

lib_reflect

Inspect the engine's surface and manipulate literal terms as data.

!(import! &self (library lib_reflect))
!(test (atom-variables (f $x $y)) ($x $y))

lib_regex

Declare compiled PCRE2 matching, capture scans and substitutions.

!(import! &self (library lib_regex))
!(test (re-match "(?i)^needle" "Needle in a haystack") True)

lib_roman

Tracing helpers and higher-order list operations, map-flat among them.

!(import! &self (library lib_roman))
!(test (get-metatype roman) Symbol)

lib_sets

Derive set operations over canonical expressions from core collections. Needs sequence variables.

!(import! &self (library lib_sets))
!(test (set-of (3 1 2 1)) (1 2 3))

lib_socket

Typed generated socket operations over File's owned stream handles.

!(import! &self (library lib_socket))
!(test (socket-wait! () infinite) ())

lib_soft

Score written terms using symbol similarity and structural recursion.

!(import! &self (library lib_soft))
!(test (sym-sim a a) 1.0)

lib_spaces

Migrate, copy, drain and count atoms between spaces.

!(import! &self (library lib_spaces))
!(test (match-count (new-space) ($x)) 0)

lib_statistics

Derive sample summaries and finite probability laws in MeTTa. Needs sequence variables.

!(import! &self (library lib_statistics))
!(test (stats-mean (1 2 3)) 2)

lib_strategy

Compose literal term rewrites through ordinary MeTTa functions. Needs sequence variables.

!(import! &self (library lib_strategy))
!(test (get-type seq) (-> Atom (:seg Atom) %Undefined%))

lib_string

Compose String recipes over the shared text and metric providers.

!(import! &self (library lib_string))
!(test (string-length "a🦊é") 3)

lib_system

The environment, the working directory and what the host says about itself, as data a program can read and write.

!(import! &self (library lib_system))
!(test (collapse (env-get "NO_SUCH_VARIABLE_HERE")) ())

lib_tabling

The runtime control plane for tabling MeTTa functions. Needs sequence variables.

!(import! &self (library lib_tabling))
!(test (get-type tabled) (-> Atom Bool))

lib_testing

Import finite generators for properties expressed with core assertions.

!(import! &self (library lib_testing))
!(test (== 1 1) True)

lib_thread

Publish parallel data operations, M:N engine futures, timers, channels, pools, Linda waits and locks over SWI-Prolog primitives.

!(import! &self (library lib_thread))
!(test (get-type spawn) (-> Atom %Undefined%))

lib_torch

PyTorch from plain MeTTa through py-call: tensors, algebra, reductions, activations, the exits back to MeTTa data and autograd, with no Python-side setup needed beyond torch being importable.

!(import! &self (library lib_torch))
!(test (get-type torch-tensor) (-[det,writesState]-> %Undefined% %Undefined%))

lib_unicode

The Unicode character database and the standard text transformations over it.

!(import! &self (library lib_unicode))
!(test (unicode-normalize nfkc "ffi") "ffi")

lib_uri

Declare URI operations from their native typed exports.

!(import! &self (library lib_uri))
!(test (uri-parts "") (("path" "")))

lib_uuid

Compose UUID names, namespaces and byte fields as MeTTa equations. Needs sequence variables.

!(import! &self (library lib_uuid))
!(test (uuid-version (uuid-random!)) 4)

lib_vector

Compose numeric construction from MeTTa streams and shared kernels.

!(import! &self (library lib_vector))
!(test (dot (1.0 2.0) (3.0 4.0)) 11.0)

lib_yaml

YAML documents as MeTTa values, in the shape lib_json already uses.

!(import! &self (library lib_yaml))
!(test (yaml-decode "- 1\n- 2\n") (1 2))

lib_zar

Prolog interop: predicate-style consult and use_module wrappers.

!(import! &self (library lib_zar))
!(test (get-type consult_file) (-> %Undefined% %Undefined%))

CMeTTa

A C program opens the engine in its own process, builds terms and asks. Repository · llms.txt

Feature Doors
Runtime mt_open, mt_close, mt_verbose, mt_thread_attach, mt_thread_detach
Constructors mt_sym, mt_var, mt_text, mt_num, mt_real, mt_bool, mt_unit, mt_bigint, mt_rational, mt_spaceref, mt_exprv
References mt_keep, mt_drop
Inspection mt_kind_of, mt_name, mt_int, mt_float, mt_truth, mt_len, mt_at, mt_eq, mt_hash
Unification mt_unify, mt_unifyv, mt_bindings_*, mt_substitute
Spaces mt_self, mt_catalog, mt_space_open, add/del/match/eval/atoms/count/wipe
Answers mt_run, mt_load, mt_do, mt_next, mt_row_next, mt_bound
Text mt_parse, mt_show, mt_write_dup, mt_free
Errors mt_error, mt_errmsg, mt_remedy, mt_ground, mt_ok, mt_clear
Defining mt_def for a C function, mt_lower for equations from C tokens
#define MT_SHORTHAND
#include <cmetta.h>
#include <stdio.h>

/* --- the two doors, side by side ------------------------------------ *
 *
 * mt_def publishes a C function. The engine CALLS it, and because nothing can
 * be seen of what it does, it must declare an effect class.
 *
 * mt_lower installs an EQUATION. It is MeTTa, so the engine reads it,
 * type-checks it, specialises it, matches on it, and a call crosses into no
 * host at all.
 *
 * The preprocessor is what makes the second one possible in C. Python lowers
 * by reading a function's __code__ and Node by reading its toString(); C has
 * neither at run time, but `#` is access to the program's own source at the
 * one moment C offers it.
 */

static mt_status op_triple(mt_call *call, void *user)
{ int64_t v;
  (void)user;
  mt_clear();
  v = mt_int(mt_arg(call, 0));
  if ( !mt_ok() ) return mt_fail(call, "triple wants a Number");
  return mt_answer(call, N(v * 3));
}

/* --- one body, two languages ---------------------------------------- *
 *
 * The operators are parameters, so the same body expands to C in one mode and
 * to MeTTa tokens in the other. The function exists once and is callable from
 * both, which is what the other seats' twins buy, bought the way C buys it.
 */
#define POLY(ADD, MUL, x)  ADD(MUL(3, x), 1)
#define C_ADD(a, b)        ((a) + (b))
#define C_MUL(a, b)        ((a) * (b))
#define M_ADD(a, b)        (+ a b)
#define M_MUL(a, b)        (* a b)

static int64_t poly(int64_t x) { return POLY(C_ADD, C_MUL, x); }

int main(void)
{ metta *m = mt_open(NULL);
  if ( !m ) return fprintf(stderr, "boot: %s\n", mt_errmsg()), 1;

  /* Called: the engine crosses into C, and had to be told the effect class. */
  mt_def(m, (mt_op){ .name = "triple", .arity = 1,
                     .effect = MT_PURE, .fn = op_triple });
  printf("called   (triple 7) = %lld\n",
         (long long)mt_one_int(mt_run(m, "!(triple 7)")));

  /* Lowered: the body is C tokens the compiler saw, installed as MeTTa. No
     quoting, no escaped newlines, and unbalanced parentheses are a compile
     error rather than a runtime one. */
  mt_lower(m, (twice $x), (* 2 $x));
  mt_lower(m, (fib $n), (if (< $n 2) $n
                            (+ (fib (- $n 1)) (fib (- $n 2)))));
  printf("lowered  (twice 21) = %lld\n",
         (long long)mt_one_int(mt_run(m, "!(twice 21)")));
  printf("lowered  (fib 20)   = %lld\n",
         (long long)mt_one_int(mt_run(m, "!(fib 20)")));

  /* One body, both languages. */
  mt_lower(m, (poly $x), POLY(M_ADD, M_MUL, $x));
  printf("in MeTTa (poly 5)   = %lld\n",
         (long long)mt_one_int(mt_run(m, "!(poly 5)")));
  printf("in C     poly(5)    = %lld\n", (long long)poly(5));

  /* And the difference that matters: a lowered equation is an ATOM in the
     space, so the engine can be asked about it. A published C function is
     opaque and there is nothing to ask. */
  mt_each (a, mt_match(mt_self(m), E("=", E("poly", V("x")), V("body"))))
      printf("the engine can see: %s\n", mt_show(a));

  mt_each (a, mt_match(mt_self(m), E("=", E("triple", V("x")), V("body"))))
      printf("...but not this:    %s\n", mt_show(a));
  printf("(nothing printed above, because a called function has no equation)\n");

  mt_close(m);
  return 0;
}

Documentation

Read For
llms.txt the language and every surface, exact return shapes, gate-checked names
examples/ 360 programs in 22 chapters, every one run by the gate
EXTENDING.md writing an integration
CONTRIBUTING.md working on this repository
SECURITY.md reporting a vulnerability

Citing

@software{petta,
  author = {Hammer, Patrick},
  title  = {PeTTa},
  url    = {https://github.com/patham9/PeTTa},
  note   = {The MeTTa implementation whose semantics this engine follows}
}

@software{metta_kernel,
  author  = {MesTTo},
  title   = {MeTTa Kernel},
  url     = {https://github.com/MesTTo/MeTTa},
  version = {0.8.0}
}

Licence

Apache-2.0. See LICENSE.

Release files for PyMeTTa 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for PyMeTTa 0.9.0
File Size Uploaded
pymetta-0.9.0.tar.gz 9.9 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for PyMeTTa 0.9.0
File Interpreter ABI Platform
pymetta-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 20.0 MB

Release files / pymetta-0.9.0.tar.gz

Download URL pymetta-0.9.0.tar.gz
Size 9.9 MB
Tags Source
SHA-256 checksum
How to use checksums
04f2497f159109c22204d2d1bec3d0a14929986720b54852d67dfaf78acf0061
BLAKE2b-256 checksum
How to use checksums
32d76721ff95c5a2c3d2678fc759cef4e5b72534c1d0f25553d890447425afcb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / pymetta-0.9.0-py3-none-any.whl

Download URL pymetta-0.9.0-py3-none-any.whl
Size 10.1 MB
Tags Python 3
SHA-256 checksum
How to use checksums
4bb7c19b26959cc72be15aa6f72def58c5ac8ae0b36544481e5f63f16103e6b0
BLAKE2b-256 checksum
How to use checksums
a7b1b9b2c7c44fae03d3f42f71c312cddcd0fc6e1aaf65acb4e6e1ca40146d18
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release history Release notifications | RSS feed

0.9.3

5 release files

0.9.2

5 release files

0.9.1

2 release files

This release

0.9.0 This release

2 release files

0.8.0

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page