# Hermes Tool Implementation Guide ## Overview This document explains how to create a Hermes tool that integrates with external services (like Pi agent). --- ## What is a Hermes Tool? A Hermes tool is a Python function that: 1. **Hermes calls** when the agent decides to use it 2. **Receives parameters** from the LLM 3. **Does work** (calls external services, runs commands, etc.) 4. **Returns a string** that Hermes shows to the agent --- ## Tool Structure Every Hermes tool needs: ```python def my_tool(param1: str, param2: Optional[int] = None) -> str: """ Tool description that LLM sees. Args: param1: Description param2: Description Returns: What the tool returns """ # Do work here return "result" def check_my_tool_requirements() -> bool: """Check if tool can be used (e.g., external service available).""" return True # Schema for LLM MY_TOOL_SCHEMA = { "name": "my_tool", "description": "What the tool does", "parameters": { "type": "object", "properties": { "param1": {"type": "string", "description": "..."}, }, "required": ["param1"] } } # Register registry.register( name="my_tool", toolset="my_toolset", # Group in Hermes config schema=MY_TOOL_SCHEMA, handler=lambda args, **kw: my_tool(**args), check_fn=check_my_tool_requirements, emoji="📦", ) ``` --- ## Key Components ### 1. Function Handler ```python def my_tool(param1: str, ...) -> str: # Work return "result as string" ``` ### 2. Requirements Check ```python def check_my_tool_requirements() -> bool: # Check external service, API key, etc. return True # or False if not available ``` ### 3. Schema (JSON) ```python MY_TOOL_SCHEMA = { "name": "tool_name", "description": "What it does (LLM reads this!)", "parameters": { "type": "object", "properties": { "param1": {"type": "string", "description": "..."}, }, "required": ["param1"] } } ``` ### 4. Registry ```python registry.register( name="tool_name", toolset="toolset_name", # Enable in config schema=SCHEMA, handler=lambda args, **kw: my_tool(**args), check_fn=check_requirements, emoji="📦", ) ``` --- ## Example: Pi Agent Tool See `pi_agent_tool.py` for a working example. ### Flow ``` User: "Fix the bug in auth.py" ↓ Hermes Agent decides to use pi_agent tool ↓ Calls pi_agent_tool(message="Fix the bug...") ↓ Tool calls HTTP server (Level 4) ↓ HTTP server runs Pi agent ↓ Returns response to Hermes ↓ Hermes shows to user ``` --- ## How to Use ### 1. Start Pi Server (Level 4) ```bash npx tsx level4.ts ``` ### 2. Add Tool to Hermes Option A: Copy to Hermes tools ```bash cp pi_agent_tool.py ~/.hermes/hermes-agent/tools/ ``` Option B: Add to Python path or custom tools directory ### 3. Enable in Hermes Config ```yaml # In config.yaml toolset: - pi_agent ``` ### 4. Use in Conversation ``` User: Can you fix the bug in auth.py? Hermes: *uses pi_agent tool* Tool result: Fixed the bug by changing line 42... ``` --- ## Tool Best Practices ### 1. Always Return a String ```python # Good return "Result: found 5 files" # Bad return {"result": "found 5"} # JSON must be stringified ``` ### 2. Handle Errors Gracefully ```python try: # Do work return result except Exception as e: return f"Error: {str(e)}" ``` ### 3. Add Requirements Check ```python def check_requirements() -> bool: # Check API keys, services, etc. return api_key is not None ``` ### 4. Write Clear Descriptions ```python # Good - LLM knows when to use """ Analyze the codebase for security vulnerabilities. Use after finding potential issues. """ # Bad - LLM confused """Do something""" ``` ### 5. Keep Schema Simple - Only include needed parameters - Mark required parameters - Add descriptions for each parameter --- ## Testing ### 1. Test the Function Directly ```python # In Python result = pi_agent_tool(message="Say hello") print(result) ``` ### 2. Test with curl ```bash curl -X POST http://localhost:3000/message \ -d '{"message": "Hello"}' ``` ### 3. Test with Hermes - Add to toolset - Ask Hermes to use the tool --- ## Troubleshooting ### Tool Not Found - Check tool is in `~/.hermes/hermes-agent/tools/` - Check it's in the toolset config ### Tool Not Available - Check `check_*_requirements()` returns `True` - Check external service is running ### Tool Called but No Response - Check tool returns a string - Check for exceptions in handler --- ## Integration Options: HTTP vs Direct Spawn There are two ways to integrate Pi agent with Hermes: ### Option 1: HTTP Server (Current Implementation) ``` Hermes → Python Tool → HTTP Request → Node/TS Server → Pi Agent ``` ```python # In tool import requests response = requests.post("http://localhost:3000/message", json={"message": "..."}) return response.json()["response"] ``` **Pros:** - Easy to test/debug (curl, logs) - Stateful (agent stays alive between calls) - Reuses connections - Easier monitoring/rate-limiting **Cons:** - More complex (two services) - HTTP overhead (~50ms per call) - Server must stay running ### Option 2: Direct Spawn (Alternative) ``` Hermes → Python Tool → Spawn Process → Pi Wrapper ``` ```python # In tool import subprocess process = subprocess.Popen(["npx", "tsx", "pi-wrapper.ts", message], stdout=subprocess.PIPE) stdout, _ = process.communicate(timeout=300) return stdout.decode() ``` **Pros:** - Simpler (one process per call) - No server to maintain - Matches Kugetsu's current pattern - Good for low traffic **Cons:** - Slow startup (~100-500ms per call) - No state between calls - Harder to debug - Resource heavy under load ### Comparison Table | Factor | HTTP Server | Direct Spawn | |--------|-------------|--------------| | Latency | ~50ms | ~100-500ms | | Memory | Persistent (50-100MB) | Per-call | | State | Yes | No | | Complexity | Higher | Lower | | Debugging | Network logs | Process logs | | Best For | Production | POC/Simple | ### Recommendation - **High load / Production**: HTTP Server - **Low load / POC**: Direct Spawn - **Matches Kugetsu pattern**: Direct Spawn --- ## Files in This Project | File | Description | |------|-------------| | `pi_agent_tool.py` | Working Hermes tool (HTTP approach) | | `level4.ts` | HTTP server | | `hermes-tool-guide.md` | This document |