# 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. 🎛️