6.4 KiB
6.4 KiB
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:
- Hermes calls when the agent decides to use it
- Receives parameters from the LLM
- Does work (calls external services, runs commands, etc.)
- Returns a string that Hermes shows to the agent
Tool Structure
Every Hermes tool needs:
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
def my_tool(param1: str, ...) -> str:
# Work
return "result as string"
2. Requirements Check
def check_my_tool_requirements() -> bool:
# Check external service, API key, etc.
return True # or False if not available
3. Schema (JSON)
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
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)
npx tsx level4.ts
2. Add Tool to Hermes
Option A: Copy to Hermes tools
cp pi_agent_tool.py ~/.hermes/hermes-agent/tools/
Option B: Add to Python path or custom tools directory
3. Enable in Hermes Config
# 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
# Good
return "Result: found 5 files"
# Bad
return {"result": "found 5"} # JSON must be stringified
2. Handle Errors Gracefully
try:
# Do work
return result
except Exception as e:
return f"Error: {str(e)}"
3. Add Requirements Check
def check_requirements() -> bool:
# Check API keys, services, etc.
return api_key is not None
4. Write Clear Descriptions
# 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
# In Python
result = pi_agent_tool(message="Say hello")
print(result)
2. Test with curl
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()returnsTrue - 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
# 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
# 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 |