diff --git a/main.py b/main.py new file mode 100644 index 0000000..1acd46c --- /dev/null +++ b/main.py @@ -0,0 +1,81 @@ +"""Deep agent: web search + virtual files → real filesystem export.""" +import os +import asyncio +from pathlib import Path + +from dotenv import load_dotenv +from langchain_openai import ChatOpenAI +from langchain_core.messages import HumanMessage +from langchain.tools import tool +from deepagents import create_deep_agent +from deepagents.backends import LocalShellBackend, CompositeBackend + +load_dotenv() + +llm = ChatOpenAI( + model="openai/gpt-oss-20b:free", + base_url="https://openrouter.ai/api/v1", + api_key=os.getenv("OPENAI_API_KEY"), + temperature=0.0, +) + +WORKSPACE = Path("./workspace") +REAL_OUT = Path("./output") + + +@tool +def web_search(query: str) -> str: + """Search the web for information and return snippets.""" + try: + from duckduckgo_search import DDGS + with DDGS() as ddgs: + results = list(ddgs.text(query, max_results=5)) + return "\n".join(f"{r['title']}: {r['body']}" for r in results) + except Exception as exc: + return f"Search error: {exc}" + + +backend = CompositeBackend( + default=LocalShellBackend( + root_dir=str(WORKSPACE), + virtual_mode=True, + inherit_env=True, + ), +) + +agent = create_deep_agent( + model=llm, + tools=[web_search], + backend=backend, + system_prompt=( + "You are a research agent. " + "Use web_search to find information, then create virtual files with write_file. " + "When done, export all virtual files to real filesystem by calling execute with " + "a shell command that copies /virtual/ contents to the output directory." + ), +) + + +async def main(query: str = "Python LangChain agent best practices 2024") -> None: + WORKSPACE.mkdir(parents=True, exist_ok=True) + REAL_OUT.mkdir(parents=True, exist_ok=True) + + config = {"configurable": {"thread_id": "research-session-1"}} + result = await agent.ainvoke( + {"messages": [HumanMessage( + content=( + f"Search the web for: {query}\n" + "Save your findings to results.txt as a virtual file.\n" + "Then export the virtual file results.txt to the real filesystem " + f"at {REAL_OUT}/results.txt" + ) + )]}, + config, + ) + print(result["messages"][-1].content) + + +if __name__ == "__main__": + import sys + q = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else "Python LangChain agent best practices 2024" + asyncio.run(main(q))