Prolog in Python for Neurosymbolic AI
Documentation: clausal.pl · start with the Tutorial.
Neural networks are good at perception, language and pattern-matching, but are slow, resource-hungry, unreliable and need to be constrained. Symbolic AI is good at rules, reasoning and guarantees but can't deal with the real world. Clausal Prolog puts both in one Python process: a neural network can call symbolic logic that in turn calls neural predicates, nested as deeply as you like, with no serialisation, IPC or second runtime in between. Combining the two gives systems that are:
- Explainable: conclusions come from rules you can read and a derivation you can trace, not only from weights.
- Reliable: hard constraints such as regulations, safety rules and business policy hold exactly, every time, rather than approximately.
- Data-efficient: knowledge you can state as a rule doesn't have to be learned from examples.
- Correctable: change a rule and the behaviour changes, with no retraining.
Clausal Prolog is a Prolog implemented in Python that aims for ISO Prolog
conformity. Logic programs go in .clausal files, written in Clausal Prolog:
ISO syntax without cut or committed choice, which guarantees properties of
programs that let you realise The Power of Prolog.
Existing ISO Prolog goes in .pl files. The seam (.seam) is a Python-syntax
surface for the adapters that give controlled access* to the whole Python
ecosystem. All three import with Python's standard import system, and the
import rules preserve each surface's guarantees. The engine includes
constraint solving, tabling, DCGs and a large standard library.
*Python seam adaptors assume the Python programmer takes full responsibility for correctness (in the Pythonic way).
The package is clausal: pip install clausal, import clausal.
Three source surfaces
| Extension | Surface | Syntax | Use it for |
|---|---|---|---|
.clausal |
Clausal Prolog | ISO Prolog, without cut | Your logic programs. The default choice. |
.pl |
ISO Prolog | Regular ISO Prolog, cut included | External Prolog code, for Prolog systems such as Scryer or Trealla |
.seam |
Seam | Python syntax | The boundary with Python: ++ escapes, hosted Python, adapters |
All three are importable modules once clausal is imported. In one
directory, name.seam beats name.clausal, which beats name.pl.
Changed in 1.0 (the extension flip).
.clausalused to be the Python-syntax seam language. It is now Clausal Prolog, and seam source is named.seam. A seam file still named.clausalfails to load with a Prolog syntax error. To migrate, rungit mv name.clausal name.seamfor each one. Move it rather than copying it: aname.clausalleft besidename.seamis a different module, written in Prolog. See CHANGELOG.md.
Features
- Clausal Prolog: ISO syntax, ISO builtin names and error terms,
"…"as a string, and modules withmodule/2,use_module/1,2andend_module/1 - Purity by design: no cut,
->or*->; usedif/2,if_/3fromlibrary(reif), constraints and first-argument indexing instead - Constraint solving: CLP(Z) for integers, CLP(B), CLP(Q), CLP(R) and
dif/2 - SLG tabling and well-founded semantics for negation over tabled predicates
- DCGs:
-->grammar rules withphrase/2,3 - Regular ISO Prolog alongside:
.plfiles, run in the Scryer or Trealla embeddings, or imported directly (experimental) - Python interop through the seam:
library(...)facades over the engine's Python modules (library(json),library(datetime), …), Python-free.seammodules, and allowlisted Python bridges - ISO direction: ISO builtin names, ISO error terms and ISO modules; where ISO is silent, Scryer Prolog's behaviour
- C extensions: logic variables, trail-based backtracking and a trampoline, with no WAM
Installation
pip install clausal
Requires Python ≥ 3.13 and a C compiler (pip uses it automatically when building from source).
Quick start
A Clausal Prolog module
% family.clausal
:- module(family, [grandparent/2, fib/2, path/2]).
:- use_module(library(clpz)).
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).
parent(bob, pat).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
% CLP(Z) arithmetic: fib/2 runs in both directions.
fib(0, 0).
fib(1, 1).
fib(N, F) :-
N #> 1,
N1 #= N - 1, N2 #= N - 2,
F #>= N1, F #= F1 + F2,
fib(N1, F1), fib(N2, F2).
% Tabling terminates on the cycle.
:- table(path/2).
edge(1, 2).
edge(2, 3).
edge(3, 1).
path(X, Y) :- edge(X, Y).
path(X, Y) :- edge(X, Z), path(Z, Y).
test("tom's grandchildren") :- grandparent(tom, ann), grandparent(tom, pat).
test("fib(10) = 55") :- fib(10, 55).
test("which fib is 55?") :- once(fib(N, 55)), N == 10.
test("path reaches the whole cycle") :- findall(Y, path(1, Y), Ys), msort(Ys, [1, 2, 3]).
test("tom has no grandparent", fail) :- grandparent(_, tom).
:- end_module(family).
A Clausal Prolog module file must end with :- end_module(Name)..
Running it
clausal family.clausal -g "grandparent(tom, X)" # X = ann. X = pat.
clausal --test family.clausal # runs the test clauses
clausal FILE on its own runs the program's main/0. See
docs/cli.md.
Querying it from Python
Python asks the questions from a .seam file, with a goal in for
position after --:
# app.seam
-import_from(family, [grandparent, fib])
-private([tom])
for GRANDCHILD in --grandparent(tom, GRANDCHILD):
print(GRANDCHILD) # ann, then pat
for N in --fib(N, 55):
print(N) # 10
break
python -c "import clausal, app" # import clausal installs the import hook
See Python Integration for more ways to query.
Constraints, DCGs and reified conditions
% puzzles.clausal
:- module(puzzles, [greeting//0, send_more/1, classify/2]).
:- use_module(library(clpz)).
:- use_module(library(reif)).
greeting --> [hello], name.
name --> [world].
name --> [prolog].
send_more([S,E,N,D,M,O,R,Y]) :-
Vars = [S,E,N,D,M,O,R,Y],
Vars ins 0..9, all_different(Vars),
S #\= 0, M #\= 0,
1000*S + 100*E + 10*N + D + 1000*M + 100*O + 10*R + E #=
10000*M + 1000*O + 100*N + 10*E + Y,
label(Vars).
% if_/3 instead of (Cond -> Then ; Else): it stays correct when X is unbound.
classify(X, R) :- if_(X = a, R = yes, R = no).
test("dcg") :- phrase(greeting, [hello, prolog]).
test("send more money") :- send_more([9,5,6,7,1,0,8,2]).
test("if_") :- classify(a, yes), classify(b, no).
test("dif") :- dif(X, a), X = b.
:- end_module(puzzles).
What Clausal Prolog restricts
Clausal Prolog is ISO Prolog with a few deliberate rules. Each one is enforced when the file loads:
- Cut-free.
!and->are refused, and*->is not an operator. Usedif/2,if_/3,once/1, constraints or first-argument indexing. - Modules close. A module file must end with
:- end_module(Name).. A file can opt out with:- set_prolog_flag(require_end_module, false).. - One-way dependency on ISO Prolog. A
.clausalmodule may not import a.plmodule, which may use cut. It is refused withpermission_error(access, prolog_module, M). A.plmodule may import a.clausalone. - Python only through the seam. A
.clausalfile reaches Python through engine-shippedlibrary(...)facades (for example:- use_module(library(datetime), [date_add/3]).), through Python-free.seammodules, or through.seammodules listed under[tool.clausal] python_bridgesin the importing project'spyproject.toml. Anything else is refused withpermission_error(import, python_bridge, M).
See docs/importing_prolog.md for the full rules.
ISO Prolog .pl files
A .pl file is regular, external ISO Prolog: it is not restricted to the
cut-free subset, and that is why a .clausal module may not import one.
To run full ISO Prolog, cut included, alongside Clausal Prolog, use the
Scryer or
Trealla embeddings.
Importing a .pl file straight into the engine (put it on sys.path and
import it) is
experimental and outside the 1.0 compatibility promise. That in-process
loader does not run cut yet: a .pl file that uses ! or -> fails to
load there. CLAUSAL_PL_FRONTEND selects its front end (translator by
default, or native, the ISO reader that .clausal files always use).
The seam: .seam files
Code that must call Python lives in .seam files. These use the older
Python-syntax surface, with the ++expr escape, hosted Python statements
and adapters over Python libraries. A .clausal module imports a .seam
module like any other (subject to the
Python-bridge rules). Keep .seam
modules small and write your logic in Clausal Prolog. clausal-fmt and
clausal-rewrite work on .seam files only. See
docs/clausal_prolog.md for how the two surfaces
differ.
Testing
A module carries its tests inline as test/1 clauses, or as test/2
with the option fail for a goal that must have no solution:
test("fib(5) = 5") :- fib(5, 5).
test("no grandparent", fail) :- grandparent(_, tom).
Standalone runner:
python -m clausal.testing path/to/dir/ # every .seam, .clausal and .pl file
python -m clausal.testing family.clausal # a single file
python -m clausal.testing -v clausal/examples/ # verbose
Via pytest: test clauses in .seam, .clausal and .pl files are
collected automatically.
python -m pytest tests/ clausal/examples/ -q
Requirements
- Python ≥ 3.13 (no other runtime dependencies)
- C compiler (for building from source)
Optional packages (YAML, spaCy, SciPy, PyTorch, the Scryer and Trealla
embeddings, and more) live in packages/ and
are not on PyPI yet. Install one from the repository, for example:
pip install "clausal-yaml @ git+https://github.com/neurosymbolica/clausal-prolog#subdirectory=packages/clausal-yaml"
License
MIT
Metadata
Release files for clausal 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| clausal-1.0.0.tar.gz | 3.7 MB | Details |
Built distributions (wheels)
Total release size: 30.0 MB
Release files / clausal-1.0.0.tar.gz
| Download URL | clausal-1.0.0.tar.gz |
|---|---|
| Size | 3.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cc59f9e0d3000be8dcffca1fe948477718403c13c08084b62b92cc754c8774eb
|
|
BLAKE2b-256 checksum How to use checksums |
5e9ba30226d94636a14c470d30a9df201dbafe90c89e2fa47b7a8e8c44bce82d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / clausal-1.0.0-cp314-cp314-win_amd64.whl
| Download URL | clausal-1.0.0-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
e6f30f7b5c209e02814131cb9eb65cc0de9d2278cc21af1753d4f82087fff50a
|
|
BLAKE2b-256 checksum How to use checksums |
01a294db5f07c11ae9e3c9ff4003ba7525142cb618f313bca81bc24d8f24a2d9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / clausal-1.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
| Download URL | clausal-1.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.14 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 |
|
SHA-256 checksum How to use checksums |
ef2ee466cd0ee68dda17f6e5db96da5b6d429b10e8456ea3ff69e91daafcf4f7
|
|
BLAKE2b-256 checksum How to use checksums |
0d9d0b6febab26bc3cc7500efc11a4a1b999f0f9ad62e7fb5a4733df607f4d0c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / clausal-1.0.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
| Download URL | clausal-1.0.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 2.9 MB |
| Tags | CPython 3.14 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64 |
|
SHA-256 checksum How to use checksums |
b4cdac2fa9208b5feebee3049e1c3c82e11b1485a49845dfbd34705aed38bac6
|
|
BLAKE2b-256 checksum How to use checksums |
33723ea1ffeea2e1455d6c8a9ccadb4098faff90c12097b0b1a6c6603dc2f20d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / clausal-1.0.0-cp314-cp314-macosx_11_0_arm64.whl
| Download URL | clausal-1.0.0-cp314-cp314-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.14 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
80f4f52af16fc7ebb6e7769cc6fbeabda883becff8283dbbd487b91bd4b107f8
|
|
BLAKE2b-256 checksum How to use checksums |
bf556d30c5cba409259ef85fb5d881f4e75c7dfd4a753239ddebe5dde4810a71
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / clausal-1.0.0-cp314-cp314-macosx_10_15_x86_64.whl
| Download URL | clausal-1.0.0-cp314-cp314-macosx_10_15_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.14 macOS 10.15+ x86-64 |
|
SHA-256 checksum How to use checksums |
41bd86316c1093c9046ab4fed27ff55f2b03ecda8f27fc6553cec84475cdbe70
|
|
BLAKE2b-256 checksum How to use checksums |
eb297a5fc5ab3401f42b992b2b47c85d10274d4ce6c94bc3c0bceff554c8ddfb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / clausal-1.0.0-cp313-cp313-win_amd64.whl
| Download URL | clausal-1.0.0-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
c37e6192297881c12ce571ac0a3237a544be1aaa70d27ad3ba5655fbe6996085
|
|
BLAKE2b-256 checksum How to use checksums |
ac2e3a16e165ac17f70bcfc37fb0b87ba70b937e7038a5e1a765957c811a2a0d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / clausal-1.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
| Download URL | clausal-1.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.13 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 |
|
SHA-256 checksum How to use checksums |
43c875b9592b0643ef145f57249c7fda08644053b162dfb93257433bbb9c7daa
|
|
BLAKE2b-256 checksum How to use checksums |
ff72ad5215300deeef57aa0677a78b3b0ce1c9e51e46f6db4f4ae9ff7e4b2f06
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / clausal-1.0.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
| Download URL | clausal-1.0.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 2.9 MB |
| Tags | CPython 3.13 Linux glibc 2.28+ x86-64 Linux glibc 2.5+ x86-64 |
|
SHA-256 checksum How to use checksums |
f2f4cc5d683cb9ad0ec310433b8461d1b47c35f957b8adcd29283c454d1a355a
|
|
BLAKE2b-256 checksum How to use checksums |
3d5662863f360dd6e1b672ce6c00a2a786016f6dec31da765b0136a8f750cb84
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / clausal-1.0.0-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | clausal-1.0.0-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
a505bdcfbde52933eafd8626725eec643f7d720985aaef3bd569f8be88517952
|
|
BLAKE2b-256 checksum How to use checksums |
3d40438a3573270bb3e4f4734d4ce2a542b832f9bf54b690ed7b1938c2e5b262
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / clausal-1.0.0-cp313-cp313-macosx_10_13_x86_64.whl
| Download URL | clausal-1.0.0-cp313-cp313-macosx_10_13_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.13 macOS 10.13+ x86-64 |
|
SHA-256 checksum How to use checksums |
6cf7c17be181be7c316e39f5425b8e4c4033cfc837d4d4d9d00b53ed9874d6d8
|
|
BLAKE2b-256 checksum How to use checksums |
529c89fd7963c2d1fc0a0d0078afa5dfcf84e66aac245b8d14bf7b293e408234
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency log