Sign inSign up

cygnusnetworks/tiqora

By cygnusnetworks

•Updated 3 days ago

Self-hosted ticket/helpdesk system, database-compatible with OTRS 6.0.x / Znuny 6.0–7.3

Image
0

1.2K

cygnusnetworks/tiqora repository overview

⁠Tiqora

License: AGPL-3.0 Python 3.12+ React + TypeScript Znuny/OTRS 6.0–7.3 DB Docker Live site Backend coverage Frontend coverage

Tiqora is a modern, self-hosted ticket / helpdesk system that is database-compatible with OTRS 6.0.x and Znuny 6.0–7.3 (MariaDB/MySQL and PostgreSQL). It is a clean-room reimplementation (Python FastAPI + React), not a fork of Znuny — no Znuny source code is included or redistributed.

BackendPython 3.12+, FastAPI, SQLAlchemy 2 async, Alembic, Pydantic v2
FrontendReact + TypeScript + Vite, Tailwind, theming via CSS variables
SearchMeilisearch (full-text; hybrid / vector RAG planned later)
JobsPlain asyncio worker loops (tiqora-worker, tiqora-ai-worker), Redis for sessions/pub-sub
AI surfaceMCP server (FastMCP) under the same permission engine as UI/REST
LicenseAGPL-3.0⁠ — Copyright © 2026 Cygnus Networks GmbH

⁠Try it

In the browser, nothing to install: the interactive demo⁠ runs the full agent, admin and portal UI against mock data.

On your machine, one command (Docker with Compose v2):

curl -fsSLO https://raw.githubusercontent.com/CygnusNetworks/tiqora/main/docker-compose.quickstart.yml
docker compose -f docker-compose.quickstart.yml up -d

Open http://localhost:8000/⁠ and sign in as root@localhost / tiqora-demo. The first start creates the database and seeds 40 fake tickets; docker compose -f docker-compose.quickstart.yml down -v removes everything again. The quickstart is for evaluation only (fixed passwords, plain HTTP). For a real installation see Getting started⁠.

Running OTRS or Znuny already? Tiqora can work on your existing database, next to Znuny — read Moving off OTRS/Znuny without a big-bang migration⁠ or the comparison with Znuny, OTRS, Zammad and others⁠.

Questions, ideas, war stories from your OTRS migration: GitHub Discussions⁠.

⁠Why Tiqora

  • Modern web UI — agent workspace, admin console, and customer portal that feel like a current product, not a 2000s helpdesk skin.
  • Znuny / OTRS 6.0–7.3 database compatibility — same core ticket tables; a runtime schema profile detects the peer (see docs/support-matrix.md⁠). Parallel operation on one shared database is a first-class path (additive tiqora_* tables only until you explicitly take schema ownership). Preferred peers: Znuny 6.5 (LTS) or 7.3.
  • AI-ready ticket search — Meilisearch indexing plus an MCP server so AI agents act with the same ACLs as humans.
  • AI agent assistance — per-queue policies drive draft replies, state-only ticket summaries (document- and attachment-aware), AI triage (queue routing for new tickets), text refine with a word-level diff to review (and a call-note mode for phone notes), and an optional autonomous auto-reply worker. Attachments get text extraction plus a vision pre-pass for images; sensitive data is PII-masked (spaCy NER) before any LLM call; every request lands in an audit log with per-subject ACLs, token/request limits and per-provider cost budgets (day/week/month). Every AI-written article is marked 🤖 in the ticket and carries the tool trace behind it — each call with the arguments it was made with. The agent can hand off to a human, which really stops the auto-reply until someone takes over, and agents can pause all automatic AI actions per ticket. Bring your own OpenAI-compatible endpoints: a model catalog with fallback profiles and per-task routing (research, answer, triage, summary, refine, vision — globally or per queue). Gated by the operation mode so nothing autonomous runs during parallel operation (except auto-replies on Tiqora-only channels such as Telegram).
  • PGP and S/MIME — Znuny-compatible key stores shared with a running Znuny; inbound mail verified and decrypted (security badge per article), outbound replies, forwards, new email tickets and event notifications signed and/or encrypted, with per-queue defaults (sign by default; encryption off / when possible / required), customer keys, and settings editable in the admin UI (Znuny's SysConfig still wins where it is set).
  • Telegram chat & phone/CTI — a messenger-style chat composer for Telegram tickets (attachments, quote replies, answer buttons that resolve the ticket, edit/retract, chat snippets), and Znuny phone parity with an incoming-call popup fed by a PBX webhook, caller lookup, click-to-call and a compact phone ticket form.
  • GDPR tooling — anonymization, retention jobs, and audit trails in admin.
  • Modern design — light, dark and system themes, compact cobalt design system.
  • 49 UI languages — full Znuny language catalogue (48 Znuny .po codes + English source), RTL included; agent preference syncs with Znuny UserLanguage (see docs/i18n.md⁠).
  • No Perl application stack — Python FastAPI + React throughout Tiqora itself (optional small Znuny OPM addon only if you co-run Znuny for cache coherence).
  • Customer portal & knowledge base — self-service tickets (opt-in via TIQORA_PORTAL_ENABLED) and Markdown KB.
  • Integration-friendly — REST /api/v1, GenericInterface REST/SOAP compatibility, webhooks, channel plugins (email, SMS, WhatsApp, Telegram, phone/CTI).
  • Modern auth — legacy password hashes, OIDC, LDAP/AD, Kerberos/SPNEGO (with seamless re-auth when a session expires), enforceable TOTP, and passkeys.

⁠Live product site & demo

Product site⁠ — overview, features, screenshots.

Interactive demo⁠ — full agent, admin, and portal UI in the browser against mock data (nothing is saved). Built from frontend/ with Mock Service Worker⁠; local build:

VITE_BASE=/tiqora/demo/ pnpm --filter tiqora-frontend build:demo

⁠Screenshots

Inbox with channel filters and an incoming-call popup Inbox sorted by last activity, with e-mail / Telegram / phone filters — and a CTI popup for the call that is ringing through.

Grouped by topic; click a section to expand it, click a picture for full size. The product site⁠ shows the same set as a gallery with a light/dark switch.

AI assistance — summaries, drafts with MCP tools, auto-replies, refine, model routing (12)
Ticket summaryDraft grounded in MCP toolsAuto-reply with its tool trace
AI summaryAI assist + MCPAI origin trace
Refine, reviewed as a diffModel catalogTask → profile routing
Refine diffAI modelsAI routing
Per-queue policiesAI settingsProviders
Queue AI policiesAI settingsLLM providers
Cost budget & tool roundsMCP tool sourcesLLM request audit
Provider budgetMCP clientsAI audit
Agent workspace — inbox, ticket view, dashboard, search, reports, calendar, KB (7)
InboxTicket viewDashboard
Queue viewTicket zoomAgent dashboard
SearchReporting & SLACalendar
SearchReportingCalendar
Knowledge base
Knowledge base
Chat & phone — Telegram chat, CTI call popup, compact phone ticket (3)
Telegram chatCTI call popupPhone ticket with caller lookup
Telegram chatCTI popupPhone ticket
PGP & S/MIME — verified mail, signed & encrypted replies, queue defaults, key admin (5)
Verified signature on arrivalSign & encrypt in the composerPer-queue security defaults
Security badgeSecurity controlQueue security
PGP keysS/MIME certificates
PGP keysS/MIME certificates
Administration — queues & escalation, agents, groups, customers, fields, GDPR, 2FA (10)
QueuesEscalation matrixAgents
Admin queuesEscalation matrixAdmin users
GroupsRoles ↔ groupsCustomer users
Admin groupsAdmin role groupsAdmin customer users
Customer user groupsDynamic fieldsPrivacy / GDPR
Admin customer user groupsAdmin dynamic fieldsGDPR
Two-factor
2FA administration
Sign-in & portal — login, account security, account menu, customer portal (4)
LoginAccount securityAccount menuCustomer portal
LoginSecurityUser menuCustomer portal

Generated with SCREENSHOTS=1 pnpm exec playwright test screenshots (e2e/fixtures/rich-mock.ts) — no backend required. Use THEME=dark / LANG_UI=de for variants.

⁠Also included

AreaNotes
Ticket write path + Znuny invariantsGolden-master multi-peer matrix (OTRS/Znuny 6.0–7.3)
GenericInterface compatibilitySession*, TicketCreate/Update/Get/Search/HistoryGet, TimeAccountingGet, OutOfOffice; REST + SOAP
MCP toolsticket_*, customer lookup, KB — see docs/ai-integration.md⁠
AI assistance subsystemDraft replies, summaries, triage, refine (diff review, call notes), auto-reply worker, human handoff, per-ticket pause, 🤖 origin traces, attachment/vision, PII masking, model catalog/profiles/task routing, per-subject ACL, cost budgets & audit — /admin/ai/*, docs/ai-integration.md⁠
Daemon takeover (mail, escalation, notify, GA)Per-function flags, off by default
Calendar / appointmentsMonth/week/agenda UI; reuses Znuny calendar* tables
Process management (BPM)Reuses Znuny pm_* tables — docs/process-management.md⁠
PGP / S-MIMEOff by default (Znuny's PGP / SMIME switches). Shared Znuny key stores, admin pages with overview/keys/settings, inbound verify/decrypt, outbound sign/encrypt with per-queue defaults and per-sender sign keys, signed/encrypted notifications, customer keys, public S/MIME roots trusted out of the box — docs/crypto.md⁠
Telegram, SMS, WhatsApp, phone/CTITelegram chat composer; phone tickets, call logging and CTI incoming-call popup — docs/channels.md⁠
New-ticket helpersQueue suggested from the customer's history, property bar, compact phone ticket with call strip
Integrations endpointPer-customer ticket history for external tools (/api/v1/integrations/customer-tickets)
SSE realtime + agent presenceLive updates on ticket zoom
CSV ticket exportPermission-filtered streaming export
TiqoraSync Znuny addonOptional OPM for cache coherence during parallel op

⁠Architecture overview

                    ┌──────────────────────────────────────────┐
                    │              Clients                      │
                    │  Agent UI · Portal · Admin · AI agents    │
                    └───────────┬──────────────┬────────────────┘
                                │              │
                     /api/v1    │              │  MCP (streamable HTTP)
              /znuny-compat/*   │              │
                                ▼              ▼
                    ┌────────────────┐  ┌─────────────┐
                    │  tiqora-api    │  │ tiqora-mcp  │
                    │  (FastAPI)     │  │ (FastMCP)   │
                    └───────┬────────┘  └──────┬──────┘
                            │                  │
                            │   domain/*       │
                            │   permissions/*  │
                            ▼                  ▼
              ┌─────────────────────────────────────────────┐
              │              Shared domain layer             │
              │  TicketService · ACL · sessions · outbox     │
              └───────────┬───────────────────┬─────────────┘
                          │                   │
           ┌──────────────▼──────┐   ┌────────▼────────┐
           │  OTRS/Znuny tables  │   │  tiqora_* tables│
           │  (6.0–7.3; R/W, no  │   │  (Alembic chain │
           │   schema changes)   │   │   versions_tiqora)│
           └──────────┬──────────┘   └────────┬────────┘
                      │                       │
         ┌────────────▼──────────┐            │
         │  Peer instance        │            │
         │  (optional parallel)  │◄── cache invalidation via TiqoraSync OPM
         └───────────────────────┘
                      │
         ┌────────────▼────────────────────────────────────┐
         │  tiqora-worker · ai-worker · Redis · Meili      │
         └─────────────────────────────────────────────────┘
flowchart TB
  subgraph clients [Clients]
    AgentUI[Agent UI]
    Portal[Customer Portal]
    Admin[Admin]
    AI[AI Agents via MCP]
  end

  subgraph tiqora [Tiqora]
    API[tiqora-api FastAPI]
    MCP[tiqora-mcp FastMCP]
    Worker[tiqora-worker + ai-worker]
    Domain[domain + permissions]
  end

  subgraph data [Shared data plane]
    ZTables[(Znuny tables)]
    TTables[(tiqora_* tables)]
    Redis[(Redis)]
    Meili[(Meilisearch)]
  end

  Znuny[OTRS/Znuny 6.0–7.3 peer]

  AgentUI --> API
  Portal --> API
  Admin --> API
  AI --> MCP
  API --> Domain
  MCP --> Domain
  Domain --> ZTables
  Domain --> TTables
  Worker --> ZTables
  Worker --> TTables
  Worker --> Redis
  Worker --> Meili
  Znuny --> ZTables
  Domain -.->|tiqora_cache_invalidation| Znuny

Package layout (backend):

backend/src/tiqora/
  db/legacy/        # Hand-written models for Znuny tables + conformance tests
  db/tiqora/        # tiqora_* models (Alembic: versions_tiqora / versions_owned)
  znuny/            # Invariants: ticket numbers, history, escalation, follow-up, …
  domain/           # Services — sole write paths, bundling invariants
  permissions/      # Groups/roles + ACL for UI, REST, MCP
  events/           # Async bus + transactional outbox
  channels/         # Channel plugins (email, SMS, WhatsApp, Telegram, phone)
  storage/          # StorageBackend interface (DB MIME in V1)
  api/              # v1 routers + GenericInterface compat layer
  mcp_server/       # FastMCP process
  worker/           # asyncio worker loops (daemon takeover, outbox, pollers)
  kb/               # Knowledge base

⁠Parallel operation with Znuny

Tiqora and Znuny can share one PostgreSQL or MariaDB/MySQL database:

RuleDetail
No Znuny schema changesTiqora never alters Znuny tables until post-cutover ownership mode
New tables only as tiqora_*Alembic chain versions_tiqora/
Behavioural parityTicket numbers, history formats, escalation columns, search flags must match Znuny
Daemon ownershipZnuny keeps mail/escalation/notifications/GenericAgent until feature flags hand each over
Cache coherenceOptional TiqoraSync Znuny OPM reads tiqora_cache_invalidation; or lower Znuny cache TTLs

See docs/parallel-operation.md⁠ for the full invariant list.

⁠Getting started — three ways to run

PathWhenDoc
QuickstartEvaluate locally in two minutes, demo data includeddocker-compose.quickstart.yml⁠ — see Try it⁠
Fresh standaloneEmpty database, no Znuny — greenfield install via tiqora bootstrapdocs/guide/fresh-install.md⁠
Parallel to ZnunyCo-run with an existing OTRS/Znuny 6.0–7.3 database (additive tiqora_* only)docs/support-matrix.md⁠, docs/parallel-operation.md⁠, docs/guide/znuny-to-tiqora.md⁠
Migrate awayAfter parallel operation: schema ownership, cutover checklistdocs/cutover.md⁠

⁠Quick start (development)

⁠Prerequisites
⁠1. Start infrastructure
docker compose -f docker-compose.dev.yml up -d
# MariaDB :3306, Postgres :5432, Redis :6379, Meilisearch :7700, Mailpit :8025/:1025
⁠2. Backend
cd backend
uv sync
export DATABASE_URL=postgresql+asyncpg://tiqora:tiqora@localhost:5432/tiqora
# or: mysql+aiomysql://tiqora:tiqora@localhost:3306/tiqora
export REDIS_URL=redis://localhost:6379/0
export MEILI_URL=http://localhost:7700
uv run uvicorn tiqora.api.app:create_app --factory --reload --host 0.0.0.0 --port 8000

Health checks:

curl -s http://localhost:8000/health
curl -s http://localhost:8000/ready
curl -s http://localhost:8000/metrics | head
⁠3. Frontend
cd frontend
pnpm install
pnpm dev
# http://localhost:5173  — agent, portal, and admin UI
⁠Makefile / just shortcuts

Tag summary

Content type

Image

Digest

sha256:531944b25…

Size

234.1 MB

Last updated

3 days ago

docker pull cygnusnetworks/tiqora