"""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))