import os from dotenv import load_dotenv from langchain.agents import create_agent from langgraph.checkpoint.memory import InMemorySaver from langchain_community.tools import DuckDuckGoSearchRun from langchain.agents.middleware import ( ModelCallLimitMiddleware, ToolCallLimitMiddleware, ) from langchain.messages import HumanMessage, AIMessage load_dotenv() class LangChainAgent: def __init__(self): os.environ["GOOGLE_API_KEY"] = os.getenv("GEMINI_API_KEY") system_prompt = """finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.""" self.agent = create_agent( model="google_genai:gemini-2.5-flash", tools=[DuckDuckGoSearchRun()], system_prompt=system_prompt, checkpointer=InMemorySaver(), middleware=[ ModelCallLimitMiddleware(run_limit=10, exit_behavior="end"), ToolCallLimitMiddleware(run_limit=20, exit_behavior="end"), ], ) def __call__(self, question: str) -> str: print(f"Agent received question (first 50 chars): {question[:50]}...") response = self.agent.invoke( {"messages": [HumanMessage(content=question)]}, {"configurable": {"thread_id": "1"}, "recursion_limit": 50}, ) answer = response["messages"][-1].text() print(f"Agent returning answer: {answer}") return answer