NetSendo Logo
Platform Updates

NetSendo v2.0.12: Brain AI Autonomy, Performance Scoring & Webhook Overhaul

NetSendo TeamJuly 9, 20269 min read
NetSendo v2.0.12: Brain AI Autonomy, Performance Scoring & Webhook Overhaul

πŸš€ The Smartest NetSendo Yet β€” Meet v2.0.12

What separates a good marketing automation platform from a great one? The ability to learn from the past and act on that knowledge automatically. NetSendo v2.0.12 does exactly that β€” introducing a performance-driven scoring dimension into the Brain AI engine, giving each agent its own autonomy level, and wiring up a calendar-based execution pipeline that turns your weekly strategy into hands-free campaign delivery.

On top of the AI upgrades, this release also ships a comprehensive webhook reliability overhaul: the per-list webhook finally fires for all subscriber lifecycle events, the event picker now exposes the full canonical vocabulary, and two longstanding bugs (a missing secret default and silent per-list delivery failures) are fully resolved. If you rely on webhooks to connect NetSendo to n8n, Zapier, or your own backend β€” this update is required reading.

TL;DR: v2.0.12 adds a performance_affinity scoring dimension (task scores now 0–125), per-agent autonomy modes (autonomous / semi-auto / manual per agent), calendar-driven autonomous campaign execution, a strategy & agent settings UI, and a full webhook reliability overhaul covering the per-list event picker, silent delivery failures, and a secret auto-generation fix. Several critical bugs in bounce settings, unsubscribe HTTP codes, backup, and the message editor are also resolved.

🧠 What's New in Brain AI

1 β€” Performance-Driven Task Scoring: The 5th Dimension

The Brain's TaskScorer previously evaluated tasks across four dimensions with a maximum total score of 100. v2.0.12 adds a fifth: performance_affinity, a 0–25 point scale that rewards tasks closely matching your historically successful patterns β€” winning days of the week, peak send hours, high-performing campaign types, and effective subject line patterns.

The new PerformanceLearner signals are injected into gatherScoringContext() via PerformanceLearner::getTuningSignals(), giving the scorer a data-driven picture of what actually works for your audience. The result: the Brain naturally gravitates toward repeating successful patterns without any manual configuration.

πŸ“Š

Score Range: 0–125

Task scores now span 0–125 (up from 0–100), with the new performance_affinity dimension contributing up to 25 points.

πŸ”

Pattern Recognition

Rewards tasks that match winning days, hours, campaign types, and subject patterns from your history.

βš™οΈ

Automatic & Zero-Config

No manual tuning needed β€” PerformanceLearner signals flow automatically into every scoring cycle.

ℹ️ Note: The 5th scoring dimension is additive. Existing tasks will be re-scored on their next evaluation cycle β€” no data migration required.

2 β€” Strategy-Aware AI Analysis & Campaign Planning

The Brain's AI prompts have been substantially enriched. SituationAnalyzer now injects two new context blocks into every analysis prompt: PERFORMANCE INSIGHTS (your top-performing days, hours, and campaign types) and STRATEGY CONSTRAINTS (tone, excluded days, send limits, goal focus). Two new prompt instructions (9 & 10) explicitly require the AI to respect these user-defined constraints and leverage historical data in every recommendation.

The CampaignCalendarService weekly planning prompt receives the same treatment β€” excluded days, max weekly sends, preferred hours, tone, and goal focus are all woven into the calendar generation logic. Your strategy settings are no longer advisory; they are enforced at the AI level.

3 β€” Calendar-Driven Autonomous Campaign Execution

This is the headline automation feature of v2.0.12. The CRON pipeline now includes a new executeDueCalendarEntries() method that automatically picks up AiCampaignCalendar entries where planned_date <= today and status = 'draft', converts them into fully-formed tasks, and routes them through the agent orchestrator.

  • βœ… Calendar entries automatically become real campaigns β€” no manual trigger needed
  • βœ… Weekly send limits from your strategy settings are enforced automatically
  • βœ… A safety cap of 3 entries per CRON cycle prevents runaway execution
  • βœ… Full campaign context (type, audience, tone, strategic context) is preserved end-to-end
⚠️ Important: Calendar-driven execution respects the per-agent autonomy mode (see below). A Campaign agent set to manual will log calendar entries as suggestions rather than executing them.

4 β€” Per-Agent Autonomy Mode Routing

Previously, the Brain operated in a single global work mode. v2.0.12 replaces this with individual autonomy levels per agent. Every task now checks its agent's mode via $settings->getAgentMode($agentType) and routes accordingly:

ModeBehavior
autonomousExecute immediately via AgentOrchestrator::executeCronTask()
semi_autoCreate action plan + send Telegram approval request
manualLog as suggestion, skip execution

This granular control means you can, for example, trust the Campaign agent to run fully autonomously while keeping the CRM agent on semi-auto for human review, and the List agent on manual until you're comfortable with its recommendations.

5 β€” Strategy & Agent Mode Settings UI

All of the above is configurable through a new, dedicated section in the Brain Settings page. Two panels have been added:

🧩 Agent Mode Grid

A 7-agent grid covering Campaign, List, Message, CRM, Analytics, Segmentation, and Research agents β€” each with its own dropdown for Autonomous / Semi-Auto / Manual. Changes are saved independently via PUT /brain/api/settings.

🎯 Campaign Strategy Settings

A full strategy configuration panel including:

  • Communication tone selector (professional, casual, friendly, formal, humorous)
  • Max campaigns per week slider (1–20)
  • Excluded days toggle buttons (Mon–Sun)
  • Preferred send hours (from/to range)
  • Goal focus selector (engagement, conversion, retention, growth)
  • Preferred topics input (comma-separated)

Strategy settings are persisted as a deep-merged JSON structure in AiBrainSettings.strategy_settings, so partial updates never overwrite unrelated fields.

πŸ’‘ Pro Tip: Start with your Campaign agent on semi_auto for the first week. Review the Telegram approval requests to build confidence in the AI's decisions, then switch to autonomous once the patterns match your expectations.

πŸ”— What's New in Webhooks

Full Subscriber Lifecycle Event Picker (GitHub #20)

The per-list webhook event picker in List Settings β†’ Integration previously offered only four legacy short names: subscribe, unsubscribe, update, bounce. These didn't match the canonical event names the webhook pipeline actually dispatches, creating a silent mismatch.

v2.0.12 replaces the legacy picker with the full canonical event set:

[
  "subscriber.created",
  "subscriber.subscribed",
  "subscriber.unsubscribed",
  "subscriber.bounced",
  "subscriber.tag_added",
  "subscriber.tag_removed"
]

Existing configurations are automatically migrated β€” legacy short names are mapped to their canonical equivalents both when the settings page loads and on save. No manual reconfiguration is needed, and no webhook configuration is lost on upgrade. i18n labels for all six events have been added in all four supported locales (en, pl, de, es).

Per-List Webhook Now Fires for All Real Events (GitHub #20)

This was a significant reliability gap: a list's webhook_url was only delivered from a small number of inline call sites (the API subscribe/unsubscribe endpoints, form submissions, and the Test button). Subscriber events originating from the Web UI, unsubscribe links, bounce processing, CSV import, and tag changes were silently dropped and never appeared in webhook_logs.

DispatchWebhooksListener now delivers to the relevant list's webhook_url for every subscriber-lifecycle event β€” asynchronously via the new queued DispatchListWebhookJob β€” and records delivery in webhook_logs exactly like account-level webhooks. Additionally, the redundant inline triggerWebhook('subscribe') call in FormSubmissionService has been removed (the listener covers it via SubscriberSignedUp), eliminating duplicate deliveries for form submissions.

⚠️ Important: If you were relying on the per-list webhook for tag-based automation (e.g., triggering n8n flows on tag changes), those events were never being delivered before v2.0.12. After upgrading, expect to start receiving subscriber.tag_added and subscriber.tag_removed events for the first time.

πŸ› Critical Bug Fixes

Webhook Secret Auto-Generation (GitHub #20)

The webhooks.secret column was NOT NULL with no default value, causing any webhook creation path other than Webhook::createWithSecret() to abort with SQLSTATE[HY000] 1364. The Webhook model now auto-generates a 64-character secret on the creating Eloquent event regardless of entry point. A new migration also relaxes the column to nullable as a belt-and-suspenders guard against raw SQL inserts.

Global Unsubscribe Returns HTTP 403 on Bad Signatures (GitHub #15)

All four public unsubscribe endpoints were returning 200 OK when a signed-URL signature was invalid, tampered, or expired β€” masking authorization failures as successful responses. renderSystemPage() now accepts an HTTP status argument and all four signature-failure paths correctly return 403 Forbidden. The user-facing error page content is unchanged; only the status code is corrected.

Bounce Scope & Soft Bounce Threshold Settings Never Saved (GitHub #14)

The list settings form sent settings.advanced.bounce_scope and settings.advanced.soft_bounce_threshold, but the controller's validation rules only whitelisted settings.advanced.bounce_analysis. Since Laravel's $request->validate() returns only validated keys, both fields were silently stripped on every save β€” the UI showed "settings saved" while the values snapped back to defaults. Missing validation rules have been added and applied consistently to list creation, list update, and global default settings.

Backup mysqldump Crashes on MariaDB Client (GitHub #11)

The --ssl-mode=DISABLED flag added in a previous SSL fix is a MySQL-client-only option. The app image ships the MariaDB client, which doesn't recognize it and aborts immediately. The option has been switched to the MariaDB-compatible --ssl=0, matching the [client] ssl=0 already set in /etc/my.cnf. Backups no longer crash on the dump step.

Message Editor Tag Quick-Select Submitted the Form

Tag quick-select buttons in the message recipients panel were missing type="button", causing them to default to type="submit" inside their surrounding form. Clicking a tag saved the message and redirected away instead of selecting lists. type="button" has been added so clicks only run toggleByTag().


🎯 Real-World Use Cases

πŸ›’

E-commerce: Fully Autonomous Seasonal Campaigns

Set your Campaign agent to autonomous, configure a strategy with tone: friendly, goal: conversion, and max 5 campaigns/week. The Brain generates and schedules your promotional calendar, picks optimal send times based on your historical data, and executes due entries automatically β€” without you lifting a finger between planning sessions.

πŸ“±

SaaS: Tag-Driven Onboarding via n8n

With the fixed per-list webhook and the new subscriber.tag_added event, you can now reliably trigger n8n workflows the moment a user completes an onboarding step (tagged as onboarding_complete). Previously, tag-based webhook events were silently dropped β€” this is now fully operational in v2.0.12.

🏒

Agencies: Supervised AI with Telegram Approvals

For client accounts where you want AI assistance but human sign-off, set the Campaign agent to semi_auto. The Brain drafts the campaign plan, sends it to your Telegram for approval, and only executes after you confirm. You get the speed of AI planning with the accountability of human review β€” ideal for compliance-sensitive industries.


βš™οΈ Step-by-Step: Configuring Brain Autonomy & Strategy

  1. Open Brain Settings

    Navigate to Brain β†’ Settings in your NetSendo dashboard. You'll see two new panels below the existing configuration.

  2. Set Per-Agent Modes

    In the 🧩 Agent Modes grid, select an autonomy level for each of the 7 agents. Start conservatively β€” semi_auto is recommended for new deployments so you can review AI decisions before granting full autonomy.

  3. Configure Campaign Strategy

    In the 🎯 Campaign Strategy panel, set your communication tone, weekly send cap, excluded days (e.g., weekends), preferred send window, and goal focus. These constraints are enforced at the AI prompt level.

  4. Generate a Campaign Calendar

    Go to Brain β†’ Calendar and trigger a new weekly plan. Verify the generated entries respect your excluded days and send limits before enabling autonomous execution.

  5. Enable Calendar Execution

    Once satisfied with calendar quality, set your Campaign agent to autonomous. From the next CRON cycle onward, due calendar entries will be executed automatically (up to 3 per cycle, within your weekly send cap).

  6. Verify Webhook Delivery

    After upgrading, go to Lists β†’ [Your List] β†’ Integration and confirm your event selections now show canonical names. Check Settings β†’ Webhooks β†’ Logs to verify events are being delivered across all trigger paths (Web UI, unsubscribe links, imports, tag changes).

πŸ’‘ Pro Tip: After upgrading, open each list's Integration settings page and click Save once β€” even without changes. This triggers the auto-migration of legacy event names to canonical names and ensures your webhook configurations are stored in the updated format.

🎯 Expert Tips

1
Let PerformanceLearner Accumulate Data Before Trusting It

The performance_affinity scoring dimension is only as good as the historical data behind it. For accounts with fewer than 10–15 completed campaigns, the performance signals will be sparse. Give it 2–3 weeks of campaign data before switching agents to autonomous mode β€” the scoring will be significantly more accurate.

2
Use Excluded Days to Protect Revenue-Critical Periods

The excluded days toggle in Strategy Settings isn't just for weekends. If you know your audience doesn't engage on Mondays (post-weekend inertia) or Fridays (pre-weekend distraction), exclude those days. The AI calendar generator and the calendar execution engine both respect this setting.

3
Use the Safety Cap to Your Advantage

The 3-entries-per-CRON-cycle cap is a safety feature, not a limitation. If your calendar has many due entries (e.g., after a system pause), they'll be processed in order across successive CRON runs rather than all at once. Schedule your CRON to run frequently (e.g., every 30 minutes) if you need timely execution of dense calendars.

4
Monitor Webhook Logs After Upgrading

Because per-list webhooks now fire for all lifecycle events (including tag changes and CSV imports), you may see a significant increase in webhook volume immediately after upgrading. Check your endpoint's rate limits and n8n workflow concurrency settings before deploying to production.

5
Validate Bounce Settings After the Fix

If you previously configured Bounce Scope or Soft Bounce Threshold in list settings, those values were never actually saved (they silently reverted to defaults). After upgrading to v2.0.12, open each list's advanced settings, re-enter your desired values, and save. This time they'll actually persist.


πŸ”„ How to Upgrade

v2.0.12 includes database migrations. Run the standard update sequence:

# Pull the latest image
docker compose pull

# Restart with migrations
docker compose up -d

# Verify migrations ran successfully
docker compose exec app php artisan migrate:status
⚠️ Important: Two new migrations ship with this release: one makes webhooks.secret nullable, and one is part of the Brain strategy settings persistence. Both are non-destructive and reversible. Always back up your database before upgrading β€” and note that the backup mysqldump bug is also fixed in this release, so your first backup after upgrade should complete cleanly.

πŸ“‹ Full Changelog Summary

  • βœ… Added: performance_affinity scoring dimension (0–25) in TaskScorer β€” total range now 0–125
  • βœ… Added: PERFORMANCE INSIGHTS & STRATEGY CONSTRAINTS injected into AI analysis and calendar prompts
  • βœ… Added: Calendar-driven autonomous campaign execution in CRON pipeline (safety cap: 3/cycle)
  • βœ… Added: Per-agent autonomy mode routing (autonomous / semi_auto / manual)
  • βœ… Added: Agent Mode Grid & Campaign Strategy Settings UI in Brain Settings
  • βœ… Added: Full canonical event set in per-list webhook event picker with auto-migration of legacy names
  • πŸ”„ Changed: Knowledge base auto-enrichment removed from CRON β€” now exclusively user-controlled
  • πŸ› Fixed: Webhook secret auto-generation on model creating event + nullable migration
  • πŸ› Fixed: Per-list webhook now fires for all subscriber lifecycle events via DispatchListWebhookJob
  • πŸ› Fixed: Global unsubscribe returns HTTP 403 (not 200) on invalid/expired signatures
  • πŸ› Fixed: Bounce Scope & Soft Bounce Threshold settings now correctly persisted
  • πŸ› Fixed: Backup mysqldump --ssl-mode=DISABLED replaced with MariaDB-compatible --ssl=0
  • πŸ› Fixed: Message editor tag quick-select buttons no longer submit the form

Ready to Let the Brain Take the Wheel?

v2.0.12 is available now on GitHub. Upgrade your self-hosted instance and start configuring per-agent autonomy and campaign strategy today.

#brain-ai#automation#webhooks#autonomous-campaigns#platform-updates#self-hosted#api
Share: