Files
ajarbot/docs/HEARTBEAT_HOOKS.md
Jordan Ramos a99799bf3d Initial commit: Ajarbot with optimizations
Features:
- Multi-platform bot (Slack, Telegram)
- Memory system with SQLite FTS
- Tool use capabilities (file ops, commands)
- Scheduled tasks system
- Dynamic model switching (/sonnet, /haiku)
- Prompt caching for cost optimization

Optimizations:
- Default to Haiku 4.5 (12x cheaper)
- Reduced context: 3 messages, 2 memory results
- Optimized SOUL.md (48% smaller)
- Automatic caching when using Sonnet (90% savings)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 19:06:28 -07:00

137 lines
3.6 KiB
Markdown

# Heartbeat & Hooks System
Simple Python implementation inspired by OpenClaw's automation patterns.
## Heartbeat
**What**: Periodic background check that reads `HEARTBEAT.md` and processes with LLM.
**How it works**:
1. Runs every N minutes (default: 30)
2. Only during active hours (default: 8am-10pm)
3. Reads HEARTBEAT.md checklist
4. Sends to LLM with context (SOUL, pending tasks, current time)
5. Returns `HEARTBEAT_OK` if nothing needs attention
6. Calls alert callback if action needed
**Files**:
- `heartbeat.py` - Heartbeat implementation
- `memory_workspace/HEARTBEAT.md` - Checklist (auto-created)
**Usage**:
```python
from heartbeat import Heartbeat
heartbeat = Heartbeat(memory, llm, interval_minutes=30, active_hours=(8, 22))
heartbeat.on_alert = lambda msg: print(f"ALERT: {msg}")
heartbeat.start()
# Test immediately
result = heartbeat.check_now()
```
## Hooks
**What**: Event-driven automation for agent lifecycle events.
**Events**:
- `task:created` - When task added
- `memory:synced` - After memory sync
- `agent:startup` - Agent starts
- `agent:shutdown` - Agent cleanup
**How it works**:
1. Register handler functions for events
2. System triggers events at key points
3. All registered handlers run
4. Handlers can add messages to event
**Files**:
- `hooks.py` - Hooks system + example handlers
**Usage**:
```python
from hooks import HooksSystem, HookEvent
hooks = HooksSystem()
def my_hook(event: HookEvent):
if event.type != "task" or event.action != "created":
return
print(f"Task: {event.context['title']}")
event.messages.append("Logged!")
hooks.register("task:created", my_hook)
hooks.trigger("task", "created", {"title": "Build feature"})
```
## Integration with Agent
```python
from agent import Agent
# Heartbeat runs in background
agent = Agent(provider="claude", enable_heartbeat=True)
# Hooks auto-registered
agent.hooks.register("task:created", my_custom_hook)
# Events trigger automatically
task_id = agent.memory.add_task("Do something") # → task:created event
# Cleanup
agent.shutdown() # → agent:shutdown event
```
## OpenClaw Comparison
| Feature | OpenClaw | This Implementation |
|---------|----------|---------------------|
| Heartbeat | ✅ Main session, context-aware | ✅ Background thread, context-aware |
| Interval | ✅ Configurable (default 30m) | ✅ Configurable (default 30m) |
| Active hours | ✅ Start/end times | ✅ Start/end times (24h format) |
| Checklist | ✅ HEARTBEAT.md | ✅ HEARTBEAT.md |
| Alert suppression | ✅ HEARTBEAT_OK | ✅ HEARTBEAT_OK |
| Hooks system | ✅ TypeScript, directory-based | ✅ Python, function-based |
| Hook discovery | ✅ Auto-scan directories | ✅ Manual registration |
| Event types | ✅ command, session, agent, gateway | ✅ task, memory, agent |
| Async execution | ✅ In main event loop | ✅ Threading |
## Simple Extensions
**Add custom event**:
```python
# In your code
agent.hooks.trigger("custom", "action", {"data": "value"})
# Register handler
def on_custom(event):
print(f"Custom: {event.context}")
agent.hooks.register("custom:action", on_custom)
```
**Custom heartbeat checklist**:
Edit `memory_workspace/HEARTBEAT.md`:
```markdown
# Heartbeat Checklist
- Check email (if integrated)
- Review calendar events in next 2h
- Check pending tasks > 24h old
- System health check
```
**Multi-check batching** (like OpenClaw):
```python
# Single heartbeat checks multiple things
checklist = """
- Email: Check inbox
- Calendar: Events next 2h
- Tasks: Pending > 24h
- Memory: Sync status
"""
```
LLM processes all in one turn = more efficient than separate calls.