@happyvertical/smrt-messages
A unified STI hierarchy for email, social, and other communication channels, plus in-app notifications.
What it gives you
A unified STI hierarchy for email, social, and other communication channels, plus in-app notifications.
This package is one focused part of the s-m-r-t stack. Its decorated models participate in the same manifest, tenancy, persistence, and generated-interface conventions as the rest of the framework.
Channels and accounts are polymorphic
Message has Email, Tweet, and SlackMessage subtypes; Account has Email, Twitter, Slack, Zulip, and Telegram subtypes. Import a provider from smrt-messages/providers/email, slack, twitter, or all when needed. The root import remains free of provider SDK weight, and credentialSecretId points to write-only smrt-secrets storage.
Persona routes are wired by a trusted caller
MessagingEndpoint, PersonaMessageRoute, and PersonaMessagingService operate behind messages.send and messages.manage-routes. createPersonaMessagingTool fixes personaId in trusted wiring so an agent-provided argument cannot choose a different persona. EmailAccount.readIntakeMessage is the authorized seam for opt-in ingestion of full message bytes; it never advances sync checkpoints.
In-app notifications are a closed service
UserNotification stores one row per recipient with kind, title, body, link, severity, a source reference, and read and dismissed state. UserNotificationService is the only access path: notify and notifyMany deduplicate on the source reference, and listForUser, countUnread, markRead, dismiss, and markAllRead filter on the recipient. Generated REST, MCP, and CLI are off, because a tenant-scoped list would expose every member. Hosts expose their own routes with the signed-in user id.
Package UI
Components in this package
Import these public components directly. When the package also exports playground entries, the next tab renders its real components with package-owned example data.
Package previews
Try the working views
These previews are owned by the package and use its public components. Mock mode is intended for safe browsing; live mode appears only where the package supports it.
Generated interface
REST
The exact route set comes from each model's @smrt({ api }) policy
and the application manifest—not from a second controller definition.
GET /api/messages
GET /api/messages/:id
POST /api/messages
PATCH /api/messages/:idWhat stays consistent
- Tenant scope and operation permissions run before model access.
- OpenAPI and generated clients use the same manifest fields.
- Packages can expose read-only or custom action sets.
Generated interface
MCP
AI tools are generated from the methods you explicitly include. Their inputs are validated against the same model metadata used by REST and CLI.
messages_list({ where, limit, orderBy })
messages_get({ id })
messages_create({ data })
messages_update({ id, data })Agent-safe by construction
- Tool availability can be narrower than the HTTP API.
- Principal execution intersects RBAC, agent ceilings, and persona tools.
- Descriptions and schemas are emitted from source metadata.
Browser-native agent interface
WebMCP
The generated web definitions carry the same tool names, descriptions, and JSON Schema
inputs as MCP. smrt-web registers them with document.modelContext.
import { webMcpToolDefinitions } from '@happyvertical/smrt-virt-web';
import { registerWebMcpTools } from '@happyvertical/smrt-web';
// Omitting an exposure policy registers read-only tools only.
const dispose = registerWebMcpTools(webMcpToolDefinitions);The page keeps its security boundary
- Tools execute through generated REST fetchers as the signed-in page user.
- Authentication, tenant gates, permissions, and field policy stay server-side.
- Feature detection makes registration a safe no-op outside supported browsers.
Generated interface
CLI
The app CLI turns manifest resources into predictable operator commands while keeping package-specific actions close to their models.
smrt messages list --limit 25 --order-by created_at:desc
smrt messages get <id>
smrt messages create --from-file ./record.jsonMade for automation
- Machine-readable output and file-based input.
- The same include/exclude policy as other surfaces.
- Migration, introspection, dispatch, and knowledge commands stay in smrt-cli.