|
|
"""Example 4: Full Agent with All Features |
|
|
|
|
|
This example demonstrates a complete agent setup with: |
|
|
- All basic tools (Read, Write, Edit, Bash) |
|
|
- Session Note tools for memory |
|
|
- MCP tools (Memory, Search, etc.) |
|
|
- Skills integration |
|
|
|
|
|
Based on: tests/test_integration.py |
|
|
""" |
|
|
|
|
|
import asyncio |
|
|
import tempfile |
|
|
from pathlib import Path |
|
|
|
|
|
from mini_agent import LLMClient |
|
|
from mini_agent.agent import Agent |
|
|
from mini_agent.config import Config |
|
|
from mini_agent.tools import BashTool, EditTool, ReadTool, WriteTool |
|
|
from mini_agent.tools.mcp_loader import load_mcp_tools_async |
|
|
from mini_agent.tools.note_tool import RecallNoteTool, SessionNoteTool |
|
|
|
|
|
|
|
|
async def demo_full_agent(): |
|
|
"""Demo: Full-featured agent with all capabilities.""" |
|
|
print("\n" + "=" * 60) |
|
|
print("Full Mini Agent - All Features Enabled") |
|
|
print("=" * 60) |
|
|
|
|
|
|
|
|
config_path = Path("mini_agent/config/config.yaml") |
|
|
if not config_path.exists(): |
|
|
print("β config.yaml not found. Please run:") |
|
|
print(" cp mini_agent/config/config-example.yaml mini_agent/config/config.yaml") |
|
|
return |
|
|
|
|
|
config = Config.from_yaml(config_path) |
|
|
|
|
|
|
|
|
if not config.llm.api_key or config.llm.api_key.startswith("YOUR_"): |
|
|
print("β API key not configured in config.yaml") |
|
|
return |
|
|
|
|
|
|
|
|
with tempfile.TemporaryDirectory() as workspace_dir: |
|
|
print(f"π Workspace: {workspace_dir}") |
|
|
|
|
|
|
|
|
system_prompt_path = Path("mini_agent/config/system_prompt.md") |
|
|
if system_prompt_path.exists(): |
|
|
system_prompt = system_prompt_path.read_text(encoding="utf-8") |
|
|
else: |
|
|
system_prompt = "You are a helpful AI assistant." |
|
|
|
|
|
|
|
|
note_instructions = """ |
|
|
|
|
|
IMPORTANT - Session Memory: |
|
|
You have record_note and recall_notes tools. Use them to: |
|
|
- Save important facts, decisions, and context |
|
|
- Recall previous information across conversations |
|
|
""" |
|
|
system_prompt += note_instructions |
|
|
|
|
|
|
|
|
llm_client = LLMClient( |
|
|
api_key=config.llm.api_key, |
|
|
api_base=config.llm.api_base, |
|
|
model=config.llm.model, |
|
|
) |
|
|
|
|
|
|
|
|
tools = [ |
|
|
ReadTool(workspace_dir=workspace_dir), |
|
|
WriteTool(workspace_dir=workspace_dir), |
|
|
EditTool(workspace_dir=workspace_dir), |
|
|
BashTool(), |
|
|
] |
|
|
print("β Loaded 4 basic tools") |
|
|
|
|
|
|
|
|
memory_file = Path(workspace_dir) / ".agent_memory.json" |
|
|
tools.extend( |
|
|
[ |
|
|
SessionNoteTool(memory_file=str(memory_file)), |
|
|
RecallNoteTool(memory_file=str(memory_file)), |
|
|
] |
|
|
) |
|
|
print("β Loaded 2 Session Note tools") |
|
|
|
|
|
|
|
|
try: |
|
|
mcp_tools = await load_mcp_tools_async(config_path="mini_agent/config/mcp.json") |
|
|
if mcp_tools: |
|
|
tools.extend(mcp_tools) |
|
|
print(f"β Loaded {len(mcp_tools)} MCP tools") |
|
|
else: |
|
|
print("β οΈ No MCP tools configured (mcp.json is empty or disabled)") |
|
|
except Exception as e: |
|
|
print(f"β οΈ MCP tools not loaded: {e}") |
|
|
|
|
|
|
|
|
agent = Agent( |
|
|
llm_client=llm_client, |
|
|
system_prompt=system_prompt, |
|
|
tools=tools, |
|
|
max_steps=config.agent.max_steps, |
|
|
workspace_dir=workspace_dir, |
|
|
) |
|
|
|
|
|
print(f"\nπ€ Agent created with {len(tools)} total tools\n") |
|
|
|
|
|
|
|
|
task = """ |
|
|
Please help me with the following tasks: |
|
|
|
|
|
1. Create a Python script called 'calculator.py' that: |
|
|
- Has functions for add, subtract, multiply, divide |
|
|
- Has a main() function that demonstrates usage |
|
|
- Includes proper docstrings and type hints |
|
|
|
|
|
2. Create a README.md file that: |
|
|
- Describes the calculator script |
|
|
- Shows how to run it |
|
|
- Lists the available functions |
|
|
|
|
|
3. Test the calculator by running it with bash |
|
|
|
|
|
4. Remember this project info: |
|
|
- Project: Simple Calculator |
|
|
- Language: Python |
|
|
- Purpose: Demonstration of agent capabilities |
|
|
""" |
|
|
|
|
|
print("=" * 60) |
|
|
print("π Task:") |
|
|
print("=" * 60) |
|
|
print(task) |
|
|
print("\n" + "=" * 60) |
|
|
print("π€ Agent is working...\n") |
|
|
|
|
|
agent.add_user_message(task) |
|
|
|
|
|
try: |
|
|
result = await agent.run() |
|
|
|
|
|
print("\n" + "=" * 60) |
|
|
print("β
Agent completed!") |
|
|
print("=" * 60) |
|
|
print(f"\nAgent's final response:\n{result}\n") |
|
|
|
|
|
|
|
|
print("=" * 60) |
|
|
print("π Created files in workspace:") |
|
|
print("=" * 60) |
|
|
|
|
|
workspace = Path(workspace_dir) |
|
|
for file in workspace.glob("*"): |
|
|
if file.is_file() and not file.name.startswith("."): |
|
|
print(f"\nπ {file.name}:") |
|
|
print("-" * 60) |
|
|
content = file.read_text() |
|
|
|
|
|
lines = content.split("\n")[:20] |
|
|
print("\n".join(lines)) |
|
|
if len(content.split("\n")) > 20: |
|
|
print("... (truncated)") |
|
|
print("-" * 60) |
|
|
|
|
|
|
|
|
if memory_file.exists(): |
|
|
import json |
|
|
|
|
|
notes = json.loads(memory_file.read_text()) |
|
|
print(f"\nπΎ Session notes recorded: {len(notes)}") |
|
|
for note in notes: |
|
|
print(f" - [{note['category']}] {note['content'][:60]}...") |
|
|
|
|
|
except Exception as e: |
|
|
print(f"β Error during agent execution: {e}") |
|
|
import traceback |
|
|
|
|
|
traceback.print_exc() |
|
|
|
|
|
|
|
|
async def demo_interactive_mode(): |
|
|
"""Demo: Interactive conversation with agent.""" |
|
|
print("\n" + "=" * 60) |
|
|
print("Interactive Mini Agent") |
|
|
print("=" * 60) |
|
|
print("\nThis demo shows multi-turn conversation.") |
|
|
print("(In production, use `mini-agent` for full interactive mode)") |
|
|
|
|
|
|
|
|
config_path = Path("mini_agent/config/config.yaml") |
|
|
if not config_path.exists(): |
|
|
print("β config.yaml not found") |
|
|
return |
|
|
|
|
|
config = Config.from_yaml(config_path) |
|
|
|
|
|
if not config.llm.api_key or config.llm.api_key.startswith("YOUR_"): |
|
|
print("β API key not configured") |
|
|
return |
|
|
|
|
|
with tempfile.TemporaryDirectory() as workspace_dir: |
|
|
|
|
|
system_prompt = "You are a helpful assistant with access to tools." |
|
|
llm_client = LLMClient( |
|
|
api_key=config.llm.api_key, |
|
|
api_base=config.llm.api_base, |
|
|
model=config.llm.model, |
|
|
) |
|
|
|
|
|
tools = [ |
|
|
WriteTool(workspace_dir=workspace_dir), |
|
|
ReadTool(workspace_dir=workspace_dir), |
|
|
BashTool(), |
|
|
] |
|
|
|
|
|
agent = Agent( |
|
|
llm_client=llm_client, |
|
|
system_prompt=system_prompt, |
|
|
tools=tools, |
|
|
max_steps=20, |
|
|
workspace_dir=workspace_dir, |
|
|
) |
|
|
|
|
|
|
|
|
conversations = [ |
|
|
"Create a file called 'data.txt' with the numbers 1 to 5, one per line.", |
|
|
"Now read the file and tell me what's in it.", |
|
|
"Count how many lines are in the file using bash.", |
|
|
] |
|
|
|
|
|
for i, message in enumerate(conversations, 1): |
|
|
print(f"\n{'=' * 60}") |
|
|
print(f"Turn {i}:") |
|
|
print(f"{'=' * 60}") |
|
|
print(f"User: {message}\n") |
|
|
|
|
|
agent.add_user_message(message) |
|
|
|
|
|
try: |
|
|
result = await agent.run() |
|
|
print(f"Agent: {result}\n") |
|
|
except Exception as e: |
|
|
print(f"Error: {e}") |
|
|
break |
|
|
|
|
|
|
|
|
async def main(): |
|
|
"""Run all demos.""" |
|
|
print("=" * 60) |
|
|
print("Full Agent Examples") |
|
|
print("=" * 60) |
|
|
print("\nThese examples demonstrate the complete agent capabilities:") |
|
|
print("- All basic tools (file operations, bash)") |
|
|
print("- Session memory (persistent notes)") |
|
|
print("- MCP tools (if configured)") |
|
|
print("- Multi-turn conversations\n") |
|
|
|
|
|
|
|
|
await demo_full_agent() |
|
|
print("\n" * 2) |
|
|
await demo_interactive_mode() |
|
|
|
|
|
print("\n" + "=" * 60) |
|
|
print("All demos completed! β
") |
|
|
print("=" * 60) |
|
|
print("\nπ‘ Next step: Try the interactive mode with:") |
|
|
print(" mini-agent\n") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
asyncio.run(main()) |
|
|
|