Sanctum Tasks

API-first task management with embedded Vernal chat (Ask Q)

Sanctum Tasks is the reference application in the SanctumOS stack - PHP + SQLite on multihost, a complete /api/ surface for humans and agents, an SMCP plugin (tasks__), and the first production implementation of the embedded agent chat modality: floating Ask Q on admin, q-bridge poll loop, Broca on moya, Q Vernal on Letta.

It is also the app we run our own work on (Decision Science Corp production: tasks.decisionsciencecorp.com). The repo is AGPL-3.0 (code) / CC BY-SA 4.0 (docs).

Repository: sanctumos/sanctum-tasks


What it is for

Audience Tasks provides
Operators Bootstrap admin UI - tasks, comments, directory projects/documents, todo lists, skins, API keys
Integrators Stable JSON API (/api/*.php), Python SDK, rate limits, audit logs
Agents (Otto, Q, Ada) SMCP plugin with full API parity; governor profiles (chatter, admin, full)
Platform builders Copy-paste pattern for q-bridge + Broca plugin + per-user API key injection

Tasks is not "a chat app with a task list bolted on." The host app stays authoritative; the agent receives scoped tools and session identity from the logged-in user.


Stack placement

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

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

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

Same shape as Kitchen POS Ask Porter - different ACL (operator vs partner). Tasks is also why SMCP tool governance had to exist: the production pressure here is what forced the attach/detach profiles into the protocol.


Core capabilities

Task & directory model

  • Tasks - status workflow, assignees, priority, due dates, tags, watchers, comments, attachments
  • Directory - organizations, projects, todo lists (list_id required on create), document library with markdown bodies
  • API-first - every operator action has an /api/ counterpart; no scraping of admin HTML

Ask Q (embedded Vernal)

SMCP plugin

Path in repo: smcp_plugin/tasks/cli.py

python3 smcp_plugin/tasks/cli.py --describe
python3 smcp_plugin/tasks/cli.py list-tasks --limit 5

python3 smcp_plugin/tasks/cli.py --describe python3 smcp_plugin/tasks/cli.py list-tasks --limit 5

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

Install runtime (Otto / Cursor): sanctum-tasks/docs/otto-smcp-cursor.md

Tool profiles: SMCP-TASKS-TOOL-PROFILES.md - chatter (~12 verbs for in-app Q), admin, full.

Governor attach/detach: sanctumos/smcp sanctum__tools + SMCP_ATTACH_PROFILE.

Python SDK & FastAPI mirror

Artifact Location
Python SDK tasks_sdk/ in sanctum-tasks
FastAPI clone sanctumos/py-tasks - same SQLite semantics, swap base URL

Quick start (local)

python3 smcp_plugin/tasks/cli.py --describe
python3 smcp_plugin/tasks/cli.py list-tasks --limit 5

git clone https://github.com/sanctumos/sanctum-tasks.git cd sanctum-tasks cp public/includes/secrets.php.example public/includes/secrets.php php -S 127.0.0.1:8080 -t public

Admin: http://127.0.0.1:8080/admin/login.php

API key: db/api_key.txt after first bootstrap (or TASKS_BOOTSTRAP_API_KEY)

Browser (admin UI + Ask Q bubble)
    ↕ session cookie
PHP host (sanctum-tasks) — q-bridge SQLite queue
    ↕ poll bearer
Broca (q_vernal_webchat plugin) on agent host
    ↕ Letta API
Q Vernal (+ SMCP tasks__ tools with injected user key)
    ↕ HTTPS /api/
Tasks REST API (same origin)
python3 smcp_plugin/tasks/cli.py --describe
python3 smcp_plugin/tasks/cli.py list-tasks --limit 5

SMCP (requires sanctumos/smcp clone - see docs/integrations.md)

export TASKS_SMCP_BASE_URL=http://127.0.0.1:8080 python3 smcp_plugin/tasks/cli.py health

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

Wire SMCP into Cursor / Otto

  1. Clone sanctumos/smcp and sanctumos/sanctum-tasks
  2. Run ./tools/install-otto-smcp-runtime.sh from the Tasks repo (documented in docs/integrations.md)
  3. Point Cursor MCP at stdio server; tools appear as tasks__create-task, tasks__list-documents, etc.
  4. Optional: SMCP_ATTACH_PROFILE=chatter for a narrow Q-like surface

Documentation map (repo)

Doc Topic
docs/api.md REST contract
docs/integrations.md API keys, SDK, SMCP
docs/HEARTBEAT.md Agent heartbeat queues via Tasks
docs/MODALITY-EMBEDDED-AGENT-CHAT-IN-SANCTUM-APP.md q-bridge pattern template
docs/SMCP-TOOL-GOVERNANCE-PHASE.md Why 35 tools -> profiles

In-app user guide: /admin/documentation.php (from public/docs/user-guide.md).


Related SanctumOS modules


Production notes

Decision Science Corp runs Tasks on multihost LEMP at tasks.decisionsciencecorp.com. Deploys follow the standard sites/.env + sync.sh pattern. Blog posts on design parity, Ask Q hardening, and SMCP governance all reference this deployment - the product is Sanctum Tasks; the hostname is ours.

When you self-host, you own the SQLite files under db/ and public/uploads/task-assets/ (inline images for tasks/documents, fetched via the upload API).


Sanctum Tasks is the workload + permissions layer that many Sanctum agents actually run against - worth documenting on its own, not only as a footnote in SMCP governance posts.