~/chandan-satwani/projects/pulsedesk-os $
// case study

PulseDesk OS

An auditable support console where code owns the workflow and the model owns the judgments.

role
Solo build
status
v1 released
license
MIT, open source
judgments
TypeSafe Jev
stack
Python 3.11, FastAPI, React and Vite, SQLite, FastMCP, Docker

The problem

Most agent systems let a language model decide what happens next, and hope an open-ended prompt won't loop, make something up, or leak a customer's data.

For support tickets that's the wrong trade. Every decision has to be explainable to the person who gets the reply, and to the operator who has to trust it.

The idea

Invert it. State machines, routing gates and handlers are ordinary, testable Python. The model is only asked narrow questions: which route, how urgent, is this spam, does it contain personal data, is this memory relevant, is this reply supported.

Every answer comes back typed, with a confidence score, so each step can be gated, logged and audited.

How a ticket moves through the line

thresholds from config.yaml
  1. station 1TriageNine structured judgments per ticket, including route, spam risk, urgency and personal-data checks.
  2. station 2Policy gatesSpam risk of 0.60 or more is quarantined. Routing confidence under 0.75 goes to a person.
  3. station 3RecallBM25 search over tenant memory, then a rerank that drops anything scoring over 0.30 for prompt injection.
  4. station 4Dispatch and draftA handler registry picks the right handler. Adding a category means registering one function.
  5. station 5VerifyThe draft is checked against recalled evidence. Verified replies ship; the rest wait for review.

A Monday-morning storm

Five realistic tickets from the demo script, and where the pipeline sent each one.

python sandbox/run_demo.py
ticketjudgmentoutcome
Critical outage, API returning 500sbug_report, high urgencyAuto-routed
Duplicate chargebilling, high confidenceAuto-routed
VPN provisioning requestit_access, credential check safeAuto-routed
Phishing bonus offer asking for credentialshigh spam riskQuarantined
Vague, ambiguous reportlow routing confidenceHuman review

Built to be trusted

59tests, plus ruff, strict mypy, a secret scan and end-to-end smoke tests on every change.
Offline firstRuns with deterministic heuristics and no API key, so anyone can try the full pipeline locally.
Tenant-scopedEvery memory read and delete is scoped by tenant. A delete without matching ownership fails safely.
Plugs inShips as a Claude Code plugin with three slash commands and a FastMCP server with five tools.

What I learned

The biggest lesson was that reliable agent systems need a hard boundary between workflow control and model judgment. Keeping routing, policy gates and handlers in ordinary typed code made the system easier to test, inspect and change than an open-ended prompt would have been. I also learned that tenant ownership and evidence checks have to be enforced by the pipeline, not left to the model.

Next: Add more real support-system integrations and give operators a clearer view of each judgment, policy gate and evidence trail.

Links