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:
353
docs/CONTROL_AND_CONFIGURATION.md
Normal file
353
docs/CONTROL_AND_CONFIGURATION.md
Normal file
@@ -0,0 +1,353 @@
|
||||
# Control & Configuration Guide
|
||||
|
||||
## ❓ Key Question: What Does the Agent Control vs What Do I Control?
|
||||
|
||||
### ✅ You Control (100% of monitoring decisions)
|
||||
|
||||
| What | How |
|
||||
|------|-----|
|
||||
| **What to monitor** | You define pulse checks in code/config |
|
||||
| **When to monitor** | You set interval_seconds for each check |
|
||||
| **When to invoke brain** | You define conditions (disk > 90%, errors found, etc.) |
|
||||
| **What prompts to use** | You write the prompt templates |
|
||||
| **Where to send alerts** | You specify platform and channel |
|
||||
|
||||
### ❌ Agent Does NOT Control
|
||||
|
||||
- ❌ The agent **cannot** decide what to monitor
|
||||
- ❌ The agent **cannot** add new checks on its own
|
||||
- ❌ The agent **cannot** change monitoring intervals
|
||||
- ❌ The agent **cannot** start monitoring something you didn't ask for
|
||||
|
||||
### 🤖 Agent Only Does This
|
||||
|
||||
When **YOU** trigger the brain (via condition or schedule), the agent:
|
||||
- ✅ Analyzes the data you give it
|
||||
- ✅ Responds to the prompt you wrote
|
||||
- ✅ Provides recommendations
|
||||
|
||||
**The agent is a tool you invoke, not an autonomous system that picks tasks.**
|
||||
|
||||
## 🎯 Three Levels of Control
|
||||
|
||||
### Level 1: Use Example Checks (Easiest)
|
||||
|
||||
The default `PulseBrain` includes example checks:
|
||||
|
||||
```python
|
||||
pb = PulseBrain(agent)
|
||||
pb.start()
|
||||
```
|
||||
|
||||
**What monitors by default:**
|
||||
- Disk space (every 5 min)
|
||||
- Memory tasks (every 10 min)
|
||||
- Log errors (every 1 min)
|
||||
- Morning briefing (8:00 AM)
|
||||
- Evening summary (6:00 PM)
|
||||
|
||||
**You can disable any:**
|
||||
```python
|
||||
pb = PulseBrain(agent)
|
||||
|
||||
# Remove checks you don't want
|
||||
pb.pulse_checks = [c for c in pb.pulse_checks if c.name != "log-errors"]
|
||||
pb.brain_tasks = [t for t in pb.brain_tasks if t.name != "morning-briefing"]
|
||||
|
||||
pb.start()
|
||||
```
|
||||
|
||||
### Level 2: Start Clean, Add Only What You Want (Recommended)
|
||||
|
||||
```python
|
||||
pb = PulseBrain(agent)
|
||||
|
||||
# Clear all defaults
|
||||
pb.pulse_checks = []
|
||||
pb.brain_tasks = []
|
||||
|
||||
# Add ONLY what you want to monitor
|
||||
pb.pulse_checks.append(
|
||||
PulseCheck("my-check", my_function, interval_seconds=300)
|
||||
)
|
||||
|
||||
pb.start()
|
||||
```
|
||||
|
||||
**Now it ONLY monitors what you explicitly added.**
|
||||
|
||||
### Level 3: Message-Driven (Most Control)
|
||||
|
||||
The agent only monitors when you send a message:
|
||||
|
||||
```python
|
||||
from agent import Agent
|
||||
|
||||
agent = Agent(provider="claude")
|
||||
|
||||
# No Pulse & Brain at all
|
||||
# No TaskScheduler
|
||||
# No automated monitoring
|
||||
|
||||
# Agent only responds when YOU message it:
|
||||
response = agent.chat("Check if the server is running")
|
||||
```
|
||||
|
||||
**Zero automation. Full manual control.**
|
||||
|
||||
## 📝 Configuration Examples
|
||||
|
||||
### Example 1: Only Monitor Disk Space
|
||||
|
||||
```python
|
||||
pb = PulseBrain(agent)
|
||||
pb.pulse_checks = [] # Clear all
|
||||
pb.brain_tasks = []
|
||||
|
||||
# Add ONE check
|
||||
def check_disk():
|
||||
import shutil
|
||||
usage = shutil.disk_usage(".")
|
||||
percent = (usage.used / usage.total) * 100
|
||||
return {
|
||||
"status": "error" if percent > 90 else "ok",
|
||||
"percent": percent
|
||||
}
|
||||
|
||||
pb.pulse_checks.append(PulseCheck("disk", check_disk, 600))
|
||||
|
||||
# Add ONE brain task
|
||||
pb.brain_tasks.append(BrainTask(
|
||||
name="disk-alert",
|
||||
check_type=CheckType.CONDITIONAL,
|
||||
prompt_template="Disk is {percent:.1f}% full. What should I delete?",
|
||||
condition_func=lambda data: data["status"] == "error"
|
||||
))
|
||||
|
||||
pb.start()
|
||||
```
|
||||
|
||||
**Result:**
|
||||
- Pulse checks disk every 10 minutes (zero cost)
|
||||
- Brain ONLY invokes if disk > 90%
|
||||
- Nothing else happens
|
||||
|
||||
### Example 2: Only Morning Briefing (No Monitoring)
|
||||
|
||||
```python
|
||||
pb = PulseBrain(agent)
|
||||
pb.pulse_checks = [] # No monitoring
|
||||
pb.brain_tasks = []
|
||||
|
||||
# ONE scheduled brain task
|
||||
pb.brain_tasks.append(BrainTask(
|
||||
name="briefing",
|
||||
check_type=CheckType.SCHEDULED,
|
||||
schedule_time="08:00",
|
||||
prompt_template="Good morning! What are my pending tasks?",
|
||||
send_to_platform="slack",
|
||||
send_to_channel="C12345"
|
||||
))
|
||||
|
||||
pb.start()
|
||||
```
|
||||
|
||||
**Result:**
|
||||
- No pulse checks (zero monitoring)
|
||||
- Brain invokes once per day at 8:00 AM
|
||||
- Sends to Slack
|
||||
|
||||
### Example 3: Zero Automation (Pure Chat Bot)
|
||||
|
||||
```python
|
||||
# Don't use Pulse & Brain at all
|
||||
# Don't use TaskScheduler at all
|
||||
|
||||
from agent import Agent
|
||||
from adapters.runtime import AdapterRuntime
|
||||
|
||||
agent = Agent(provider="claude")
|
||||
runtime = AdapterRuntime(agent)
|
||||
runtime.add_adapter(slack_adapter)
|
||||
|
||||
await runtime.start()
|
||||
|
||||
# Now the bot ONLY responds to user messages
|
||||
# No monitoring, no automation, no scheduled tasks
|
||||
```
|
||||
|
||||
**Result:**
|
||||
- Bot only responds when users message it
|
||||
- Zero background activity
|
||||
- Zero automated brain invocations
|
||||
|
||||
## 🔍 How to Know What's Running
|
||||
|
||||
### Check Configuration Before Starting
|
||||
|
||||
```python
|
||||
pb = PulseBrain(agent)
|
||||
|
||||
print("Pulse checks that will run:")
|
||||
for check in pb.pulse_checks:
|
||||
print(f" - {check.name} (every {check.interval_seconds}s)")
|
||||
|
||||
print("\nBrain tasks that will run:")
|
||||
for task in pb.brain_tasks:
|
||||
if task.check_type == CheckType.SCHEDULED:
|
||||
print(f" - {task.name} (scheduled {task.schedule_time})")
|
||||
else:
|
||||
print(f" - {task.name} (conditional)")
|
||||
|
||||
# If you don't like what you see, modify before starting:
|
||||
# pb.pulse_checks = [...]
|
||||
# pb.brain_tasks = [...]
|
||||
|
||||
pb.start()
|
||||
```
|
||||
|
||||
### Monitor Runtime Activity
|
||||
|
||||
```python
|
||||
pb.start()
|
||||
|
||||
# Check how many times brain was invoked
|
||||
status = pb.get_status()
|
||||
print(f"Brain invoked {status['brain_invocations']} times")
|
||||
print(f"Latest pulse data: {status['latest_pulse_data']}")
|
||||
```
|
||||
|
||||
## 🛡️ Safety Guardrails
|
||||
|
||||
### 1. Explicit Configuration Required
|
||||
|
||||
Nothing monitors unless you:
|
||||
1. Define a `PulseCheck` function
|
||||
2. Add it to `pb.pulse_checks`
|
||||
3. Call `pb.start()`
|
||||
|
||||
```python
|
||||
# This does NOTHING:
|
||||
def my_check():
|
||||
return {"status": "ok"}
|
||||
|
||||
# You must explicitly add it:
|
||||
pb.pulse_checks.append(PulseCheck("my-check", my_check, 60))
|
||||
```
|
||||
|
||||
### 2. Brain Only Invokes on YOUR Conditions
|
||||
|
||||
```python
|
||||
# Brain will NOT run unless:
|
||||
BrainTask(
|
||||
condition_func=lambda data: YOUR_CONDITION_HERE
|
||||
# or
|
||||
schedule_time="YOUR_TIME_HERE"
|
||||
)
|
||||
```
|
||||
|
||||
**The agent cannot change these conditions.**
|
||||
|
||||
### 3. No Self-Modification
|
||||
|
||||
The Pulse & Brain system **cannot**:
|
||||
- Add new checks while running
|
||||
- Modify intervals while running
|
||||
- Change conditions while running
|
||||
|
||||
To change monitoring, you must:
|
||||
1. Stop the system
|
||||
2. Modify configuration
|
||||
3. Restart
|
||||
|
||||
```python
|
||||
pb.stop()
|
||||
pb.pulse_checks.append(new_check)
|
||||
pb.start()
|
||||
```
|
||||
|
||||
## 💡 Recommended Approach
|
||||
|
||||
### For Most Users: Start Clean
|
||||
|
||||
```python
|
||||
from agent import Agent
|
||||
from pulse_brain import PulseBrain, PulseCheck, BrainTask, CheckType
|
||||
|
||||
agent = Agent(provider="claude")
|
||||
pb = PulseBrain(agent)
|
||||
|
||||
# Remove all defaults
|
||||
pb.pulse_checks = []
|
||||
pb.brain_tasks = []
|
||||
|
||||
print("Starting with zero checks.")
|
||||
print("Now YOU add only what you want to monitor.")
|
||||
|
||||
# Add checks one by one, with full understanding
|
||||
pb.pulse_checks.append(PulseCheck(
|
||||
name="thing-i-want-to-monitor",
|
||||
check_func=my_check_function,
|
||||
interval_seconds=300
|
||||
))
|
||||
|
||||
pb.start()
|
||||
```
|
||||
|
||||
### Advanced: Use Configuration File
|
||||
|
||||
Create `my_monitoring_config.py`:
|
||||
|
||||
```python
|
||||
from pulse_brain import PulseCheck, BrainTask, CheckType
|
||||
|
||||
def check_server():
|
||||
# Your check here
|
||||
return {"status": "ok"}
|
||||
|
||||
MY_PULSE_CHECKS = [
|
||||
PulseCheck("server", check_server, 60)
|
||||
]
|
||||
|
||||
MY_BRAIN_TASKS = [
|
||||
BrainTask(
|
||||
name="server-down",
|
||||
check_type=CheckType.CONDITIONAL,
|
||||
prompt_template="Server is down. Help!",
|
||||
condition_func=lambda d: d["status"] == "error"
|
||||
)
|
||||
]
|
||||
```
|
||||
|
||||
Then in your main script:
|
||||
|
||||
```python
|
||||
from my_monitoring_config import MY_PULSE_CHECKS, MY_BRAIN_TASKS
|
||||
|
||||
pb = PulseBrain(agent)
|
||||
pb.pulse_checks = MY_PULSE_CHECKS # Your config
|
||||
pb.brain_tasks = MY_BRAIN_TASKS # Your config
|
||||
pb.start()
|
||||
```
|
||||
|
||||
**Now your monitoring is:**
|
||||
1. Version controlled
|
||||
2. Reviewable
|
||||
3. Explicit
|
||||
4. Under YOUR control
|
||||
|
||||
## 🎯 Summary
|
||||
|
||||
| Question | Answer |
|
||||
|----------|--------|
|
||||
| **Who decides what to monitor?** | YOU (via code/config) |
|
||||
| **Can agent add monitors?** | NO |
|
||||
| **Can agent change intervals?** | NO |
|
||||
| **Can agent modify conditions?** | NO |
|
||||
| **What does agent control?** | Only its responses to YOUR prompts |
|
||||
| **Can I start with zero automation?** | YES (clear pulse_checks and brain_tasks) |
|
||||
| **Can I disable defaults?** | YES (remove from lists before calling start()) |
|
||||
|
||||
**Bottom line:** The Pulse & Brain system is a framework YOU configure. The agent is a tool that executes YOUR monitoring strategy, not an autonomous system that decides what to watch.
|
||||
|
||||
You are in complete control. 🎛️
|
||||
Reference in New Issue
Block a user