import os import asyncio from langchain_openai import ChatOpenAI from langchain.tools import tool from langchain.agents import create_agent from langchain_core.messages import HumanMessage from deepagents import create_deep_agent from deepagents.backends import CompositeBackend, LocalShellBackend, FilesystemBackend # ---------- LLM ---------- # Use OpenRouter – cloud API, no local GPU required llm = ChatOpenAI( model="openai/gpt-oss-20b:free", base_url="https://openrouter.ai/api/v1", api_key=os.getenv("OPENAI_API_KEY"), temperature=0.7, ) # ---------- Backend ---------- backend = CompositeBackend([ LocalShellBackend(workspace_dir="./workspace"), FilesystemBackend(), ]) # ---------- Tool with sub‑agent ---------- @tool def get_price(product: str, city: str) -> str: """Return a realistic price table for a product in a city. The tool internally creates a sub‑agent that generates the table. """ # Sub‑agent that simply produces a price table sub_agent = create_agent( model=llm, tools=[], system_prompt=f"You are a price estimator for {city}. Provide a realistic price for {product} in a table format.", ) prompt = ( f"Generate a table with columns Продукт, Цена (руб.), Магазин for product '{product}' in city '{city}'." ) result = sub_agent.invoke({"messages": [HumanMessage(content=prompt)]}) # The last message contains the table return result["messages"][-1].content # ---------- Main agent ---------- agent = create_deep_agent( model=llm, tools=[get_price], backend=backend, system_prompt="Ты помощник по планированию покупок.", ) # ---------- Helper to pretty‑print messages ---------- def format_message(msg): if hasattr(msg, "content") and msg.content: return msg.content if hasattr(msg, "tool_calls") and msg.tool_calls: call = msg.tool_calls[0] return f"{call['name']}({call['args']})" return "" # ---------- Main execution ---------- async def main(): user_query = "Помоги составить список покупок: молоко, хлеб, яблоки. Я нахожусь в Казани." result = await agent.ainvoke( {"messages": [HumanMessage(content=user_query)]}, {"configurable": {"thread_id": "session-1"}}, ) # Print all messages in order for msg in result["messages"]: print(format_message(msg)) print("---") if __name__ == "__main__": asyncio.run(main())