openhoof 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openhoof-2.0.0/.gitignore +90 -0
- openhoof-2.0.0/PKG-INFO +459 -0
- openhoof-2.0.0/README.md +423 -0
- openhoof-2.0.0/docs/AGENTS.md +297 -0
- openhoof-2.0.0/docs/AGENT_TEMPLATES.md +437 -0
- openhoof-2.0.0/docs/API.md +383 -0
- openhoof-2.0.0/docs/ARCHITECTURE.md +249 -0
- openhoof-2.0.0/docs/BLOG_POST.md +301 -0
- openhoof-2.0.0/docs/BUILTIN_TOOLS.md +218 -0
- openhoof-2.0.0/docs/CONTEXT_MANAGEMENT.md +313 -0
- openhoof-2.0.0/docs/GETTING_STARTED.md +184 -0
- openhoof-2.0.0/docs/IMPLEMENTATION_SUMMARY.md +317 -0
- openhoof-2.0.0/docs/LLAMAFARM.md +278 -0
- openhoof-2.0.0/docs/LLAMAFARM_V2.md +246 -0
- openhoof-2.0.0/docs/OVERHAUL_PLAN.md +161 -0
- openhoof-2.0.0/docs/QUICKSTART.md +205 -0
- openhoof-2.0.0/docs/TOKEN_BUDGET.md +433 -0
- openhoof-2.0.0/docs/TOOLS.md +345 -0
- openhoof-2.0.0/docs/TOOL_GUIDANCE.md +509 -0
- openhoof-2.0.0/docs/TRIGGERS.md +307 -0
- openhoof-2.0.0/docs/openhoof-logo.png +0 -0
- openhoof-2.0.0/experiments/test_function_pipeline.py +356 -0
- openhoof-2.0.0/experiments/test_pipeline_direct.py +455 -0
- openhoof-2.0.0/integrations/atmosphere_client.py +398 -0
- openhoof-2.0.0/integrations/horizon_integration.py +254 -0
- openhoof-2.0.0/integrations/medical_wing_integration.py +459 -0
- openhoof-2.0.0/llamafarm.yaml +72 -0
- openhoof-2.0.0/openhoof/__init__.py +82 -0
- openhoof-2.0.0/openhoof/__main__.py +6 -0
- openhoof-2.0.0/openhoof/agent.py +387 -0
- openhoof-2.0.0/openhoof/bootstrap.py +110 -0
- openhoof-2.0.0/openhoof/builtin_tools/__init__.py +318 -0
- openhoof-2.0.0/openhoof/builtin_tools/context.py +107 -0
- openhoof-2.0.0/openhoof/builtin_tools/logging.py +77 -0
- openhoof-2.0.0/openhoof/builtin_tools/memory.py +162 -0
- openhoof-2.0.0/openhoof/builtin_tools/mission.py +195 -0
- openhoof-2.0.0/openhoof/builtin_tools/state.py +91 -0
- openhoof-2.0.0/openhoof/builtin_tools/time_tools.py +21 -0
- openhoof-2.0.0/openhoof/builtin_tools/tool_schema.py +75 -0
- openhoof-2.0.0/openhoof/config.py +116 -0
- openhoof-2.0.0/openhoof/ddil.py +144 -0
- openhoof-2.0.0/openhoof/events.py +116 -0
- openhoof-2.0.0/openhoof/heartbeat.py +117 -0
- openhoof-2.0.0/openhoof/memory.py +131 -0
- openhoof-2.0.0/openhoof/models.py +270 -0
- openhoof-2.0.0/openhoof/soul.py +73 -0
- openhoof-2.0.0/openhoof/templates/AGENTS.md +71 -0
- openhoof-2.0.0/openhoof/templates/HEARTBEAT.md +12 -0
- openhoof-2.0.0/openhoof/templates/IDENTITY.md +5 -0
- openhoof-2.0.0/openhoof/templates/TOOLS.md +37 -0
- openhoof-2.0.0/openhoof/templates/USER.md +9 -0
- openhoof-2.0.0/openhoof/tool_registry.py +158 -0
- openhoof-2.0.0/openhoof/tools/__init__.py +11 -0
- openhoof-2.0.0/openhoof/tools/base.py +89 -0
- openhoof-2.0.0/openhoof/tools/builtin/__init__.py +38 -0
- openhoof-2.0.0/openhoof/tools/builtin/exec.py +109 -0
- openhoof-2.0.0/openhoof/tools/builtin/memory.py +153 -0
- openhoof-2.0.0/openhoof/tools/builtin/notify.py +87 -0
- openhoof-2.0.0/openhoof/tools/builtin/shared.py +310 -0
- openhoof-2.0.0/openhoof/tools/builtin/spawn.py +94 -0
- openhoof-2.0.0/openhoof/tools/registry.py +71 -0
- openhoof-2.0.0/openhoof/training.py +151 -0
- openhoof-2.0.0/pyproject.toml +87 -0
- openhoof-2.0.0/tests/__init__.py +1 -0
- openhoof-2.0.0/tests/conftest.py +79 -0
- openhoof-2.0.0/tests/test_api.py +187 -0
- openhoof-2.0.0/tests/test_builtin_tools.py +291 -0
- openhoof-2.0.0/tests/test_events.py +106 -0
- openhoof-2.0.0/tests/test_max_turns.py +59 -0
- openhoof-2.0.0/tests/test_multi_tool.py +275 -0
- openhoof-2.0.0/tests/test_sessions.py +77 -0
- openhoof-2.0.0/tests/test_simple.py +111 -0
- openhoof-2.0.0/tests/test_tools.py +175 -0
- openhoof-2.0.0/tests/test_transcripts.py +116 -0
- openhoof-2.0.0/tests/test_with_llm.py +128 -0
- openhoof-2.0.0/tests/test_workspace.py +78 -0
- openhoof-2.0.0/training/README.md +131 -0
- openhoof-2.0.0/training/__init__.py +0 -0
- openhoof-2.0.0/training/pipeline.py +351 -0
- openhoof-2.0.0/training/requirements-linux.txt +8 -0
- openhoof-2.0.0/training/requirements-mac.txt +6 -0
- openhoof-2.0.0/training/setup.sh +49 -0
- openhoof-2.0.0/training/train_tool_router.py +465 -0
- openhoof-2.0.0/ui/app/activity/page.tsx +94 -0
- openhoof-2.0.0/ui/app/agents/[id]/chat/page.tsx +160 -0
- openhoof-2.0.0/ui/app/agents/[id]/page.tsx +308 -0
- openhoof-2.0.0/ui/app/agents/new/page.tsx +134 -0
- openhoof-2.0.0/ui/app/agents/page.tsx +147 -0
- openhoof-2.0.0/ui/app/approvals/page.tsx +131 -0
- openhoof-2.0.0/ui/app/globals.css +55 -0
- openhoof-2.0.0/ui/app/layout.tsx +47 -0
- openhoof-2.0.0/ui/app/page.tsx +255 -0
- openhoof-2.0.0/ui/app/tools/page.tsx +182 -0
- openhoof-2.0.0/ui/app/training/page.tsx +434 -0
- openhoof-2.0.0/ui/next-env.d.ts +5 -0
- openhoof-2.0.0/ui/next.config.js +14 -0
- openhoof-2.0.0/ui/package-lock.json +2454 -0
- openhoof-2.0.0/ui/package.json +34 -0
- openhoof-2.0.0/ui/postcss.config.js +6 -0
- openhoof-2.0.0/ui/tailwind.config.js +49 -0
- openhoof-2.0.0/ui/tsconfig.json +26 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
.venv/
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
env/
|
|
28
|
+
|
|
29
|
+
# IDE
|
|
30
|
+
.idea/
|
|
31
|
+
.vscode/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
*~
|
|
35
|
+
|
|
36
|
+
# Testing
|
|
37
|
+
.pytest_cache/
|
|
38
|
+
.coverage
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.nox/
|
|
42
|
+
|
|
43
|
+
# MyPy
|
|
44
|
+
.mypy_cache/
|
|
45
|
+
|
|
46
|
+
# Logs
|
|
47
|
+
*.log
|
|
48
|
+
logs/
|
|
49
|
+
|
|
50
|
+
# Local configuration
|
|
51
|
+
.env
|
|
52
|
+
.env.local
|
|
53
|
+
*.local.yaml
|
|
54
|
+
|
|
55
|
+
# macOS
|
|
56
|
+
.DS_Store
|
|
57
|
+
.AppleDouble
|
|
58
|
+
.LSOverride
|
|
59
|
+
|
|
60
|
+
# Node (for UI)
|
|
61
|
+
node_modules/
|
|
62
|
+
.next/
|
|
63
|
+
out/
|
|
64
|
+
.turbo/
|
|
65
|
+
|
|
66
|
+
# Data (don't commit user data)
|
|
67
|
+
~/.openhoof/
|
|
68
|
+
data/
|
|
69
|
+
|
|
70
|
+
# Temp files
|
|
71
|
+
*.tmp
|
|
72
|
+
*.temp
|
|
73
|
+
/tmp/
|
|
74
|
+
.venv-train/
|
|
75
|
+
|
|
76
|
+
# Model weights (too large for git)
|
|
77
|
+
fused_model/
|
|
78
|
+
*.safetensors
|
|
79
|
+
*.gguf
|
|
80
|
+
.venv-train/
|
|
81
|
+
|
|
82
|
+
# Agent workspace runtime files (belong in ~/.openhoof/, not repo)
|
|
83
|
+
.microclaw/
|
|
84
|
+
SOUL.md
|
|
85
|
+
MEMORY.md
|
|
86
|
+
memory/
|
|
87
|
+
test_agent_workspace/
|
|
88
|
+
|
|
89
|
+
# Training data (captured at runtime, not committed)
|
|
90
|
+
*.jsonl
|
openhoof-2.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openhoof
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Lightweight agent runtime library for autonomous edge agents
|
|
5
|
+
Project-URL: Homepage, https://github.com/llama-farm/openhoof
|
|
6
|
+
Project-URL: Documentation, https://github.com/llama-farm/openhoof/tree/main/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/llama-farm/openhoof
|
|
8
|
+
Project-URL: Issues, https://github.com/llama-farm/openhoof/issues
|
|
9
|
+
Author-email: LlamaFarm <hello@llamafarm.ai>
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
Keywords: agents,ai,autonomous,edge,llamafarm,llm,runtime
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: pydantic>=2.5.0
|
|
21
|
+
Requires-Dist: pyyaml>=6.0
|
|
22
|
+
Requires-Dist: requests>=2.31.0
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: mypy>=1.8.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
29
|
+
Provides-Extra: training
|
|
30
|
+
Requires-Dist: datasets>=2.16.0; extra == 'training'
|
|
31
|
+
Requires-Dist: peft>=0.7.0; extra == 'training'
|
|
32
|
+
Requires-Dist: torch>=2.1.0; extra == 'training'
|
|
33
|
+
Requires-Dist: tqdm>=4.66.0; extra == 'training'
|
|
34
|
+
Requires-Dist: transformers>=4.37.0; extra == 'training'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# 🦙 OpenHoof v2.0
|
|
38
|
+
|
|
39
|
+
**Local AI agent runtime library with FunctionGemma training**
|
|
40
|
+
|
|
41
|
+
OpenHoof is a standalone, extensible library for running AI agents that persist across sessions, respond to events, and coordinate with each other. Built to work with [LlamaFarm](https://github.com/llama-farm/llamafarm) for local inference.
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
45
|
+
│ YOUR APPLICATION │
|
|
46
|
+
│ (Drone Control, Medical, etc.) │
|
|
47
|
+
├─────────────────────────────────────────────────────────────┤
|
|
48
|
+
│ │ │
|
|
49
|
+
│ Agent Runtime │
|
|
50
|
+
│ ▼ │
|
|
51
|
+
├─────────────────────────────────────────────────────────────┤
|
|
52
|
+
│ O P E N H O O F │
|
|
53
|
+
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
|
54
|
+
│ │ Agent │ │ Soul │ │ Memory │ │ Tools │ │
|
|
55
|
+
│ │ Loop │ │ Loading │ │ Recall │ │Registry │ │
|
|
56
|
+
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
|
|
57
|
+
│ │ │ │ │ │
|
|
58
|
+
│ └────────────┴─────┬──────┴────────────┘ │
|
|
59
|
+
│ │ │
|
|
60
|
+
│ LlamaFarm │
|
|
61
|
+
│ (local inference) │
|
|
62
|
+
└─────────────────────────────────────────────────────────────┘
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## ✨ What's New in v2.0
|
|
68
|
+
|
|
69
|
+
**Complete rebuild** as a standalone library (was a server framework in v1.x):
|
|
70
|
+
|
|
71
|
+
- **🎯 Agent Runtime** — Event loop, heartbeat, exit conditions
|
|
72
|
+
- **🧠 Context Files** — SOUL.md, MEMORY.md, USER.md, TOOLS.md as first-class citizens
|
|
73
|
+
- **💾 DDIL** — Store-and-forward for offline operation (Denied/Degraded/Intermittent/Limited networks)
|
|
74
|
+
- **🔌 LlamaFarm Integration** — Tools + prompts passed through in API calls
|
|
75
|
+
- **📡 Training Data Capture** — Every tool call logged for fine-tuning
|
|
76
|
+
- **🎓 FunctionGemma Pipeline** — Auto-generate training data, fine-tune tool routing model (GOLD!)
|
|
77
|
+
- **📱 Runs Anywhere** — Python (now) → Kotlin (Android) → Rust (cross-platform)
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 🚀 Quick Start
|
|
82
|
+
|
|
83
|
+
### Installation
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pip install -e git+https://github.com/llama-farm/openhoof.git@feat/microclaw-rebuild#egg=openhoof
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Basic Usage
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from openhoof import Agent, Soul, Memory
|
|
93
|
+
|
|
94
|
+
# Define your tools (OpenAI-compatible format)
|
|
95
|
+
tools = [
|
|
96
|
+
{
|
|
97
|
+
"name": "get_weather",
|
|
98
|
+
"description": "Get current weather for a location",
|
|
99
|
+
"parameters": {
|
|
100
|
+
"type": "object",
|
|
101
|
+
"properties": {
|
|
102
|
+
"location": {"type": "string"}
|
|
103
|
+
},
|
|
104
|
+
"required": ["location"]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
# Tool executor (your implementation)
|
|
110
|
+
def execute_tool(tool_name: str, params: dict) -> dict:
|
|
111
|
+
if tool_name == "get_weather":
|
|
112
|
+
return {"temp": 72, "condition": "sunny"}
|
|
113
|
+
return {"error": "Unknown tool"}
|
|
114
|
+
|
|
115
|
+
# Create agent
|
|
116
|
+
agent = Agent(
|
|
117
|
+
soul="SOUL.md", # Your agent's identity + mission
|
|
118
|
+
memory="MEMORY.md", # Long-term recall
|
|
119
|
+
tools=tools,
|
|
120
|
+
executor=execute_tool,
|
|
121
|
+
llamafarm_config="llamafarm.yaml", # LlamaFarm models
|
|
122
|
+
heartbeat_interval=30.0
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Exit conditions
|
|
126
|
+
agent.on_exit("timeout", lambda: time.time() - agent.start_time > 1800)
|
|
127
|
+
|
|
128
|
+
# Heartbeat callbacks
|
|
129
|
+
agent.on_heartbeat(lambda: print(f"💓 Still alive"))
|
|
130
|
+
|
|
131
|
+
# Run agent
|
|
132
|
+
agent.run()
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 📖 Core Concepts
|
|
138
|
+
|
|
139
|
+
### Context Files
|
|
140
|
+
|
|
141
|
+
OpenHoof agents are defined by markdown files:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
my-agent/
|
|
145
|
+
├── SOUL.md # Identity, mission, style, constraints
|
|
146
|
+
├── MEMORY.md # Long-term recall, persistent context
|
|
147
|
+
├── USER.md # Who the agent serves, preferences
|
|
148
|
+
└── TOOLS.md # Available capabilities, tool docs
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**SOUL.md example:**
|
|
152
|
+
```markdown
|
|
153
|
+
# SOUL.md - Weather Agent
|
|
154
|
+
|
|
155
|
+
You are a helpful weather assistant AI.
|
|
156
|
+
|
|
157
|
+
**Name:** WeatherBot
|
|
158
|
+
**Emoji:** ☀️
|
|
159
|
+
|
|
160
|
+
## Mission
|
|
161
|
+
Provide accurate, timely weather information to users.
|
|
162
|
+
|
|
163
|
+
## Style
|
|
164
|
+
- Be concise and factual
|
|
165
|
+
- Always include units (°F, mph, etc.)
|
|
166
|
+
- Warn about severe weather
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Tool Schema Format
|
|
170
|
+
|
|
171
|
+
OpenHoof uses **OpenAI-compatible tool schemas** (same format Ace uses):
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
{
|
|
175
|
+
"name": "drone_takeoff",
|
|
176
|
+
"description": "Take off and hover at specified altitude",
|
|
177
|
+
"parameters": {
|
|
178
|
+
"type": "object",
|
|
179
|
+
"properties": {
|
|
180
|
+
"alt_m": {"type": "number", "description": "Altitude in meters"},
|
|
181
|
+
},
|
|
182
|
+
"required": ["alt_m"]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Heartbeat System
|
|
188
|
+
|
|
189
|
+
Agents run a heartbeat loop every N seconds:
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
# Check exit conditions
|
|
193
|
+
agent.on_exit("battery_low", lambda: agent.custom.get("battery") < 20)
|
|
194
|
+
agent.on_exit("timeout", lambda: runtime > 1800)
|
|
195
|
+
|
|
196
|
+
# Custom heartbeat actions
|
|
197
|
+
def heartbeat():
|
|
198
|
+
battery = get_battery()
|
|
199
|
+
agent.custom["battery"] = battery
|
|
200
|
+
if battery < 30:
|
|
201
|
+
print("⚠️ Low battery!")
|
|
202
|
+
|
|
203
|
+
agent.on_heartbeat(heartbeat)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### DDIL (Store-and-Forward)
|
|
207
|
+
|
|
208
|
+
When network is unavailable, agents buffer data locally:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
# Store data when offline
|
|
212
|
+
agent.ddil.store("telemetry", {
|
|
213
|
+
"lat": 41.8781,
|
|
214
|
+
"lon": -87.6298,
|
|
215
|
+
"battery": 85
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
# Sync when network returns
|
|
219
|
+
agent.ddil.sync_to_server("http://gateway.local")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### LlamaFarm Integration
|
|
223
|
+
|
|
224
|
+
Configure models in `llamafarm.yaml`:
|
|
225
|
+
|
|
226
|
+
```yaml
|
|
227
|
+
endpoint: "http://localhost:8765/v1"
|
|
228
|
+
|
|
229
|
+
models:
|
|
230
|
+
router:
|
|
231
|
+
model: "functiongemma:270m" # Fast tool routing
|
|
232
|
+
temperature: 0.1
|
|
233
|
+
|
|
234
|
+
reasoning:
|
|
235
|
+
model: "qwen2.5:8b" # Agent reasoning
|
|
236
|
+
temperature: 0.7
|
|
237
|
+
|
|
238
|
+
fallback:
|
|
239
|
+
model: "gpt-4o-mini" # Cloud fallback
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Use in agent:
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
# Reason about a situation (can trigger tool calls)
|
|
246
|
+
response = agent.reason("Should I continue if battery is 25%?")
|
|
247
|
+
print(response['content'])
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## 🎓 FunctionGemma Training Pipeline (THE GOLD!)
|
|
253
|
+
|
|
254
|
+
OpenHoof includes an **automated training pipeline** for fine-tuning FunctionGemma on your tool calling patterns.
|
|
255
|
+
|
|
256
|
+
### How It Works
|
|
257
|
+
|
|
258
|
+
1. **Data Collection** — Every tool call (input → tool selection → result) logged as training data
|
|
259
|
+
2. **Synthetic Generation** — Auto-generate diverse examples for each tool
|
|
260
|
+
3. **LoRA Fine-tuning** — Train FunctionGemma-270M on your tools (<300ms routing)
|
|
261
|
+
4. **GGUF Export** — Export trained model for deployment
|
|
262
|
+
5. **Hot-swap** — Update LlamaFarm with new model
|
|
263
|
+
|
|
264
|
+
### Usage
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
# Check training data status
|
|
268
|
+
python -m openhoof.training.pipeline status
|
|
269
|
+
|
|
270
|
+
# Generate synthetic training data
|
|
271
|
+
python -m openhoof.training.pipeline generate --count 100
|
|
272
|
+
|
|
273
|
+
# Run full training pipeline
|
|
274
|
+
python -m openhoof.training.pipeline run
|
|
275
|
+
|
|
276
|
+
# Export data for inspection
|
|
277
|
+
python -m openhoof.training.pipeline export
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Training Data Format
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
{
|
|
284
|
+
"input": {
|
|
285
|
+
"user_message": "Check the weather in Chicago",
|
|
286
|
+
"tools": ["get_weather", "set_reminder", "search_web"]
|
|
287
|
+
},
|
|
288
|
+
"output": {
|
|
289
|
+
"tool_calls": [
|
|
290
|
+
{"name": "get_weather", "arguments": {"location": "Chicago"}}
|
|
291
|
+
]
|
|
292
|
+
},
|
|
293
|
+
"metadata": {
|
|
294
|
+
"source": "live_usage",
|
|
295
|
+
"timestamp": "2026-02-20T15:00:00"
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
This is logged automatically by `TrainingDataCapture` on every tool call.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## 🏗️ Project Structure
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
openhoof/
|
|
308
|
+
├── openhoof/ # Python library
|
|
309
|
+
│ ├── agent.py # Core Agent class
|
|
310
|
+
│ ├── soul.py # SOUL.md loading
|
|
311
|
+
│ ├── memory.py # MEMORY.md + semantic search
|
|
312
|
+
│ ├── heartbeat.py # Heartbeat + exit conditions
|
|
313
|
+
│ ├── events.py # Event queue
|
|
314
|
+
│ ├── ddil.py # Store-and-forward buffer
|
|
315
|
+
│ ├── training.py # Training data capture
|
|
316
|
+
│ ├── models.py # LlamaFarm integration
|
|
317
|
+
│ ├── tools/ # Tool base classes + registry
|
|
318
|
+
│ │ ├── base.py # Tool base class
|
|
319
|
+
│ │ ├── registry.py # ToolRegistry
|
|
320
|
+
│ │ └── builtin/ # Built-in tools
|
|
321
|
+
│ └── tool_registry.py # Simple registry (for basic use)
|
|
322
|
+
├── training/ # FunctionGemma pipeline (THE GOLD!)
|
|
323
|
+
│ ├── pipeline.py # Training pipeline orchestration
|
|
324
|
+
│ └── train_tool_router.py # LoRA fine-tuning script
|
|
325
|
+
├── examples/ # Example agents
|
|
326
|
+
├── tests/ # Unit tests
|
|
327
|
+
└── llamafarm.yaml # LlamaFarm config
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## 🔧 Tool Schema (What Ace Uses)
|
|
333
|
+
|
|
334
|
+
OpenHoof defines a **tool schema format** that's 100% OpenAI-compatible. This is what Ace uses (not the library itself, just the format):
|
|
335
|
+
|
|
336
|
+
```python
|
|
337
|
+
DRONE_TOOLS = [
|
|
338
|
+
{
|
|
339
|
+
"name": "drone_takeoff",
|
|
340
|
+
"description": "Take off and hover at specified altitude",
|
|
341
|
+
"parameters": {
|
|
342
|
+
"type": "object",
|
|
343
|
+
"properties": {
|
|
344
|
+
"alt_m": {"type": "number", "default": 15.0}
|
|
345
|
+
},
|
|
346
|
+
"required": []
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
"name": "drone_move",
|
|
351
|
+
"description": "Move relative to current position",
|
|
352
|
+
"parameters": {
|
|
353
|
+
"type": "object",
|
|
354
|
+
"properties": {
|
|
355
|
+
"north_m": {"type": "number", "default": 0.0},
|
|
356
|
+
"east_m": {"type": "number", "default": 0.0},
|
|
357
|
+
"up_m": {"type": "number", "default": 0.0},
|
|
358
|
+
"yaw_deg": {"type": "number", "default": 0.0}
|
|
359
|
+
},
|
|
360
|
+
"required": []
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
]
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
This format works with:
|
|
367
|
+
- FunctionGemma fine-tuning
|
|
368
|
+
- LlamaFarm tool calling
|
|
369
|
+
- OpenAI API (if using cloud fallback)
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## 📦 Installation & Development
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# Clone the repo
|
|
377
|
+
git clone https://github.com/llama-farm/openhoof.git
|
|
378
|
+
cd openhoof
|
|
379
|
+
|
|
380
|
+
# Install in development mode
|
|
381
|
+
pip install -e .
|
|
382
|
+
|
|
383
|
+
# Run tests
|
|
384
|
+
pytest tests/
|
|
385
|
+
|
|
386
|
+
# Generate synthetic training data
|
|
387
|
+
python -m openhoof.training.pipeline generate --count 100
|
|
388
|
+
|
|
389
|
+
# Train FunctionGemma
|
|
390
|
+
python -m openhoof.training.pipeline run
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## 🎯 Example: Drone Agent
|
|
396
|
+
|
|
397
|
+
```python
|
|
398
|
+
from openhoof import Agent
|
|
399
|
+
from my_drone_tools import DRONE_TOOLS, DroneToolExecutor
|
|
400
|
+
|
|
401
|
+
agent = Agent(
|
|
402
|
+
soul="SOUL.md",
|
|
403
|
+
memory="MEMORY.md",
|
|
404
|
+
tools=DRONE_TOOLS,
|
|
405
|
+
executor=DroneToolExecutor(),
|
|
406
|
+
heartbeat_interval=30.0
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
# Exit on battery low or geofence breach
|
|
410
|
+
agent.on_exit("battery_low", lambda: agent.custom.get("battery") < 20)
|
|
411
|
+
agent.on_exit("geofence", lambda: not agent.custom.get("in_bounds"))
|
|
412
|
+
|
|
413
|
+
# Sync telemetry on heartbeat
|
|
414
|
+
def heartbeat():
|
|
415
|
+
telemetry = get_telemetry()
|
|
416
|
+
agent.custom["battery"] = telemetry.battery
|
|
417
|
+
agent.custom["in_bounds"] = telemetry.in_geofence
|
|
418
|
+
|
|
419
|
+
# Buffer telemetry for DDIL
|
|
420
|
+
agent.ddil.store("telemetry", telemetry.to_dict())
|
|
421
|
+
|
|
422
|
+
agent.on_heartbeat(heartbeat)
|
|
423
|
+
|
|
424
|
+
# Run agent
|
|
425
|
+
agent.run()
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## 🔄 Migration from v1.x
|
|
431
|
+
|
|
432
|
+
**v1.x was a server** (FastAPI + WebSockets + UI)
|
|
433
|
+
**v2.0 is a library** (standalone agent runtime)
|
|
434
|
+
|
|
435
|
+
If you were using v1.x:
|
|
436
|
+
- **Server features** → Moved to separate project (TBD)
|
|
437
|
+
- **Agent runtime** → Now a library you import
|
|
438
|
+
- **Tool schemas** → 100% compatible, no changes needed
|
|
439
|
+
- **Training pipeline** → Still here, improved!
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 📜 License
|
|
444
|
+
|
|
445
|
+
Apache 2.0
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## 🙏 Acknowledgments
|
|
450
|
+
|
|
451
|
+
- [LlamaFarm](https://github.com/llama-farm/llamafarm) — Local LLM inference
|
|
452
|
+
- Built with ❤️ for anyone who needs reliable local AI agents
|
|
453
|
+
- Special thanks to Ace (drone agent) for validating the architecture
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
**Ready to build agents that kick into action?** 🦙
|
|
458
|
+
|
|
459
|
+
*No llamas were harmed in the making of this library. Several were bedazzled.*
|