import os import asyncio from langchain_openai import ChatOpenAI from langchain.tools import tool from deepagents import create_deep_agent from deepagents.backends import CompositeBackend, LocalShellBackend, FilesystemBackend from langchain.agents import create_agent # --- LLM configuration (OpenRouter) --- 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 for deepagents --- backend = CompositeBackend([ LocalShellBackend(workspace_dir="./workspace"), FilesystemBackend(), ]) # --- Tool with sub‑agent that returns a price table --- @tool def get_price(product: str, city: str) -> str: """Retrieve price for product in city. Returns a Markdown table: | Продукт | Цена (руб.) | Магазин | """ # Sub‑agent to generate a realistic price table sub_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, ) sub_agent = create_agent( model=sub_llm, tools=[], system_prompt=f"Generate a realistic price for {product} in {city}. Return the result as a Markdown table with columns Продукт, Цена (руб.), Магазин.", ) # Ask sub‑agent to produce the table res = sub_agent.invoke( {"messages": [{"role": "user", "content": "Provide the price table"}]} ) return res["messages"][-1]["content"] # --- Main hierarchical agent --- main_agent = create_deep_agent( model=llm, tools=[get_price], backend=backend, system_prompt="Ты помощник по планированию покупок. Принимаешь список продуктов, узнаёшь цены и считаешь итоговую стоимость.", ) async def main(): question = "Помоги составить список покупок: молоко, хлеб, яблоки. Я нахожусь в Казани." result = await main_agent.ainvoke( {"messages": [{"role": "human", "content": question}]}, {"configurable": {"thread_id": "shopping-session-1"}}, ) # Print all messages in order (tool calls and final answer) for msg in result["messages"]: if "content" in msg: print(msg["content"]) if "tool_calls" in msg: for call in msg["tool_calls"]: print(f"{call['name']}({call['args']})") # Final answer (last message) print("\n--- Final answer ---") print(result["messages"][-1]["content"]) if __name__ == "__main__": asyncio.run(main())