Back to directory
szTheory avatar

cairnloop

An embedded, Phoenix-native customer support automation layer for Elixir applications.. Read more below about its uses, features, and usage.

Clone repository

git clone https://github.com/szTheory/cairnloop.git

1

Stars

0

Forks

0

Watchers

MIT

License

Cairnloop

Hex.pm Version HexDocs GitHub Actions CI

An embedded, Phoenix-native customer support automation layer for Elixir applications.

What Cairnloop Is For

Cairnloop belongs inside a Phoenix app that already owns customers, operators, authorization, Postgres, Oban, and deployment. Use it when you want support conversations, AI-assisted drafts, knowledge-base maintenance, governed tool proposals, audit history, and outbound follow-up to stay in your app instead of syncing through a separate helpdesk service.

When not to use Cairnloop

  • Cairnloop is not a hosted helpdesk; you run it inside your Phoenix application.
  • Cairnloop is not a replacement for host auth or authorization; protect routes and inject operator identity from your own app.
  • Cairnloop is not autonomous customer-visible support; keep AI replies and governed actions behind your operators and policies.
  • Cairnloop is not a tenant-isolation layer; design tenant boundaries in your own app and database.
  • Cairnloop is not a managed outbound campaign system; outbound follow-up stays host-owned and routed through your configured notifier.

Installation

Try the live demo first

From a fresh clone, the fastest way to see Cairnloop working is the Docker demo:

./bin/demo

The command starts the example Phoenix app, a private pgvector Postgres container, migrations, and the realistic Trailmark seed data. Start with the demo index URL printed by ./bin/demo; it also prints the exact local URLs to click: the demo index, operator cockpit, inbox, customer chat, knowledge base, audit log, settings, and health probe.

The demo publishes only the Phoenix UI on 127.0.0.1 and uses a dynamic port range by default, so it can run alongside other local Dockerized UI demos without fighting over 4000, 5432, or 5433. Use ./bin/demo reset when you want a clean reseeded database, and ./bin/demo smoke to boot an isolated stack and verify the main demo routes end to end.

Install in your app

After you have tried the Docker demo, use this host-app path to install Cairnloop in a Phoenix application. The fastest host-app install uses Igniter's package installer:

mix igniter.install cairnloop

The installer adds {:cairnloop, "~> 0.5.1"} to your mix.exs deps and generates a create_cairnloop_tables migration against your detected Ecto repo.

If Cairnloop is already in mix.exs and your deps are fetched, you can re-run Cairnloop's package task directly with mix cairnloop.install.

After the installer runs, configure Cairnloop with your repo and run both host and dependency migrations:

config :cairnloop, :repo, MyApp.Repo
config :cairnloop, :schema_prefix, "cairnloop"

New installs use the dedicated cairnloop Postgres schema. Existing public-schema installs should pin explicit public compatibility while following UPGRADING.md:

config :cairnloop, :schema_prefix, "public"
mix ecto.migrate
mix ecto.migrate --migrations-path deps/cairnloop/priv/repo/migrations
mix cairnloop.doctor

Inside this repository, examples/cairnloop_example/mix.exs dogfoods local source with {:cairnloop, path: "../.."}. Adopter apps should use the Hex dependency form above.

Manual install (without Igniter)

For manual host-app setup, add Cairnloop to your mix.exs dependencies:

def deps do
  [
    {:cairnloop, "~> 0.5.1"}
  ]
end

Then run mix deps.get and generate the migration manually (see the quickstart guide for the migration contents).

Configure the host repo and schema prefix:

config :cairnloop, :repo, MyApp.Repo
config :cairnloop, :schema_prefix, "cairnloop"

New installs use the dedicated cairnloop Postgres schema so Cairnloop tables do not pollute the host app's public namespace. Existing public-schema installs should pin config :cairnloop, :schema_prefix, "public" while following UPGRADING.md.

Why Cairnloop?

  • Host-owned support truth. Conversations, drafts, governed actions, and outbound follow-ups all live in your Postgres database — no external CRM sync required.
  • Safe automation by default. The AI drafts; your operators approve. Every proposed action passes through a durable approval state machine before execution.
  • KB substrate built in. Hybrid pgvector + full-text retrieval keeps AI answers grounded in your published knowledge base, not hallucinated context.
  • Additive, not invasive. Cairnloop is a library embedded in your existing Phoenix monolith. No separate service, no separate deploy.
  • Observable without lock-in. Bounded :telemetry spans on every meaningful operation. Export to any APM; your app stays in control.

What it does

Cairnloop turns support conversations into answers, product signals, knowledge-base improvements, and safe automated actions — all inside your existing Phoenix app. Incoming messages route through Phoenix Channels to a durable Ecto-backed conversation record. An Oban worker drafts an AI-grounded reply using your published KB and offers it to the operator for approval. Resolved conversations feed back into the KB maintenance queue through a governed review workflow, and support-triggered outbound follow-ups route durably through a configurable Notifier behaviour.

Explore the guides

  • Quickstart — Start with the Docker demo, then use the manual install path when you are ready to wire Cairnloop into a host app.
  • JTBD Walkthrough — A prose walkthrough of every Jobs-To-Be-Done stage in the seeded example: inbox → draft approval → governed tool proposal → resolve → outbound follow-up → bulk recovery.
  • Host Integration — Wire up ContextProvider, Notifier, AutomationPolicy, and SLAPolicyProvider in your app. Includes telemetry patterns and Oban configuration.
  • Troubleshooting — Docker demo failure recovery, dynamic ports, reset/log flows, install errors, migration order, pgvector setup, and Oban worker timing.

Production Notes

Host apps own route authentication and authorization, per-request operator identity, repo config, Oban supervision, secrets, monitoring, and deployment. Cairnloop supplies install scaffolding, bounded telemetry, liveness/metrics plugs, and mix cairnloop.doctor so those host-owned seams are visible before production traffic reaches them.

Contributing

Contributions are welcome. Open an issue or pull request on GitHub. Please follow the existing code style and run mix ci.fast before submitting. Run mix ci before release-sized changes. For focused checks: docs/package changes use mix ci.quality, DB-backed workflow changes use mix ci.integration, and the example browser journey uses cd examples/cairnloop_example && mix test.e2e. Docker demo smoke stays separate from default mix ci; run ./bin/demo smoke for Docker/demo/docs/example adoption changes.

License

MIT. See LICENSE.

Releases

0.5.1 (2026-06-03) Bug Fixes

inject the signed-in operator as host_user_id, not a hardcoded id (dce852a) inject the signed-in operator as host_user_id, not a hardcoded id (72891f5)

0.5.0 (2026-06-03) Features

automation: swappable draft-generator seam + Anthropic adapter (6632b4e) automation: swappable draft-generator seam + Anthropic adapter (ea9bf96)

0.4.0 (2026-06-03) Features

ui: add Cockpit Home + persistent nav shell (IA orientation layer) (fa24f9d) ui: design-system + IA elevation for the operator UI (ebed003) ui: finish Conversation Workspa...

May 30, 2026

Download .zip

0.3.0 (2026-05-30) Features

add mix cairnloop.doctor wiring diagnostic (24e71f9) installer: print router/auditor/doctor next steps after install (bcacf69) mix cairnloop.doctor + validated router opts...

May 30, 2026

Download .zip

0.2.3 (2026-05-30) Bug Fixes

router: cairnloop_dashboard/2 compile break + verify-before-publish hardening (21699d5) router: cairnloop_dashboard/2 failed to compile for adopters (dc0784f)