The Modular, Self-Hosted Agentic Operating System

Sanctum Tasks: the first production app from the Sanctum productivity suite

The Sanctum stack ships infrastructure—SMCP, Broca, Router, web chat bridges—and a productivity suite of API-first business apps. Sanctum Tasks is the first to earn real adoption at Decision Science Corp.

The Sanctum stack ships a lot of infrastructure - SMCP, Broca, Router, web chat bridges. Alongside that, we are building a productivity suite: API-first business apps that share design language, agent hooks, and deployment patterns. Tasks, CRM, invoicing, presale - same shop, different domains.

Sanctum Tasks is the first of those apps to earn major real-world adoption. We run Decision Science Corp on it every day at tasks.decisionsciencecorp.com: boards, documents, client engagements, agent heartbeat queues, Otto proof-of-work comments. Not a demo tenant. Not a reference stub. The app we polished until we trusted it with our own operations.

This post is the product story - what Tasks is, why it shipped first, and what the rest of the suite inherits from it.


Productivity suite, not platform cosplay

A productivity suite app has three obligations:

  1. Humans can run the business in it - assign work, file docs, comment, attach screenshots, ship.
  2. Agents can drive the same surface - /api/ parity, SMCP tools, scoped keys, audit trail.
  3. It feels like one family - shared Sanctum shell, status semantics, filter bars, not a one-off theme per repo.

CRM is catching up on visual parity (DSC - same shop as Tasks). Kitchen POS picked up the shell for operators and partners (DSC - operator UI journal). Tasks was the template - the app where we proved the modality before we spread it.

Suite member Role today
Sanctum Tasks Production - daily ops, agent queue, document library
Sanctum CRM Reference + design alignment - MCP-native contact model
Invoicing / presale Sibling properties - same multihost + API-first discipline

Tasks is not "infrastructure with a task list." It is the first shipped product in that row.


What we polished (and why it had to be Tasks first)

You cannot fake adoption. Tasks had to survive:

All-day Ask Q on admin. Embedded Vernal chat on every page - q-bridge beside tasks.db, Broca poll loop, per-user API key injection, SMCP chatter profile so Q sees ~12 verbs instead of the full admin catalog. That pattern forced SMCP tool governance into existence. Production hardening - rate limits, 429 backoff, session keys - is documented on the DSC builder journal.

API-first discipline. Every operator action has an /api/.php counterpart. Otto, Ada, and Q never scrape admin HTML. The tasks__ SMCP plugin mirrors the Python SDK; governor profiles trim the catalog for conversational vs admin lanes.

Directory model that scales. Organizations, projects, todo lists (list_id on create), markdown document library, attachments via upload API -> get-asset - the shape we use for client engagements, internal runbooks, and agent filing.

Agent heartbeat. Tasks is the queue surface for open-claw style workers: check board, pick up assigned work, log proof in comments, mark done. See HEARTBEAT.md and smcp-cursor-cli for headless Cursor runs tied to task rows.

Design language. Skins, Sanctum tokens, status pills - the chrome CRM and Kitchen POS later echoed. Tasks was where we learned what "same shop" meant in CSS, not slide decks.

That polish is why Porter on Kitchen POS could copy bridge semantics without reinventing policy (Porter mechanism post). The modality template lives in the Tasks repo: MODALITY-EMBEDDED-AGENT-CHAT-IN-SANCTUM-APP.md.


Stack map (how the pieces connect)

Browser (admin + Ask Q bubble)
    ↕ session cookie
PHP host (sanctum-tasks) — q-bridge SQLite queue
    ↕ poll bearer
Broca (q_vernal_webchat) on agent host
    ↕ Letta API
Q Vernal (+ SMCP tasks__ with injected user key)
    ↕ HTTPS /api/
Tasks REST API (same origin)

Browser (admin + Ask Q bubble) ↕ session cookie PHP host (sanctum-tasks) — q-bridge SQLite queue ↕ poll bearer Broca (q_vernal_webchat) on agent host ↕ Letta API Q Vernal (+ SMCP tasks__ with injected user key) ↕ HTTPS /api/ Tasks REST API (same origin)

Browser (admin + Ask Q bubble)
    ↕ session cookie
PHP host (sanctum-tasks) — q-bridge SQLite queue
    ↕ poll bearer
Broca (q_vernal_webchat) on agent host
    ↕ Letta API
Q Vernal (+ SMCP tasks__ with injected user key)
    ↕ HTTPS /api/
Tasks REST API (same origin)

In-app: logged-in users get Ask Q; messages never leave the PHP origin for Letta. Out-of-band: Otto and Ada call the same API with X-API-Key or Bearer - same rows, same ACL rules.


Documentation on sanctumos.org

We added a module page so Tasks sits beside Broca and SMCP in our own catalog:

Sanctum Tasks - module documentation

Also linked from the modules index, SMCP plugins (tasks__), and ecosystem reference applications.


If you are building the next suite app

Steal the order Tasks validated:

  1. /api/ first - agents will not drive your admin HTML.
  2. q-bridge + Broca plugin - browser talks only to your PHP origin.
  3. SMCP plugin - one verb per API action; ship chatter before attaching the full catalog to a conversational agent.
  4. Per-user key injection - the model never sees raw credentials.
  5. Shared shell tokens - lift from Tasks/CRM, do not invent a fourth design system.

CRM, invoicing, presale - same modality, different tool slice. Tasks is the production proof.


Licensing and repos

Item License / URL
sanctum-tasks (PHP, SMCP plugin, SDK) AGPL-3.0 · GitHub
py-tasks (FastAPI mirror) sanctumos/py-tasks
smcp sanctumos/smcp
broca (q_vernal_webchat) sanctumos/broca

Repo docs: CC BY-SA 4.0. Otto / Cursor install: otto-smcp-cursor.md.


Related reading

Questions and PRs: contributing · sanctum-tasks issues.