Playbook Engine and Self-Evolution
The playbook.go module implements a structured workflow engine that allows the assistant to execute predefined, multi-step tasks. More impressively, it features a "Self-Evolution" mechanism that automatically abstracts successful, ad-hoc agent plans into reusable playbooks.
Playbook Structure
A Playbook is a JSON-defined workflow that maps a user's intent to a specific sequence of tool executions.
- Trigger: A regex pattern (e.g.,
(?i)daily pulse) that activates the playbook. - NegativeTriggers: Regex patterns that explicitly prevent the playbook from running (to avoid false positives).
- RunAsRole: Allows a playbook to temporarily escalate privileges (e.g., executing as
MasterAdmin) for specific automated tasks. - Steps: A sequential array of tasks, specifying the Agent, Tool, and Arguments.
- OwnerAgent: The agent that owns and executes the playbook.
- OwnerUser: The user who owns the playbook (for user-specific playbooks).
- AutoExecute: Whether the playbook executes automatically when triggered.
Regex Caching and Safety
To ensure high performance and prevent ReDoS (Regular Expression Denial of Service) attacks, safeRegexMatch employs:
- A
regexCacheusingsync.RWMutex. - A maximum pattern length of 500 characters.
- A blocklist of dangerous patterns (e.g.,
\(.{1,10000}\)\*). - A 500ms timeout for regex matching.
Directory Structure
Playbooks are organized by scope and ownership:
assistant/playbooks/
├── global/ # Global playbooks (all users/agents)
│ ├── dlan_health_check.json
│ ├── london_hosting_check.json
│ ├── london_hosting_weekly.json
│ └── wow_news_briefing.json
├── analyst/ # Analyst agent playbooks
│ └── snow_trend_report.json
├── nova/ # Nova agent playbooks
│ ├── london_hosting_standup.json
│ └── nova_health_check.json
├── nikki/ # Nikki agent playbooks
│ └── free_games_check.json
├── dan/ # User-specific playbooks (Master Dan)
│ ├── morning_infrastructure_summary.json
│ ├── weekly_tech_roundup.json
│ └── wow_quick_check.json
├── delicious/ # Delicious agent playbooks
│ ├── delicious_ent_health_check.json
│ └── delicious_uk_health_check.json
├── sysafe/ # Sysafe agent playbooks
│ └── sysafe_health_check.json
└── candidates/ # AI-generated playbook candidates (staging)
└── [pending review]
Key Playbooks
Server Health Playbook
File: assistant/playbooks/global/dlan_health_check.json
- Name: Gadgetzan Infrastructure Health Check
- Owner:
global - Trigger:
(?i)\b(dlan\s+(status|health|check)|gadgetzan\s+status|check\s+dlan)\b - AutoExecute: true
- Steps:
- Agent:
sasha- Run health data collection (dlan_health_check, system_vitals, unifi_network) - Agent:
nikki- Send consolidated WhatsApp message to Dan
- Agent:
WoW News Briefing (Improved Summarizer)
File: assistant/playbooks/global/wow_news_briefing.json
- Name: WoW News Briefing
- Owner:
global - Trigger:
(?i)\b(wow\s+news|world\s+of\s+warcraft\s+news|news\s+from\s+wowhead)\b - AutoExecute: true
- Notes: Daily run (often via scheduler). Uses a dedicated summarization step (step 3) that receives full
{step_1_result}+{step_2_result}and is explicitly instructed to output only clean, scannable briefing text before the final send. - Steps:
- Agent:
sasha- Fetch today-in-wow markdown (active events + class changes) - Agent:
sasha- Fetch retail markdown - Agent:
nikki(free model) - Dedicated summarizer step that condenses the two raw sources into a tight daily briefing - Agent:
nikki- Send the clean summarized message to Dan
- Agent:
Standups & Health Playbooks (Agent-Owned)
Several short 2-3 step playbooks owned by nova, delicious, sysafe, and analyst follow the "gather data → finish_task with {step_N_result} embedded" pattern for domain-specific reporting. These are valid when the final answer string actually contains the previous step data.
Free Games Playbook
File: assistant/playbooks/nikki/free_games_check.json
- Name: Daily Free Games Briefing
- Owner:
nikki - Trigger:
(?i)\b(free\s+games|check\s+steam|check\s+epic|any\s+freebies)\b - AutoExecute: true
- Steps:
- Agent:
nikki- Callliaagent to find free games on Steam/Epic - Agent:
nikki- Send Discord message to gaming channel - Agent:
nikki- Send WhatsApp message to gaming group - Agent:
nikki- Send WhatsApp message to gaming group
- Agent:
Recent Changes (commits a9f3e540, 08c13f5b)
| Change | Description |
|---|---|
| Agent-Specific Reorganization | Playbooks moved into agent-specific directories (analyst/, nova/, nikki/, etc.) |
| Free Games Playbook | Added daily free games briefing playbook |
| Iteration Limits | Reduced iteration limits for playbook execution |
| Flash Model Notifications | Notification steps switched to flash model for reliability |
Loading and Registration
Startup Loading
Playbooks are loaded on startup via LoadPlaybooks():
// assistant/assistant.go
func init() {
LoadPlaybooks(ResolveAssistantPath(PlaybooksDir))
}
Directory Discovery
The system discovers playbook directories automatically:
func getUserPlaybookDirs(baseDir string) ([]string, error) {
// Returns subdirectories excluding "global" and "candidates"
// e.g., ["analyst", "nova", "nikki", "dan", "sysafe", "delicious"]
}
Registration
Playbooks are registered in the global playbookRegistry:
type PlaybookKey struct {
User string // "global" or username
Agent string // agent name
Name string // playbook name
}
playbookRegistry[PlaybookKey{User, Agent, Name}] = Playbook
Matching and Execution
Finding Playbooks
FindPlaybookForQuery() matches user queries to playbooks:
- Normalize userID and agentName to lowercase
- Strip system tags from query
- Check user-specific playbooks first (scope: user + agent)
- Check global playbooks (scope: global or agent-matched)
- Validate trigger with
safeRegexMatch() - Check
NegativeTriggers(regex mismatch prevents triggering) - Perform RBAC check via
CanUserExecutePlaybook()
Execution Flow
ExecutePlaybook() orchestrates playbook execution:
- Create execution plan from
p.Steps - Resolve placeholders from regex matches (
{query_group_1}) - Load agents via
LoadAgents("assistant/prompts/agent") - Choose planner agent (default:
nikki) - Create planner and adaptive planner sessions
- Execute via
session.SuperviseAdaptiveExecution(ctx) - Cache results (
playbookCacheTTL = 8 * time.Minute)
Placeholder Resolution
{query_group_N}: Captured regex groups from trigger{step_N_result}: Output from previous step N{step_N_result.field}: Specific field from step N output
Self-Evolution: The "Hunt"
One of the most powerful features of the assistant is its ability to learn. The RunSelfEvolutionPass() and HuntHistoricalPlaybooks() functions implement this.
- The Hunt: Periodically, the system scans the Observability DB (or legacy
.jsonlsession logs) for agent sessions that had at least 2 tasks and completed successfully. - Buffering: Successful plans are saved to
assistant/memory/evolution_buffer/. - Abstraction: During quiet periods, the
architectagent analyzes these raw execution logs and abstracts them into generic, reusable Playbook JSON definitions. - Manifestation: The new candidate playbooks are saved to
assistant/playbooks/candidates/for human review before becoming active.
Candidate Promotion
Admins can promote candidate playbooks:
// assistant/missioncontrol.go
func promoteCandidateToUser(candidatePath, username string) error {
// Move candidate to user's playbooks directory
// Set OwnerUser field
// Trigger LoadPlaybooks() to refresh registry
}
RBAC and Security
Tool Access Check
CanUserExecutePlaybook() ensures required tools are accessible:
func CanUserExecutePlaybook(role string, p *Playbook) bool {
// Check if user role has access to all tools in playbook steps
// Return false if any tool is restricted
}
Model Overrides
Playbooks can override models at multiple levels:
- Global Override:
ModelOverridefield in playbook - Step Override:
Step.ModelOverridefor individual steps - Default: Uses agent's configured model
Performance and Caching
Result Caching
Playbook results are cached to prevent duplicate executions:
const playbookCacheTTL = 8 * time.Minute
func getCachedPlaybookResult(key string) (string, bool)
func setCachedPlaybookResult(key, value string)
Cache Key Format
playbook:{user}:{agent}:{name}:{query_hash}
Ownership, Contacts & Runtime Statistics
Every approved playbook now carries a human-friendly owner field (in addition to the existing owner_agent and owner_user):
{
"name": "WoW News Briefing",
"owner_agent": "nikki",
"owner_user": "",
"owner": "global"
}
owneris populated automatically on load if missing (falls back to owner_user → owner_agent → "global").- All 14 approved playbooks have been updated with consistent
ownervalues.
Contacts note: contacts.json only contains individual people (with whatsapp_lid, whatsapp_jid, etc.). Group broadcasts (London-Hosting @g.us, NOC groups, gaming HQ, etc.) still use raw JIDs in the playbook JSONs. A future improvement could add a groups section to contacts.json with lookup support in SendMessageAsTool.
Runtime Statistics (lightweight table)
A new playbook_stats table was added to observability.db for fast per-playbook counters (no more full scans of the large sessions table for basic health):
EnsurePlaybookStatsTable()helper (idempotent, called at DB init).RecordPlaybookRun(...)called automatically fromExecutePlaybookon every termination (success or failure). Records: total_runs, successes, failures, avg/last duration, last error, step completion counts, owner info, timestamps.GetPlaybookRuntimeStats()for Mission Control / agents.- Detailed per-execution logs also go to
assistant/logs/playbooks/playbook_*.logand the session JSONL files (search forplaybook_matched,playbook_*_step_*).
You can query the table directly:
SELECT playbook_name, owner, total_runs, successes, failures,
ROUND(successes*100.0/total_runs,1) as success_pct,
last_executed
FROM playbook_stats ORDER BY total_runs DESC;
This gives instant visibility into which playbooks are healthy (e.g. Gadgetzan 100% over 49 runs) vs. ones that need attention (e.g. London-Hosting Weekly had some failures in its history).
Guidance for AI Agents
- Playbook Validation: When creating or editing a playbook JSON file, ensure the regex triggers are highly specific to avoid accidental activation.
- Review Candidates: MasterAdmin agents should periodically review the
candidates/directory to promote newly evolved playbooks into theglobal/directory. - RBAC Compliance: Always check tool access before executing playbook steps.
- Error Handling: Implement proper error handling and fallback logic for failed steps.