Documentation Index
Fetch the complete documentation index at: https://mintlify.com/operatoronline/weaver/llms.txt
Use this file to discover all available pages before exploring further.
The heartbeat service enables Weaver agents to proactively check for tasks, monitor systems, and take actions at regular intervals without explicit user prompts.
Overview
Heartbeat runs a periodic check loop that:
- Reads tasks from
HEARTBEAT.md
- Executes agent with heartbeat prompt
- Processes tool calls and responses
- Reports results to user (optional)
Use Cases:
- Monitoring device status
- Checking for notifications
- Periodic system health checks
- Automated maintenance tasks
- Scheduled reports
Configuration
Service Creation
import "github.com/operatoronline/weaver/pkg/heartbeat"
service := heartbeat.NewHeartbeatService(
workspace, // Workspace directory
30, // Interval in minutes
true, // Enabled
)
Parameters
- workspace (string) - Working directory containing
HEARTBEAT.md
- intervalMinutes (int) - Check interval (minimum: 5 minutes)
- enabled (bool) - Service enabled status
Defaults:
- Minimum interval: 5 minutes
- Default interval: 30 minutes
- Initial delay: 1 second
Setting Up Dependencies
// Set message bus for sending results
service.SetBus(messageBus)
// Set heartbeat handler
handler := func(prompt, channel, chatID string) *tools.ToolResult {
// Execute agent with heartbeat prompt
return agentExecute(prompt, channel, chatID)
}
service.SetHandler(handler)
Heartbeat File
The heartbeat file contains tasks for the agent to check:
# Heartbeat Check List
This file contains tasks for the heartbeat service to check periodically.
## Examples
- Check for unread messages
- Review upcoming calendar events
- Check device status (e.g., MaixCam)
## Instructions
- Execute ALL tasks listed below. Do NOT skip any task.
- For simple tasks (e.g., report current time), respond directly.
- For complex tasks that may take time, use the spawn tool to create a subagent.
- The spawn tool is async - subagent results will be sent to the user automatically.
- After spawning a subagent, CONTINUE to process remaining tasks.
- Only respond with HEARTBEAT_OK when ALL tasks are done AND nothing needs attention.
---
Add your heartbeat tasks below this line:
- Check MaixCam status every 30 minutes
- Review email for urgent messages
- Monitor disk space on server
Auto-Generation
If HEARTBEAT.md doesn’t exist, a default template is created on first run:
service.Start() // Creates HEARTBEAT.md if missing
Service Lifecycle
Starting the Service
err := service.Start()
if err != nil {
log.Fatalf("Failed to start heartbeat: %v", err)
}
Behavior:
- Loads configuration
- Starts background ticker
- Executes first heartbeat after 1 second
- Runs subsequent checks at configured interval
Stopping the Service
Behavior:
- Gracefully stops ticker
- Waits for current heartbeat to complete
- Closes background goroutine
Checking Status
if service.IsRunning() {
fmt.Println("Heartbeat service is active")
}
Execution Flow
1. Heartbeat Trigger
Every interval (e.g., 30 minutes):
ticker := time.NewTicker(interval)
for {
select {
case <-ticker.C:
executeHeartbeat()
}
}
2. Prompt Building
Heartbeat reads HEARTBEAT.md and builds the prompt:
func (hs *HeartbeatService) buildPrompt() string {
content := readFile("HEARTBEAT.md")
now := time.Now().Format("2006-01-02 15:04:05")
return fmt.Sprintf(`# Heartbeat Check
Current time: %s
You are a proactive AI assistant. This is a scheduled heartbeat check.
Review the following tasks and execute any necessary actions using available skills.
If there is nothing that requires attention, respond ONLY with: HEARTBEAT_OK
%s
`, now, content)
}
3. Handler Execution
The handler processes the heartbeat:
handler := func(prompt, channel, chatID string) *tools.ToolResult {
// Agent processes heartbeat prompt
// Can call tools, spawn subagents, etc.
result := agent.Process(prompt)
return result
}
4. Result Processing
Silent (HEARTBEAT_OK):
if result.Silent {
// No action needed, user not notified
return
}
Async (spawned subagent):
if result.Async {
// Subagent running in background
// Will notify user when complete
return
}
User Notification:
if result.ForUser != "" {
msgBus.PublishOutbound(bus.OutboundMessage{
Channel: lastChannel,
ChatID: lastChatID,
Content: result.ForUser,
})
}
Channel Resolution
Heartbeat uses the last active channel for notifications:
State Management
lastChannel := state.GetLastChannel()
// Format: "platform:user_id" (e.g., "telegram:123456")
platform, userID := parseLastChannel(lastChannel)
Channel Validation
Internal channels are filtered:
if constants.IsInternalChannel(platform) {
// Skip cli, system, cron channels
return
}
Valid channels:
- telegram
- whatsapp
- discord
- slack
- etc.
Invalid (internal) channels:
- cli
- system
- cron
- heartbeat
Advanced Usage
Multi-Task Heartbeats
Execute multiple checks in one heartbeat:
## Tasks
1. Check MaixCam camera status
2. Review email inbox for priority items
3. Monitor server disk space (spawn if over 80%)
4. Check for GitHub notifications
## Response Rules
- Process ALL tasks before responding
- Spawn subagents for time-consuming tasks
- Only say HEARTBEAT_OK if nothing needs attention
For long-running tasks, use the spawn tool:
Agent’s heartbeat response:
{
"tool_calls": [
{
"name": "spawn",
"args": {
"task": "Check all security cameras and report any offline devices",
"label": "camera-check"
}
}
]
}
Result:
- Heartbeat completes immediately (async)
- Subagent runs in background
- User notified when subagent finishes
Conditional Responses
Respond only when action is needed:
## Disk Space Check
- Check disk usage with `df -h`
- If any partition is over 85%, spawn cleanup task
- Otherwise, respond HEARTBEAT_OK
Agent logic:
- Call
exec tool: df -h
- Parse output
- If usage > 85%: spawn cleanup subagent
- If usage < 85%: return
HEARTBEAT_OK
Custom Intervals
Adjust interval based on task urgency:
// Critical monitoring: 5 minutes
service := heartbeat.NewHeartbeatService(workspace, 5, true)
// Regular checks: 30 minutes (default)
service := heartbeat.NewHeartbeatService(workspace, 30, true)
// Infrequent checks: 120 minutes
service := heartbeat.NewHeartbeatService(workspace, 120, true)
Logging
Heartbeat maintains a log file:
Location: <workspace>/heartbeat.log
Format:
[2026-03-01 10:30:00] [INFO] Heartbeat service started
[2026-03-01 10:30:01] [INFO] Executing heartbeat
[2026-03-01 10:30:01] [INFO] Resolved channel: telegram, chatID: 123456
[2026-03-01 10:30:02] [INFO] Async task started: Spawned subagent 'camera-check'
[2026-03-01 10:31:00] [INFO] Heartbeat completed: HEARTBEAT_OK
[2026-03-01 11:00:00] [ERROR] Heartbeat error: agent timeout
Log Levels:
- INFO - Normal operations
- ERROR - Execution failures
Error Handling
Handler Errors
if result.IsError {
log.Printf("Heartbeat error: %s", result.ForLLM)
// Error logged, service continues
// Next heartbeat will retry
}
Missing HEARTBEAT.md
if !fileExists("HEARTBEAT.md") {
createDefaultTemplate()
return "" // Skip this heartbeat
}
Channel Resolution Failure
if channel == "" || chatID == "" {
// Result not sent to user
// Logged for debugging
return
}
Heartbeat Execution Time
- Simple checks: < 1 second
- With tools: 2-5 seconds
- With spawn: 1-2 seconds (async)
Resource Usage
- Memory: Minimal (single goroutine)
- CPU: Idle between ticks, active during execution
- Disk I/O: Read
HEARTBEAT.md, write logs
Optimization Tips
-
Use spawn for heavy tasks:
- Spawn subagent for backup verification (don't block heartbeat)
-
Combine related checks:
- Check all device statuses in one tool call
-
Adjust interval appropriately:
- Critical: 5-10 minutes
- Standard: 30 minutes
- Non-urgent: 60+ minutes
Best Practices
-
Keep tasks atomic:
- One clear objective per task
- Easy to validate completion
-
Use HEARTBEAT_OK liberally:
- Only notify user when action is needed
- Reduces notification fatigue
-
Leverage async operations:
- Use
spawn for time-consuming tasks
- Keep heartbeat execution fast
-
Document task expectations:
- Clear success criteria
- Failure handling instructions
-
Monitor heartbeat logs:
- Check for recurring errors
- Adjust tasks based on results
-
Test before deployment:
- Run manual heartbeat check
- Verify tool availability
- Confirm channel routing
Example Configurations
DevOps Monitoring
# Heartbeat Tasks
- Check server CPU/memory with `top -b -n 1`
- Monitor docker containers: `docker ps --filter status=exited`
- Check disk space: `df -h`
- Review nginx error logs for 5xx errors
- If critical issues found, spawn alert subagent
Personal Assistant
# Heartbeat Tasks
- Check calendar for events in next 2 hours
- Review unread emails (priority inbox)
- Check weather forecast for travel planning
- Monitor package delivery status
- Update daily task list
IoT Device Management
# Heartbeat Tasks
- Check MaixCam status: `curl http://maixcam.local/status`
- Read temperature sensor via I2C (bus 1, addr 0x38)
- Monitor security camera connectivity
- Check smart home hub connection
- Report any offline devices
Integration with Other Features
Heartbeat + Cron
Use cron for specific schedules, heartbeat for general monitoring:
Cron: “Daily backup at 2 AM”
Heartbeat: “Check if backup completed successfully”
Heartbeat + Skills
Load skills for domain-specific heartbeats:
# Heartbeat Tasks (requires hardware skill)
- Use I2C tool to read AHT20 sensor
- Check temperature is within normal range (0-50°C)
- If abnormal, spawn alert subagent
Heartbeat + Device Monitoring
Respond to device events:
# Heartbeat Tasks
- Check if any USB devices were hotplugged
- Verify MaixCam is still connected
- Restart camera service if needed