The Missing Logic Agent
A neurosymbolic AI system that bridges the gap between symbolic reasoning and neural language models
DeepClause is a neurosymbolic AI system and Agent framework that bridges the gap between symbolic reasoning and neural language models. Unlike pure LLM-based agents that struggle with complex logic, multi-step reasoning, and deterministic behavior, DeepClause uses DML (DeepClause Meta Language) - a Prolog-based DSL - to encode agent behaviors as executable logic programs.
The goal of this project is to allow users to build "accountable agents." These are systems that are not only contextually aware (LLMs) and goal-oriented (Agents), but also logically sound (Prolog), introspectively explainable, and operationally safe. This integrated approach addresses the critical shortcomings of purely neural systems by embedding them within a framework of formal logic and secure execution, laying a principled foundation for the future of trustworthy autonomous systems.
DeepClause combines both paradigms: Prolog handles the logical scaffolding, control flow, and symbolic reasoning, while LLMs provide natural language understanding, semantic extraction, and content generation.
Electron/Node.js orchestration, LLM integration, tool calling
SWI-Prolog WASM module for symbolic reasoning and logic execution
V86 emulator for sandboxed Python/Bash execution
From Linear Programming to Agentic Browse Use
Watch DeepClause interact with web browsers via Playwright MCP.
See how DeepClause solves optimization problems using constraint programming.
Explore DeepClause's explainable AI capabilities with transparent reasoning and step-by-step traces.
Watch DeepClause solve complex logic puzzles using symbolic reasoning and constraint solving.
See DeepClause execute Python scripts and bash commands in a sandboxed Linux VM environment.
Simplified DML programs demonstrating DML lanaguage features
Conducts comprehensive research by orchestrating web searches, extracting information with LLM, verifying completeness with Prolog logic, and generating citation-backed reports.
% LLM extracts topic overview from search results
understand_topic(SearchResults, Topic, Overview) :-
@("Analyze `SearchResults` for `Topic`.
Generate a 2-3 sentence `Overview`.").
% LLM crafts targeted search queries
craft_queries(Topic, Overview, Queries) :-
@("Based on `Topic` and `Overview`,
generate 3-5 targeted search queries as a list.").
% LLM processes content and structures report
structure_report(AllResults, Topic, Structure, Sources) :-
@("Analyze `AllResults`. If sufficient, generate
`Structure` (outline) and `Sources` (URLs).").
agent_main :-
param("topic", "Research topic", Topic),
% Initial search and understanding
tool(web_search(Topic, num=5), InitialResults),
understand_topic(InitialResults, Topic, Overview),
% Targeted searches
craft_queries(Topic, Overview, Queries),
findall(R, (member(Q, Queries),
tool(web_search(Q, num=10), R)), Results),
% Structure and generate report
structure_report(Results, Topic, Structure, Sources),
write_report(Structure, Results, Sources, Report),
write_to_file("research_report.md", Report),
answer("Research complete! Report saved to research_report.md").
Extracts Sudoku puzzles from images using vision AI, then solves them with Prolog's CLP(FD) constraint solver. Shows hybrid AI-symbolic reasoning.
% Standard CLP(FD) Sudoku solver
parse_sudoku_string_to_prolog(String, List) :-
@("You are given a string containing a sudoku in the format `[[5,3,0,0,7,0,0,0,0], [6,0,0,1,9,5,0,0,0], ...]`,
please parse this into a valid prolog list term and output it in the List variable.
Do not use 0 for blank fields, instead use an underscore to denote a blank field.").
format_solved_grid(SolvedGrid, MarkdownGrid) :-
@("Take the `SolvedGrid`, which is a list of lists of numbers (1-9), and format it into a clean,
human-readable markdown table representing the Sudoku board. Add separators for the 3x3 blocks.
The output `MarkdownGrid` should be a single markdown string.").
% Sudoku solver using Constraint Logic Programming over Finite Domains (CLP(FD))
% This is a standard, well-known Prolog implementation for solving Sudoku.
sudoku(Rows) :-
% Ensure the grid is 9x9
length(Rows, 9),
maplist(same_length(Rows), Rows),
% Flatten the grid into a single list of variables
append(Rows, Vs),
% The domain for each variable is 1 to 9
Vs ins 1..9,
% All numbers in each row must be unique
maplist(all_distinct, Rows),
% Transpose the grid to get columns, and ensure they are also unique
transpose(Rows, Columns),
maplist(all_distinct, Columns),
% Define the 3x3 blocks and ensure they are unique
Rows = [A,B,C,D,E,F,G,H,I],
blocks(A, B, C),
blocks(D, E, F),
blocks(G, H, I),
% Find a valid assignment of numbers to the variables
maplist(labeling([ff]), Rows).
% Helper for the solver: defines the 3x3 block constraint
blocks([], [], []).
blocks([N1,N2,N3|Ns1], [N4,N5,N6|Ns2], [N7,N8,N9|Ns3]) :-
all_distinct([N1,N2,N3,N4,N5,N6,N7,N8,N9]),
blocks(Ns1, Ns2, Ns3).
% Main agent logic
% Branch 1: Successful image recognition and solving
agent_main :-
param("image_path:file", "The path to the image file containing the Sudoku puzzle.", ImagePath),
( ImagePath \= "" -> true ; (log(error="The 'image_path' parameter is missing."), fail) ),
log(task="Attempting to solve Sudoku directly from the image: '{ImagePath}'."),
% Step 1: Use the visualizer tool to perform OCR and extract the grid
log(task="Analyzing image to extract the puzzle grid and numbers."),
tool(visualizer(ImagePath,"Identify the Sudoku grid. Perform
Optical Character Recognition (OCR) on each cell.
Represent the grid as a Prolog list of lists, where each inner list is a row.
Use the integer 0 to represent empty cells. The output `SudokuGrid` must be in this
format, for example: `[[5,3,0,0,7,0,0,0,0], [6,0,0,1,9,5,0,0,0], ...]`.
If a valid 9x9 grid cannot be reliably extracted, then output nothing"), ToolOutput),
parse_sudoku_string_to_prolog(ToolOutput, UnsolvedGrid),
( UnsolvedGrid \= [] ->
log(task="Successfully extracted the grid from the image.")\
;
(log(error="Could not recognize a valid Sudoku grid in the image."), fail)
),
yield("Grid = {UnsolvedGrid}"),
% Step 2: Solve the puzzle using the CLP(FD) solver
log(task="Solving the puzzle..."),
sudoku(UnsolvedGrid), % This predicate solves the grid by unifying the variables
log(task="Puzzle solved successfully."),
% Step 3: Format the solved grid into a markdown table
log(task="Formatting the solution for display."),
format_solved_grid(UnsolvedGrid, SolvedGridMarkdown),
end_thinking,
system("You are a helpful assistant that has just solved a Sudoku puzzle from an image for the user."),
observation("I have successfully analyzed the image, extracted the puzzle, and found the solution."),
observation(SolvedGridMarkdown),
chat("Please give me the solution to this Sudoku.").