""" Main entry point for the assignment. This script demonstrates a deep agent that: 1. Uses `create_deep_agent` from the `deepagents` package. 2. Stores conversation history with `MemorySaver`. 3. Pauses before each tool call and asks the user for confirmation. 4. Can defend its decisions when a user contradicts the original task. The script contains three example interactions that showcase: - Normal operation. - Tool usage with confirmation. - Defending the agent's choice. """ import os from typing import Dict, Any # LLM configuration – BroJS only from langchain_openai import ChatOpenAI from deepagents import create_deep_agent from deepagents.backends import CompositeBackend, FilesystemBackend from langgraph.checkpoint.memory import MemorySaver from rich.console import Console from rich.markdown import Markdown # --------------------------------------------------------------------------- # Configuration # --------------------------------------------------------------------------- LLM = ChatOpenAI( model="openai/gpt-oss-20b:free", base_url="https://platform.brojs.ru/jrnl-bh/api/inference/v1", api_key=os.getenv("JOURNAL_MCP_PAT"), temperature=0.0, ) # Backend – virtual FS (real shell not needed for this demo). backend = CompositeBackend( default=FilesystemBackend(root_dir="./workspace", virtual_mode=True, inherit_env=True), routes={}, ) # --------------------------------------------------------------------------- # Helper tools # --------------------------------------------------------------------------- from langchain.tools import tool @tool def echo(text: str) -> str: """Return the same text – useful for demonstration.""" return f"Echo: {text}" @tool def add(a: int, b: int) -> int: """Add two integers.""" return a + b # --------------------------------------------------------------------------- # Agent creation # --------------------------------------------------------------------------- memory = MemorySaver() agent = create_deep_agent( llm=LLM, tools=[echo, add], backend=backend, system_prompt="You are an assistant that must follow the user’s instructions and can use tools. You should ask for confirmation before calling a tool.", checkpointer=memory, interrupt_before=["tools"], # pause before each tool call ) console = Console() # --------------------------------------------------------------------------- # Interaction helpers # --------------------------------------------------------------------------- async def run_interaction(messages: list[Dict[str, str]], thread_id: str) -> None: """Run a single interaction with the agent.""" config = {"configurable": {"thread_id": thread_id}} async for chunk in agent.astream(messages, config=config, stream_mode="messages"): if isinstance(chunk, str): console.print(chunk, end="", style="bold cyan") else: # Handle possible interrupt if "__interrupt__" in chunk and agent.get_state(config).next == ("tools",): console.print("\n[bold yellow]Agent wants to use a tool:[/]", style="yellow") console.print(Markdown(str(chunk))) confirm = input("Allow? (y/n) ").strip().lower() if confirm == "y": await agent.ainvoke(Command(resume=None), config) else: console.print("[red]Tool call rejected by user.[/]\n", style="red") break else: console.print(chunk, style="green") console.print("\n--- End of interaction ---\n", style="bold magenta") # --------------------------------------------------------------------------- # Main demo loop – three examples # --------------------------------------------------------------------------- if __name__ == "__main__": import asyncio async def main(): # Example 1: Simple echo await run_interaction( [{"role": "human", "content": "Say hello."}], thread_id="demo-echo", ) # Example 2: Tool usage with confirmation await run_interaction( [{"role": "human", "content": "Add 7 and 5."}], thread_id="demo-add", ) # Example 3: Defending the agent when user contradicts task await run_interaction( [ {"role": "human", "content": "I think you should not use tools at all."}, {"role": "assistant", "content": "But I need to add numbers. Let me call the tool."}, ], thread_id="demo-contradiction", ) asyncio.run(main())