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>
This commit is contained in:
371
docs/SCHEDULED_TASKS.md
Normal file
371
docs/SCHEDULED_TASKS.md
Normal file
@@ -0,0 +1,371 @@
|
||||
# Scheduled Tasks Guide
|
||||
|
||||
This document explains how to use the **TaskScheduler** system for cron-like scheduled tasks that require Agent/LLM execution.
|
||||
|
||||
## 🎯 What's the Difference?
|
||||
|
||||
### Heartbeat (heartbeat.py) - Simple Health Checks
|
||||
|
||||
**Use for:** Background health monitoring
|
||||
- ✅ Interval-based (every N minutes)
|
||||
- ✅ Active hours restriction (8am-10pm)
|
||||
- ✅ Uses Agent/LLM for checklist processing
|
||||
- ✅ Alerts when something needs attention
|
||||
- ❌ No specific time scheduling
|
||||
- ❌ No message sending to platforms
|
||||
|
||||
**Example:** Check for stale tasks every 30 minutes during work hours
|
||||
|
||||
### TaskScheduler (scheduled_tasks.py) - Scheduled Agent Tasks
|
||||
|
||||
**Use for:** Scheduled tasks requiring Agent execution
|
||||
- ✅ Cron-like scheduling (specific times)
|
||||
- ✅ Uses Agent/LLM to generate content
|
||||
- ✅ Can send output to Slack/Telegram
|
||||
- ✅ Daily, weekly, hourly schedules
|
||||
- ✅ Multiple tasks with different schedules
|
||||
- ✅ Manual task triggering
|
||||
|
||||
**Example:** Send weather report to Slack every day at 8am and 6pm
|
||||
|
||||
## 📋 Task Configuration
|
||||
|
||||
Tasks are defined in `config/scheduled_tasks.yaml`:
|
||||
|
||||
```yaml
|
||||
tasks:
|
||||
- name: morning-weather
|
||||
prompt: |
|
||||
Good morning! Provide:
|
||||
1. Weather forecast
|
||||
2. Pending tasks
|
||||
3. Daily motivation
|
||||
schedule: "daily 08:00"
|
||||
enabled: true
|
||||
send_to_platform: "slack"
|
||||
send_to_channel: "C12345"
|
||||
username: "scheduler"
|
||||
```
|
||||
|
||||
### Configuration Fields
|
||||
|
||||
| Field | Required | Description | Example |
|
||||
|-------|----------|-------------|---------|
|
||||
| `name` | ✅ | Unique task identifier | `"morning-weather"` |
|
||||
| `prompt` | ✅ | Message sent to Agent | `"Provide weather report"` |
|
||||
| `schedule` | ✅ | When to run | `"daily 08:00"` |
|
||||
| `enabled` | ❌ | Enable/disable task | `true` (default: `true`) |
|
||||
| `send_to_platform` | ❌ | Messaging platform | `"slack"`, `"telegram"`, or `null` |
|
||||
| `send_to_channel` | ❌ | Channel/chat ID | `"C12345"` or `"123456789"` |
|
||||
| `username` | ❌ | Agent memory username | `"scheduler"` (default) |
|
||||
|
||||
## ⏰ Schedule Formats
|
||||
|
||||
### Hourly
|
||||
```yaml
|
||||
schedule: "hourly"
|
||||
```
|
||||
Runs every hour on the hour (00:00, 01:00, 02:00, etc.)
|
||||
|
||||
### Daily
|
||||
```yaml
|
||||
schedule: "daily 08:00"
|
||||
schedule: "daily 18:30"
|
||||
```
|
||||
Runs every day at the specified time (24-hour format)
|
||||
|
||||
### Weekly
|
||||
```yaml
|
||||
schedule: "weekly mon 09:00"
|
||||
schedule: "weekly fri 17:00"
|
||||
```
|
||||
Runs every week on the specified day at the specified time
|
||||
|
||||
**Day codes:** `mon`, `tue`, `wed`, `thu`, `fri`, `sat`, `sun`
|
||||
|
||||
## 🚀 Integration with Bot
|
||||
|
||||
### Option 1: Standalone (No Messaging)
|
||||
|
||||
```python
|
||||
from agent import Agent
|
||||
from scheduled_tasks import TaskScheduler
|
||||
|
||||
agent = Agent(provider="claude")
|
||||
scheduler = TaskScheduler(agent)
|
||||
scheduler.start()
|
||||
|
||||
# Tasks run, outputs logged locally
|
||||
```
|
||||
|
||||
### Option 2: With Messaging Platforms
|
||||
|
||||
```python
|
||||
from adapters.runtime import AdapterRuntime
|
||||
from scheduled_tasks import TaskScheduler
|
||||
|
||||
# Create runtime with adapters
|
||||
runtime = AdapterRuntime(agent)
|
||||
runtime.add_adapter(slack_adapter)
|
||||
|
||||
# Create scheduler
|
||||
scheduler = TaskScheduler(agent)
|
||||
|
||||
# Register adapters so scheduler can send messages
|
||||
scheduler.add_adapter("slack", slack_adapter)
|
||||
scheduler.add_adapter("telegram", telegram_adapter)
|
||||
|
||||
# Start both
|
||||
await runtime.start()
|
||||
scheduler.start()
|
||||
```
|
||||
|
||||
### Option 3: Use Example Bot
|
||||
|
||||
```bash
|
||||
python example_bot_with_scheduler.py
|
||||
```
|
||||
|
||||
## 📝 Example Tasks
|
||||
|
||||
### 1. Daily Weather Report (sent to Slack)
|
||||
|
||||
```yaml
|
||||
- name: weather-report
|
||||
prompt: |
|
||||
Provide today's weather report:
|
||||
1. Current conditions
|
||||
2. Forecast for the day
|
||||
3. Any weather alerts
|
||||
|
||||
Note: You may need to say you don't have API access,
|
||||
or suggest integrating a weather API.
|
||||
schedule: "daily 08:00"
|
||||
enabled: true
|
||||
send_to_platform: "slack"
|
||||
send_to_channel: "C12345"
|
||||
```
|
||||
|
||||
**How it works:**
|
||||
1. At 8:00 AM, scheduler triggers task
|
||||
2. Agent receives the prompt
|
||||
3. Agent generates weather report (or notes it needs API)
|
||||
4. Output sent to Slack channel `C12345`
|
||||
|
||||
### 2. Evening Summary (sent to Telegram)
|
||||
|
||||
```yaml
|
||||
- name: evening-summary
|
||||
prompt: |
|
||||
End of day summary:
|
||||
1. What did we accomplish today?
|
||||
2. Any pending tasks?
|
||||
3. Preview of tomorrow
|
||||
schedule: "daily 18:00"
|
||||
enabled: true
|
||||
send_to_platform: "telegram"
|
||||
send_to_channel: "123456789"
|
||||
```
|
||||
|
||||
### 3. Hourly Health Check (local only)
|
||||
|
||||
```yaml
|
||||
- name: health-check
|
||||
prompt: |
|
||||
Quick health check:
|
||||
- Any stale tasks (>24h)?
|
||||
- Memory system healthy?
|
||||
Respond "HEALTHY" or describe issues.
|
||||
schedule: "hourly"
|
||||
enabled: true
|
||||
# No send_to_platform = local logging only
|
||||
```
|
||||
|
||||
### 4. Weekly Team Review (Friday 5pm)
|
||||
|
||||
```yaml
|
||||
- name: weekly-review
|
||||
prompt: |
|
||||
Friday wrap-up! Provide:
|
||||
1. Week highlights
|
||||
2. Metrics (tasks completed)
|
||||
3. Lessons learned
|
||||
4. Next week goals
|
||||
schedule: "weekly fri 17:00"
|
||||
enabled: true
|
||||
send_to_platform: "slack"
|
||||
send_to_channel: "C12345"
|
||||
```
|
||||
|
||||
## 🔧 Advanced Usage
|
||||
|
||||
### Manual Task Execution
|
||||
|
||||
```python
|
||||
scheduler = TaskScheduler(agent)
|
||||
|
||||
# Trigger a task immediately (ignoring schedule)
|
||||
scheduler.run_task_now("morning-weather")
|
||||
```
|
||||
|
||||
### Task Status
|
||||
|
||||
```python
|
||||
# List all tasks with their status
|
||||
for task in scheduler.list_tasks():
|
||||
print(f"{task['name']}: next run at {task['next_run']}")
|
||||
```
|
||||
|
||||
### Custom Callback
|
||||
|
||||
```python
|
||||
def on_task_complete(task, response):
|
||||
print(f"Task {task.name} completed!")
|
||||
# Custom logic here (logging, alerts, etc.)
|
||||
|
||||
scheduler.on_task_complete = on_task_complete
|
||||
```
|
||||
|
||||
### Integration with Weather API
|
||||
|
||||
```yaml
|
||||
- name: real-weather
|
||||
prompt: |
|
||||
Get weather from API and provide report:
|
||||
|
||||
Location: New York
|
||||
API: Use the weather_api tool if available
|
||||
|
||||
Format the response as:
|
||||
🌤️ Current: [temp] [conditions]
|
||||
📅 Today: [forecast]
|
||||
⚠️ Alerts: [any alerts]
|
||||
schedule: "daily 08:00"
|
||||
enabled: true
|
||||
```
|
||||
|
||||
Then add a weather API tool to your agent (via hooks or skills).
|
||||
|
||||
## 📊 Use Cases
|
||||
|
||||
### 1. **Daily Standup Bot**
|
||||
```yaml
|
||||
- name: standup-reminder
|
||||
prompt: "Send standup reminder with today's priorities"
|
||||
schedule: "daily 09:00"
|
||||
send_to_platform: "slack"
|
||||
send_to_channel: "C_TEAM"
|
||||
```
|
||||
|
||||
### 2. **Build Health Reports**
|
||||
```yaml
|
||||
- name: build-status
|
||||
prompt: "Check CI/CD status and report any failures"
|
||||
schedule: "hourly"
|
||||
send_to_platform: "slack"
|
||||
send_to_channel: "C_ENGINEERING"
|
||||
```
|
||||
|
||||
### 3. **Customer Metrics**
|
||||
```yaml
|
||||
- name: daily-metrics
|
||||
prompt: "Summarize customer metrics from yesterday"
|
||||
schedule: "daily 10:00"
|
||||
send_to_platform: "slack"
|
||||
send_to_channel: "C_METRICS"
|
||||
```
|
||||
|
||||
### 4. **Weekly Newsletter**
|
||||
```yaml
|
||||
- name: newsletter
|
||||
prompt: "Generate weekly newsletter with highlights"
|
||||
schedule: "weekly fri 16:00"
|
||||
send_to_platform: "slack"
|
||||
send_to_channel: "C_ALL_HANDS"
|
||||
```
|
||||
|
||||
## 🎯 Choosing Between Heartbeat and Scheduler
|
||||
|
||||
| Feature | Heartbeat | TaskScheduler |
|
||||
|---------|-----------|---------------|
|
||||
| **Purpose** | Health monitoring | Scheduled content generation |
|
||||
| **Scheduling** | Interval (every N min) | Cron-like (specific times) |
|
||||
| **Agent/LLM** | ✅ Yes | ✅ Yes |
|
||||
| **Messaging** | ❌ No | ✅ Yes (Slack, Telegram) |
|
||||
| **Active hours** | ✅ Yes | ❌ No (always runs) |
|
||||
| **Use SDK** | ✅ Yes | ✅ Yes |
|
||||
| **Config** | HEARTBEAT.md | scheduled_tasks.yaml |
|
||||
|
||||
**Use both together:**
|
||||
- **Heartbeat** for background health checks
|
||||
- **TaskScheduler** for user-facing scheduled reports
|
||||
|
||||
## 🚦 Getting Started
|
||||
|
||||
### 1. Edit Configuration
|
||||
|
||||
Edit `config/scheduled_tasks.yaml`:
|
||||
```yaml
|
||||
- name: my-task
|
||||
prompt: "Your prompt here"
|
||||
schedule: "daily 10:00"
|
||||
enabled: true
|
||||
send_to_platform: "slack"
|
||||
send_to_channel: "YOUR_CHANNEL_ID"
|
||||
```
|
||||
|
||||
### 2. Get Channel IDs
|
||||
|
||||
**Slack:**
|
||||
- Right-click channel → View channel details → Copy ID
|
||||
- Format: `C01234ABCDE`
|
||||
|
||||
**Telegram:**
|
||||
- For groups: Use @userinfobot
|
||||
- For DMs: Your user ID (numeric)
|
||||
|
||||
### 3. Run the Bot
|
||||
|
||||
```bash
|
||||
python example_bot_with_scheduler.py
|
||||
```
|
||||
|
||||
### 4. Monitor Tasks
|
||||
|
||||
Tasks will run automatically. Check console output:
|
||||
```
|
||||
[Scheduler] Executing task: morning-weather
|
||||
[Scheduler] ✓ Task completed: morning-weather
|
||||
[Scheduler] ✓ Sent to slack:C12345
|
||||
[Scheduler] Next run for morning-weather: 2026-02-13 08:00
|
||||
```
|
||||
|
||||
## 🔐 Security Notes
|
||||
|
||||
- **Credentials**: Store in environment variables
|
||||
- **Channel IDs**: Keep in config (not secrets, but control access)
|
||||
- **Prompts**: Review before enabling (agent will execute them)
|
||||
- **Rate limits**: Be mindful of hourly tasks + API limits
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
**Task not running:**
|
||||
- Check `enabled: true` in config
|
||||
- Verify schedule format
|
||||
- Check console for errors
|
||||
|
||||
**Message not sent:**
|
||||
- Verify channel ID is correct
|
||||
- Check adapter is registered
|
||||
- Ensure bot has permissions in channel
|
||||
|
||||
**Wrong time:**
|
||||
- Times are in local server timezone
|
||||
- Use 24-hour format (08:00, not 8am)
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
- **Example:** `example_bot_with_scheduler.py`
|
||||
- **Config:** `config/scheduled_tasks.yaml`
|
||||
- **Code:** `scheduled_tasks.py`
|
||||
- **Old heartbeat:** `heartbeat.py` (still works!)
|
||||
Reference in New Issue
Block a user