agentsclimarketplace

Frappe core notifications

Skill Impertio-Studio/Frappe_Claude_Skill_Package/skills/source/core/frappe-core-notifications

Use when implementing email notifications, system alerts, Assignment Rules, Auto Repeat, or ToDo items. Prevents misconfigured Email Accounts, broken notification templates, and silent delivery failures. Covers frappe.sendmail, Notification DocType, Email Account setup, Jinja email templates, Assignment Rules, Auto Repeat scheduling, ToDo API. Keywords: notification, email, sendmail, Email Account, Assignment Rule, Auto Repeat, ToDo, alert, template, notify on approval, email when status changes, alert, email not sending, notification not working..From its SKILL.md

Install
npx -y skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-core-notifications

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

10.0 KB, ~2.3k tokens by cl100k_base, as published. Nobody here has run it

Frappe Notification System

Quick Reference

ChannelMethodUse Case
Emailfrappe.sendmail()Programmatic email with full control
EmailNotification DocType (Email)No-code email on document events
Systemfrappe.publish_realtime()In-app real-time alerts via socket.io
SystemNotification DocType (System)No-code in-app alerts
SMSNotification DocType (SMS)No-code SMS on document events
SlackNotification DocType (Slack)No-code Slack webhook messages
Assignmentfrappe.desk.form.assign_to.add()Assign document to user (creates ToDo)
ToDofrappe.get_doc({"doctype": "ToDo", ...})Direct task creation
Commentdoc.add_comment("Comment", text)Timeline comment on document
Tagdoc.add_tag("tag_name")Document tagging for filtering

Decision Tree

What notification mechanism do you need?
│
├─ Email on document event (no code)?
│  └─ Notification DocType → Channel: Email
│
├─ Programmatic email with custom logic?
│  └─ frappe.sendmail() in server script or hook
│
├─ Real-time in-app notification?
│  ├─ No-code → Notification DocType → Channel: System Notification
│  └─ Programmatic → frappe.publish_realtime()
│
├─ SMS on document event?
│  └─ Notification DocType → Channel: SMS (requires SMS Settings)
│
├─ Assign document to user?
│  ├─ No-code → Assignment Rule DocType
│  └─ Programmatic → frappe.desk.form.assign_to.add()
│
├─ Recurring document creation?
│  └─ Auto Repeat DocType
│
└─ Add comment or tag?
   ├─ Comment → doc.add_comment("Comment", text="...")
   └─ Tag → doc.add_tag("tag_name")

Notification DocType

The Notification DocType enables no-code alerts across four channels.

Event Triggers

EventFires When
NewDocument is created
SaveDocument is saved
SubmitDocument is submitted
CancelDocument is cancelled
Value ChangeSpecific field value changes
Days BeforeN days before a date field value
Days AfterN days after a date field value
MethodCustom Python method is called

Condition Syntax

ALWAYS use Python expressions in the Condition field:

# Status-based
doc.status == "Open"

# Date-based
doc.due_date == nowdate()

# Threshold-based
doc.grand_total > 40000

# Combined
doc.status == "Overdue" and doc.grand_total > 10000

Available context: doc, nowdate(), frappe.utils.*.

Recipient Configuration

SourceDescription
Document FieldEmail/phone field on the document
RoleAll users with specified role
CustomHard-coded email address
All AssigneesAll users assigned to the document
ConditionJinja expression to filter recipients

Jinja Message Template

<h3>Order Overdue</h3>
<p>Transaction {{ doc.name }} has exceeded its due date.</p>

{% if comments %}
Last comment: {{ comments[-1].comment }} by {{ comments[-1].by }}
{% endif %}

<ul>
  <li>Customer: {{ doc.customer }}</li>
  <li>Amount: {{ doc.grand_total }}</li>
</ul>

Template variables: {{ doc }}, {{ doc.fieldname }}, {{ comments }}, {{ nowdate() }}.

Attach Print

Set Attach Print to include a PDF of the document. Select a Print Format for custom layout.


frappe.sendmail(): Programmatic Email

frappe.sendmail(
    recipients=["[email protected]"],       # list of email addresses
    subject="Invoice Due",                  # email subject
    message="<p>Your invoice is due.</p>",  # HTML body
    template="invoice_reminder",            # Jinja template name (optional)
    args={"customer": "ACME"},              # template context variables
    attachments=[{"fname": "inv.pdf", "fcontent": pdf_bytes}],
    reference_doctype="Sales Invoice",      # links email to document
    reference_name="SINV-00001",
    delayed=True,                           # queue via Email Queue (default)
    now=False,                              # True = send immediately, skip queue
    sender="[email protected]",           # override sender
    cc=["[email protected]"],
    bcc=["[email protected]"],
    reply_to="[email protected]",
    expose_recipients="header",             # show recipients in email header
)

Rules:

  • ALWAYS set reference_doctype and reference_name when the email relates to a document — this links the email in the document timeline.
  • NEVER set now=True in production — it blocks the request. Use delayed=True (default) to queue via Email Queue.
  • ALWAYS ensure an Email Account with "Enable Outgoing" is configured before calling frappe.sendmail.

Email Queue

Emails are queued in the Email Queue DocType and sent by the scheduler. Check queue status:

# Check pending emails
pending = frappe.get_all("Email Queue", filters={"status": "Not Sent"}, limit=10)

frappe.publish_realtime(): System Notifications

frappe.publish_realtime(
    event="msgprint",                      # event name
    message={"msg": "Task completed!"},    # dict payload
    user="[email protected]",               # target specific user
    doctype="Sales Invoice",               # broadcast to doctype room
    docname="SINV-00001",                  # broadcast to document room
    after_commit=True,                     # emit after transaction commits
)

Room Types

RoomAudience
user:{email}Single user (set user=)
doctype:{dt}All users viewing that list
doc:{dt}/{dn}All users viewing that document
allAll Desk users site-wide
task_progress:{id}Background task progress

Built-in Events

EventPurpose
msgprintShow message dialog to user
list_updateRefresh document list view
docinfo_updateRefresh document info sidebar
progressShow progress bar

ALWAYS set after_commit=True when publishing from within a database transaction — otherwise the event fires before data is committed and the client may read stale data.


Assignment Rules

Auto-assign documents to users based on conditions (no code).

Configuration Fields

FieldPurpose
Document TypeWhich DocType triggers the rule
Assign ConditionPython expression (same as Notification)
Assignment DaysLimit to specific weekdays
UsersList of users to assign to
Assignment RuleRound Robin, Load Balancing, or Based on Field

Programmatic Assignment

from frappe.desk.form.assign_to import add, remove, close, clear

# Assign
add({
    "assign_to": ["[email protected]"],
    "doctype": "Task",
    "name": "TASK-00001",
    "description": "Please review this task",
    "priority": "High",
    "date": "2025-12-31",
})

# Remove assignment (cancels ToDo)
remove("Task", "TASK-00001", "[email protected]")

# Close assignment (only assignee can close)
close("Task", "TASK-00001", "[email protected]")

# Clear all assignments
clear("Task", "TASK-00001")

NEVER call close() as a different user than the assignee — it raises a permission error.


Auto Repeat

Creates recurring copies of documents on a schedule.

FieldPurpose
Reference DocTypeWhich DocType to repeat
Reference DocumentSource document to copy
FrequencyDaily, Weekly, Monthly, Quarterly, Half-yearly, Yearly
Start Date / End DateSchedule window
Notify By EmailSend notification on creation

ALWAYS set an End Date on Auto Repeat — open-ended schedules create documents indefinitely and are difficult to debug.


ToDo API

# Create ToDo directly
todo = frappe.get_doc({
    "doctype": "ToDo",
    "allocated_to": "[email protected]",
    "assigned_by": frappe.session.user,
    "description": "Review the quarterly report",
    "priority": "Medium",
    "date": "2025-12-31",
    "status": "Open",
    "reference_type": "Task",
    "reference_name": "TASK-00001",
}).insert(ignore_permissions=True)

ToDo statuses: Open, Closed, Cancelled.


Comments and Tags

# Add comment (appears in document timeline)
doc.add_comment("Comment", text="Reviewed and approved")
doc.add_comment("Edit", "Values changed")

# Add/get tags
doc.add_tag("urgent")
tags = doc.get_tags()  # returns list of tag strings

Version Differences

Featurev14v15v16
Notification DocTypeAll 4 channelsAll 4 channelsAll 4 channels
Minutes Before/AfterNot availableAvailableAvailable
frappe.publish_realtimeAvailableAvailableAvailable
Assignment RulesAvailableAvailableAvailable

See Also

What ships with it: 5 files

28.6 KB alongside SKILL.md

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.