Communication (Chatter)¶
Embed a per-record message thread, activity timeline, follower list, and attachments on any record with a single mixin and one DSL block. Users post updates, schedule follow-ups, mention each other, and see the audit history right next to the record.
from ede.core import api, fields
from ede.core.kernel.model import DomainModel
from ede.foundation.communication.models.chatterable import Chatterable
@api.model("blog.post")
class Post(DomainModel, Chatterable):
title = fields.Char(required=True)
body = fields.Text()
Inheriting Chatterable is the entire backend integration. Add an <activity> block to the form view and the React web client renders the chatter panel automatically:
<FormView model="blog.post">
<sheet>
<field name="title"/>
<field name="body"/>
</sheet>
<activity>
<MessageConversation/>
<Followers/>
<ScheduledActivity/>
<Attachments/>
</activity>
</FormView>
What you get¶
Chatterablemixin — opt-in on anyDomainModel. Adds message, follower, and activity relations.communication.message— one immutable message entry on a record's thread.communication.follower— subscription rows for users who want updates on a record.activity.log— a scheduled or completed activity (task, call, review) on a record.activity.type— admin-managed catalog of activity kinds and default delays.CommunicationService— six routed methods:post_message,post_note,post_notification,schedule_activity,complete_activity,subscribe.<activity>DSL block — render any combination of<MessageConversation/>,<Followers/>,<ScheduledActivity/>,<Attachments/>inside a FormView.- HTTP API — 11 endpoints under
/api/chatter/{model}/{id}/...for thread reads, post / note / email, activities, and followers. All RBAC-gated. - Auto-follow on ownership change — toggle
COMMUNICATION_AUTO_FOLLOW_OWNERto make assignment automatically subscribe the owner. - Mention parser —
@usernamein a message body resolves to ares.user, fires the notifications bridge, and links the user as a follower. - Email bridge — incoming and outgoing email is normalised into the same
communication.messagestream.
How to use it¶
Make a model chatter-enabled¶
from ede.foundation.communication.models.chatterable import Chatterable
@api.model("blog.post")
class Post(DomainModel, Chatterable):
title = fields.Char(required=True)
body = fields.Text()
Generate and apply a migration — the mixin pulls in the relations the chatter needs.
Post a message¶
from ede.foundation.communication.services.communication_service import (
CommunicationService,
)
svc = CommunicationService.from_env(env)
svc.post_message(
related_model="blog.post",
related_id=post.record_uuid,
body="Reviewed and ready to publish.",
author_id=current_user.record_uuid,
)
Use post_note for an internal-only note (filtered out of email bridges) and post_notification for a system-generated event message (typically posted by a workflow or hook, not by a user).
Schedule an activity¶
svc.schedule_activity(
related_model="blog.post",
related_id=post.record_uuid,
activity_type_id=env.ref("communication.activity_type_review").record_uuid,
due_date=date.today() + timedelta(days=2),
assignee_id=editor.record_uuid,
note="Final copy pass before publish.",
)
activity.type rows are seeded by data/activity_type_seed.xml; reference them by external ID with env.ref().
Complete an activity¶
svc.complete_activity(
activity_id=activity.record_uuid,
summary="Approved",
)
# → posts an automated message to the thread; closes the activity row
Subscribe a user as a follower¶
svc.subscribe(
related_model="blog.post",
related_id=post.record_uuid,
user_id=reviewer.record_uuid,
)
If COMMUNICATION_AUTO_FOLLOW_OWNER=True, ownership changes call subscribe automatically.
Read the thread over HTTP¶
Returns messages, open activities, and the follower list in one payload. The 11-endpoint surface covers reads, writes, edits, and deletes for messages, notes, email, activities, and followers — see src/ede/foundation/communication/api/chatter_controller.py for the full route list.
The four <activity> components¶
<activity> accepts exactly these children (in any order; the parser rejects unknown tags at load time):
| Component | What it renders |
|---|---|
<MessageConversation/> |
Threaded message timeline with mention input. |
<Followers/> |
Follower list with add/remove controls. |
<ScheduledActivity/> |
Open and completed activities with deadline indicators. |
<Attachments/> |
Files uploaded to the record (uses Storage). |
Use any subset — a read-only record might only show <MessageConversation/> and <Attachments/>, for example.
Configuration¶
| Setting | Default | What it controls |
|---|---|---|
COMMUNICATION_AUTO_FOLLOW_OWNER |
True |
Subscribe the owner automatically when an ownership field changes. |
COMMUNICATION_MENTION_NOTIFY |
True |
Fire a notification (via the notifications bridge) when a user is @mentioned. |
How it composes with other features¶
- Storage —
<Attachments/>uploads route through the storage engine. - Notifications — mentions and new-message events publish to the notifications bridge.
- Email — the email bridge normalises inbound and outbound mail into
communication.messagerows. - Permissions — the 11 HTTP routes are RBAC-gated; record rules on the parent model decide who can read a thread.
Reference¶
- Mixin:
src/ede/foundation/communication/models/chatterable.py - Models:
src/ede/foundation/communication/models/{message,follower,activity,activity_type}.py - Service:
src/ede/foundation/communication/services/communication_service.py - Bridges & helpers:
src/ede/foundation/communication/services/{notifications_bridge,email_bridge,auto_follow,mention_parser}.py - HTTP controller:
src/ede/foundation/communication/api/chatter_controller.py - DSL parser (
<activity>element):src/ede/core/services/presentation/dsl/parser.py - React components:
src/frontend/src/workspace/views/chatter/ - Activity-type seed:
src/ede/foundation/communication/data/activity_type_seed.xml