A coding guide to build a reactive tool agent merging the logic of Prolog with Gemini and Langgraph

by Brenden Burgess

When you buy through links on our site, we may earn a commission at no extra cost to you. However, this does not influence our evaluations.

In this tutorial, we walk through a practical fusion of symbolic logic and generating AI. We have configured Pyswip to integrate a Prolog Knowledge base, wrap your predicates as Langchain tools, then wire everything in a reactive style agent. Alongside the way, we are setting up family relationship rules, mathematical predicates such as factorial and list the public services, then leaving the planting agent, appeal tools and reason on the results. At the end of the configuration, we can issue questions in natural language and look at the agent translate them into precise prologue queries, assemble responses in several stages and return JSON structured ideas.

!apt-get install swi-prolog -y
!pip install pyswip langchain-google-genai langgraph langchain-core

We install Swi-Prolog with Apt-Get, then add Pyswip, the Google Genai, Langgraph and Core Langchain de Langchain packages via PIP so that we can reject the PROology logic with our agent propelled by the Gemini. With these outbuildings in place, we are ready to code, question and orchestrate from start to finish.

import os
from pyswip import Prolog
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.messages import HumanMessage
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
import json


GOOGLE_API_KEY = "Use Your Own API Key Here"
os.environ("GOOGLE_API_KEY") = GOOGLE_API_KEY


llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", temperature=0)

We load our base battery, including Pyswip for Prolog, Langchain and Langgraph for tools, and Gemini 1.5 Flash for LLM power. We then define the Google_Api_Key environment variable so that the model can authenticate. With the LLM initialized at zero temperature, we are ready to obtain deterministic and logical answers from our agent.

class AdvancedPrologInterface:
   def __init__(self):
       self.prolog = Prolog()
       self._load_knowledge_base()
  
   def _load_knowledge_base(self):
       """Load comprehensive Prolog knowledge base"""
       rules = (
           "parent(john, mary, alice)",
           "parent(john, mary, bob)",
           "parent(bob, susan, charlie)",
           "parent(alice, david, emma)",
           "parent(charlie, lisa, frank)",
          
           "male(john)", "male(bob)", "male(david)", "male(charlie)", "male(frank)",
           "female(mary)", "female(alice)", "female(susan)", "female(emma)", "female(lisa)",
          
           "grandparent(X, Z) :- parent(X, _, Y), parent(Y, _, Z)",
           "sibling(X, Y) :- parent(P1, P2, X), parent(P1, P2, Y), X \\= Y",
           "uncle(X, Y) :- sibling(X, Z), parent(Z, _, Y), male(X)",
           "aunt(X, Y) :- sibling(X, Z), parent(Z, _, Y), female(X)",
           "cousin(X, Y) :- parent(P1, _, X), parent(P2, _, Y), sibling(P1, P2)",
          
           "factorial(0, 1)",
           "factorial(N, F) :- N > 0, N1 is N - 1, factorial(N1, F1), F is N * F1",
          
           "list_member(X, (X|_))",
           "list_member(X, (_|T)) :- list_member(X, T)",
           "list_length((), 0)",
           "list_length((_|T), N) :- list_length(T, N1), N is N1 + 1",
          
           "animal(dog)", "animal(cat)", "animal(whale)", "animal(eagle)",
           "mammal(dog)", "mammal(cat)", "mammal(whale)",
           "bird(eagle)", "bird(sparrow)",
           "can_fly(eagle)", "can_fly(sparrow)",
           "can_swim(whale)", "can_swim(fish)",
           "aquatic_mammal(X) :- mammal(X), can_swim(X)"
       )
      
       for rule in rules:
           try:
               self.prolog.assertz(rule)
           except Exception as e:
               print(f"Warning: Could not assert rule '{rule}': {e}")
  
   def query(self, query_string):
       """Execute Prolog query and return results"""
       try:
           results = list(self.prolog.query(query_string))
           return results if results else ({"result": "No solutions found"})
       except Exception as e:
           return ({"error": f"Query failed: {str(e)}"})

We wrap Swi-Prolog in a Prologinter Advanced, load a rich rule / base of facts on INIT and affirm each clause safely. We then exhibit a Query () method which performs any PROLOG objective and returns JSON user-friendly results (or a clear error / non-development message), which allows us to drive logical requests directly from Python.

prolog_interface = AdvancedPrologInterface()


@tool
def family_relationships(query: str) -> str:
   """
   Query family relationships in Prolog format.
   Examples: 'parent(john, mary, X)', 'sibling(X, Y)', 'grandparent(X, charlie)'
   """
   results = prolog_interface.query(query)
   return json.dumps(results, indent=2)


@tool
def mathematical_operations(operation: str, number: int) -> str:
   """
   Perform mathematical operations using Prolog.
   Supported operations: 'factorial'
   Example: operation='factorial', number=5
   """
   if operation == "factorial":
       query = f"factorial({number}, Result)"
       results = prolog_interface.query(query)
       return json.dumps(results, indent=2)
   else:
       return json.dumps(({"error": f"Operation '{operation}' not supported"}))


@tool
def advanced_queries(query_type: str, entity: str = "") -> str:
   """
   Perform advanced relationship queries.
   Types: 'all_children', 'all_grandchildren', 'all_siblings', 'all_cousins'
   """
   queries = {
       'all_children': f"parent(_, _, {entity})" if entity else "parent(_, _, X)",
       'all_grandchildren': f"grandparent(_, {entity})" if entity else "grandparent(_, X)",
       'all_siblings': f"sibling({entity}, X)" if entity else "sibling(X, Y)",
       'all_cousins': f"cousin({entity}, X)" if entity else "cousin(X, Y)"
   }
  
   if query_type in queries:
       results = prolog_interface.query(queries(query_type))
       return json.dumps(results, indent=2)
   else:
       return json.dumps(({"error": f"Query type '{query_type}' not supported"}))

We instance AdvancedProloginterface, then wrap his requests as Langchain tools, such as Family_relationships, Mathematical_operations and Advanced_queries, so that we can call the specific PROologic Objectives of Natural Language. We define each tool to format and send the right request (such as factorial research / 2 or cousin) and return to clean JSON, allowing our agent to orchestrate logical calls in a transparent manner.

tools = (family_relationships, mathematical_operations, advanced_queries)
agent = create_react_agent(llm, tools)


def run_family_analysis():
   """Comprehensive family relationship analysis"""
   print("👨‍👩‍👧‍👦 Family Relationship Analysis")
   print("=" * 50)
  
   queries = (
       "Who are all the parents in the family database?",
       "Find all grandparent-grandchild relationships",
       "Show me all the siblings in the family",
       "Who are John and Mary's children?",
       "Calculate the factorial of 6 using Prolog"
   )
  
   for i, query in enumerate(queries, 1):
       print(f"\n🔍 Query {i}: {query}")
       print("-" * 30)
      
       try:
           response = agent.invoke({"messages": (("human", query))})
           answer = response("messages")(-1).content
           print(f"🤖 Response: {answer}")
       except Exception as e:
           print(f"❌ Error: {str(e)}")


def demonstrate_complex_reasoning():
   """Show advanced multi-step reasoning"""
   print("\n🧠 Complex Multi-Step Reasoning")
   print("=" * 40)
  
   complex_query = """
   I want a complete family tree analysis. Please:
   1. List all parent-child relationships
   2. Identify all grandparent relationships 
   3. Find any uncle/aunt relationships
   4. Show cousin relationships
   5. Calculate factorial of 4 as a bonus math operation
   """
  
   print(f"Complex Query: {complex_query}")
   print("-" * 40)
  
   try:
       response = agent.invoke({"messages": (("human", complex_query))})
       print(f"📋 Comprehensive Analysis:\n{response('messages')(-1).content}")
   except Exception as e:
       print(f"❌ Error in complex reasoning: {str(e)}")


def interactive_prolog_session():
   """Interactive Prolog knowledge base exploration"""
   print("\n💬 Interactive Prolog Explorer")
   print("Ask about family relationships, math operations, or general queries!")
   print("Type 'examples' to see sample queries, 'quit' to exit")
   print("-" * 50)
  
   examples = (
       "Who are Bob's children?",
       "Find all grandparents in the family",
       "Calculate factorial of 5",
       "Show me all cousin relationships",
       "Who are Alice's siblings?"
   )
  
   while True:
       user_input = input("\n🧑 You: ")
      
       if user_input.lower() == 'quit':
           print("👋 Goodbye!")
           break
       elif user_input.lower() == 'examples':
           print("📝 Example queries:")
           for ex in examples:
               print(f"  • {ex}")
           continue
          
       try:
           response = agent.invoke({"messages": (("human", user_input))})
           print(f"🤖 AI: {response('messages')(-1).content}")
       except Exception as e:
           print(f"❌ Error: {str(e)}")

We record our three Prolog tools, turn a react agent around the Gemini, then script aid routines, run_family_analysis, demonstrate_ supplex_reasoning and an interactive loop, to dismiss requests in natural language that the agent translates into Prologs calls. In this way, we test simple prompts, reasoning in several stages and live questions and answers, while keeping the transparent and overflowing logical layer.

def test_direct_queries():
   """Test direct Prolog queries for verification"""
   print("\n🔬 Direct Prolog Query Testing")
   print("=" * 35)
  
   test_queries = (
       ("parent(john, mary, X)", "Find John and Mary's children"),
       ("grandparent(X, charlie)", "Find Charlie's grandparents"),
       ("sibling(alice, X)", "Find Alice's siblings"),
       ("factorial(4, X)", "Calculate 4 factorial"),
       ("cousin(X, Y)", "Find all cousin pairs")
   )
  
   for query, description in test_queries:
       print(f"\n📋 {description}")
       print(f"Query: {query}")
       results = prolog_interface.query(query)
       print(f"Results: {json.dumps(results, indent=2)}")




def main():
   """Main demonstration runner"""
   if GOOGLE_API_KEY == "YOUR_GEMINI_API_KEY_HERE":
       print("⚠️  Please set your Gemini API key in Cell 3!")
       print("Get it from: https://aistudio.google.com/app/apikey")
       return
  
   print("🚀 Advanced Prolog + Gemini Integration")
   print("Using PySwip for stable Prolog integration")
   print("=" * 55)
  
   test_direct_queries()
   run_family_analysis()
   demonstrate_complex_reasoning()
  
 def show_mathematical_capabilities():
   """Demonstrate mathematical reasoning with Prolog"""
   print("\n🔢 Mathematical Reasoning with Prolog")
   print("=" * 40)
  
   math_queries = (
       "Calculate factorial of 3, 4, and 5",
       "What is the factorial of 7?",
       "Show me how factorial calculation works step by step"
   )
  
   for query in math_queries:
       print(f"\n🧮 Math Query: {query}")
       try:
           response = agent.invoke({"messages": (("human", query))})
           print(f"📊 Result: {response('messages')(-1).content}")
       except Exception as e:
           print(f"❌ Error: {str(e)}")


if __name__ == "__main__":
   main()
   show_mathematical_capabilities()
  
   print("\n✅ Tutorial completed successfully!")
   print("🎯 Key achievements:")
   print("  • Integrated PySwip with Gemini AI")
   print("  • Created advanced Prolog reasoning tools")
   print("  • Demonstrated complex family relationship queries")
   print("  • Implemented mathematical operations in Prolog")
   print("  • Built interactive AI agent with logical reasoning")
   print("\n🚀 Try extending with your own Prolog rules and facts!")

We cuddle everything together in hand () to verify our objectives of Prolog, carry out family analysis and present the reasoning in several stages, then show_mathematical_capabilitities () underlines the factory requests of natural language. We conclude by printing a rapid summary of what we have built so far, allowing us to extend the battery with confidence with new rules or to exchange models afterwards.

In conclusion, we have shown that symbolic reasoning and LLM complement each other beautifully: Prolog guarantees the accuracy of well -defined logic, while Gemini manages the understanding and orchestration of flexible language. We are leaving with work scaffolding, direct prologue requests for verification, predicates wrapped in tools for agents and demonstration functions for complex and mathematical genealogical trees. From there, we are ready to extend the knowledge base, to add new areas (such as finance rules, game logic and knowledge graphics) or to exchange in different LLM. We are also positioned to exhibit this battery via a user interface or an interactive API, allowing others to explore the AI guided by logic in real time.


Discover the Complete codes. All the merit of this research goes to researchers in this project.

Meet the newsletter of AI dev read by 40K + developers and researchers from Nvidia, Openai, Deepmind, Meta, Microsoft, JP Morgan Chase, Amgen, Aflac, Wells Fargo and 100 others (Subscribe now)


Screen Shot 2021 09 14 at 9.02.24 AM

Asif Razzaq is the CEO of Marktechpost Media Inc .. as a visionary entrepreneur and engineer, AIF undertakes to exploit the potential of artificial intelligence for social good. His most recent company is the launch of an artificial intelligence media platform, Marktechpost, which stands out from its in-depth coverage of automatic learning and in-depth learning news which are both technically solid and easily understandable by a large audience. The platform has more than 2 million monthly views, illustrating its popularity with the public.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.