Overview
Pulse is designed to be embedded in an agent kernel, the orchestration layer that manages the agent’s lifecycle, memory, and execution. This guide shows how to wire Pulse into your system.Architecture Context
Pulse is independent of the kernel. It doesn’t know about:- How agents are implemented
- How memory is stored
- How tools are executed
- How to detect signals
- How to compute relevance scores
- How to form scoped questions
- Registering modules with Pulse
- Handling escalation callbacks
- Providing training feedback
from pathlib import Path
from pulse import PulseRegistry
class AgentKernel:
def __init__(self):
# Initialize Pulse
self.pulse = PulseRegistry(
watch_dirs=[], # Populated from module fingerprints
threshold=0.65, # Global default (can be overridden per-module)
model_save_path=Path.home() / ".macroa" / "pulse" / "models"
)
# Track activation IDs for feedback
self._active_questions: dict[str, str] = {} # question -> activation_id
# Don't start yet - register modules first
watch_dirs: Start empty; directories are added when modules registerthreshold: Default relevance threshold (0.0–1.0)model_save_path: Where to persist model weights (set to None to disable persistence)class AgentKernel:
def register_pulse_module(self, module_id: str, fingerprint: dict):
"""
Register a module with Pulse.
The fingerprint can come from:
- A static configuration file
- The module's own registration method
- Dynamic generation based on user preferences
"""
try:
self.pulse.register_module(module_id, fingerprint)
print(f"✓ Registered {module_id} with Pulse")
except ValueError as e:
print(f"✗ Failed to register {module_id}: {e}")
# Static registration during kernel init
kernel = AgentKernel()
homework_fingerprint = {
"module_id": "homework-agent",
"cluster": "academic",
"version": "1.0",
"question_template": "A new file appeared at {location}. Is this file related to a course assignment or homework?",
"default_threshold": 0.65,
"signal_priors": {
"filesystem": {
"watch_directories": ["~/Downloads", "~/Documents"],
"relevant_extensions": [".pdf", ".docx", ".pptx"],
"irrelevant_extensions": [".exe", ".zip"]
},
"time": {
"active_hours": [8, 23],
"active_days": [0, 1, 2, 3, 4],
"typical_interval_hours": 24
}
}
}
kernel.register_pulse_module("homework-agent", homework_fingerprint)
from pulse import EscalationDecision
class AgentKernel:
def _on_pulse_escalation(self, decision: EscalationDecision):
"""
Called by Pulse when a module's relevance score exceeds threshold.
Responsibility:
1. Wake the agent with the scoped question
2. Track the activation for later feedback
3. Let the agent handle the question
"""
print(f"\n[PULSE] {decision.module_id} triggered")
print(f" Question: {decision.question}")
print(f" Confidence: {decision.confidence:.2f}")
# Track this activation (needed for feedback later)
# Note: The current EscalationDecision doesn't include activation_id,
# so we'll need to derive it or enhance the API
activation_id = self._track_activation(decision)
# Wake the agent with the scoped question
result = self.agent.handle_question(
question=decision.question,
context={
"module_id": decision.module_id,
"confidence": decision.confidence,
"events": decision.triggering_events
}
)
# Provide feedback based on result
self._provide_feedback(activation_id, result)
def _track_activation(self, decision: EscalationDecision) -> str:
"""
Store the activation for later feedback.
In the current architecture, we need to manually create an activation
record. Future versions may include the activation_id in the
EscalationDecision.
"""
# The registry already recorded the activation, but we don't have the ID
# This is a design limitation - see pulse/registry.py:152
# For now, generate a synthetic ID based on the question
activation_id = hash(decision.question)
self._active_questions[decision.question] = str(activation_id)
return str(activation_id)
def _provide_feedback(self, activation_id: str, result):
"""
Provide training feedback based on agent's response.
"""
# Calculate label based on what the agent did
if result.action_taken:
# Agent took action (wrote memory, executed tool, etc.)
label = 1.0
elif result.dismissed:
# Agent explicitly dismissed as irrelevant
label = 0.0
else:
# Agent acknowledged but took no action (maybe informational)
label = 0.5
# Submit feedback
self.pulse.record_feedback(activation_id, label)
Design Note: The current
EscalationDecision doesn’t include the activation_id that was created in pulse/registry.py:152. This means the kernel must track the relationship between questions and activation IDs manually.A future enhancement would be to include activation_id in the EscalationDecision dataclass.class AgentKernel:
def start(self):
"""Start the kernel and Pulse subsystem."""
# Register the escalation callback
self.pulse.on_escalation(self._on_pulse_escalation)
# Start Pulse (begins watching filesystem, time ticks, etc.)
self.pulse.start()
print("✓ Pulse is running")
print(f" Watching: {self.pulse._watch_dirs}")
# Start other kernel components...
def stop(self):
"""Gracefully shut down the kernel."""
print("Shutting down Pulse...")
# Stop Pulse (saves model weights)
self.pulse.stop()
print("✓ Pulse stopped and models saved")
class Agent:
def handle_question(self, question: str, context: dict):
"""
Process a scoped question from Pulse.
Returns:
Result object with:
- action_taken: bool
- dismissed: bool
- confidence_score: float
"""
# Use LLM or rule-based logic to answer the question
response = self.reason(question, context)
# Decide if action is needed
if self._is_relevant(response):
# Take action (e.g., store in memory, notify user)
self.memory.write(f"/pulse/{context['module_id']}/last_seen", {
"question": question,
"timestamp": time.time(),
"response": response
})
return Result(action_taken=True, dismissed=False, confidence_score=0.9)
else:
return Result(action_taken=False, dismissed=True, confidence_score=0.3)
Complete Integration Example
Here’s a minimal kernel with Pulse integration:Advanced: Dynamic Module Registration
Modules can be registered at runtime based on user activity:Troubleshooting
Pulse starts but no escalations occur
Pulse starts but no escalations occur
Check:
- Are modules registered before
pulse.start()? - Are watch directories correct? Print them:
- Is the escalation handler registered?
- Make a test file in a watched directory and check Layer 1 output
How do I get the activation_id for feedback?
How do I get the activation_id for feedback?
The current architecture has a gap:
EscalationDecision doesn’t include the activation_id created in pulse/registry.py:152.Workaround:- Hash the question to create a synthetic ID:
- Track the mapping yourself in the kernel
EscalationDecision to include activation_id:Models not persisting between runs
Models not persisting between runs
Check that And that you call
model_save_path is set:pulse.stop() before exit (this triggers model saving).Can I run multiple PulseRegistry instances?
Can I run multiple PulseRegistry instances?
Not recommended. Pulse uses filesystem watchers (via
watchdog), which can conflict if multiple instances watch the same directories.If you need multiple kernels, use a single shared PulseRegistry and route escalations based on module_id.Best Practices
Register modules early
Register all modules before calling
pulse.start(). While dynamic registration works, it’s cleaner to register upfront.Always provide feedback
The training loop depends on feedback. Even simple heuristics (action taken → 1.0, dismissed → 0.0) improve model accuracy over time.
Set model_save_path
Always persist models. Without persistence, the model resets to synthetic priors on every restart, losing learned patterns.
Monitor escalation frequency
If escalations are too frequent (noise), increase
default_threshold. If too rare (missing events), lower it or provide more training data.Next Steps
Registering Modules
Learn how to create signal fingerprints
Training Models
Understand online learning and feedback
Monitoring Signals
Debug signal flow and troubleshoot issues
Architecture
Deep dive into Pulse’s three-layer design