How it fits together

One foundation, one front door, many domains

Every skill reads through security_invoker views and writes through security definer RPCs that check em_private.accessible_write before touching a row - it never writes a base table directly. Meaningful account-level changes append to the account changelog for an audit trail.

Entry

How the EM invokes the toolkit

qira - natural language ("hey qira, …") Direct skill triggers ("write feedback email") /em-setup, /qira commands Daily routines (em-platform-morning-run · em-platform-closer)
Domains

Domain plugins - the EM-facing capabilities

People management Account intelligence OKR management Risk management Planning Reporting BigMac sprint audit
Foundation

em-core - shared workers every domain calls

em-task-manager (task write gatekeeper) em-identity-resolver (who is this?) account-changelog (audit trail) em_db seam (the em.* read/write contract) em.em_settings_current (per-EM settings)
Data layer

The platform database (and the connectors around it)

Supabase/Postgres - the em schema (~80 tables + views) Reads via security_invoker views · writes via security definer RPCs Fireflies (transcripts) · Microsoft 365 (calendar, email, Teams) Tability (OKR system of record, mirrored in-platform)
Under the hood

How a skill actually runs - and why you can trust it

The stack above is what the toolkit is. This is what happens when you use it - the mental model behind every skill, so you know what runs on your data and why the writes are safe.

The layer cake

Nothing magic runs - it's layers of text and tool calls

When a skill "runs," there is no special runtime. From bottom to top, only one layer is unpredictable:

The model (Opus 4.8)Reads text, predicts the next words, samples one. Stochastic by design - the same prompt can be worded differently each time.Not deterministic
The harnessClaude Code. Runs the loop: assemble context, get the model's output, execute its tool calls, feed the results back.Deterministic
ToolsFunctions the model can call - read a file, run a script, call an em.* RPC through the em_db seam. Real code with real return values.Deterministic
SkillsMarkdown instruction files the harness injects when they're relevant. The text is fixed; how the model uses it varies.Mixed
PluginsA folder bundling skills + agents + commands + hooks + a manifest. Just packaging.Deterministic
HooksShell commands the harness fires on events (session start, before a tool runs). The harness runs them, not the model.Deterministic
The whole design in one line: the model is the only unpredictable part, and every decision that has to be reliable is deliberately pushed out of the model and into the deterministic layers around it.
What a skill is

A markdown file with a trigger and a body

Strip away the mystique - a skill is a text file with frontmatter. That's it:

---
name: em-1on1-logger
description: Use when the user says "log my 1:1"...  # this is the TRIGGER
---
<the instructions the model follows once this skill is active>
1

Progressive disclosure - why a big toolkit doesn't slow you down

At the start of a session the model does not load the body of every skill - only each skill's name + description, a lightweight index. The moment your message matches a description, the harness injects that one skill's full instructions. You carry the whole toolkit without filling up the context window.

2

The description is the router

That description field - "use when the user says X, Y, Z" - is the trigger logic that decides which skill fires. Getting it right is real engineering: skill-creator has eval and benchmark tooling to measure trigger accuracy, so the right skill firing is tested, not luck.

A useful way to think about it: a skill is a unit of prompt engineering with a name, a trigger, and a version, stored in git. It turns one-off prompting into a managed, reviewable, updatable asset that every EM shares.
Why the writes are safe

You're letting automation write to your platform database - here's why it won't corrupt it

The fair worry about any LLM tool: it can word things differently each time, so how is it safe to point at your tasks, risks, and people records? Five patterns - each one real in this platform - keep the unpredictable part away from your data, on top of the database's own RLS and write gate.

a

The math lives in code, not the model

em-1on1-logger has the model extract true/false signals (each with a verbatim quote), then computes the 0-10 satisfaction score by fixed arithmetic in code - not model judgment. The model does what it's good at (read a transcript, decide "did they raise a blocker? true/false"); code does the counting, identically every time. Same signals in, same score out.

b

Idempotency keys - run it twice, nothing breaks

Every write carries a dedup key, e.g. convlog:<engagement>:<date>T<HH:MM>. Run the same skill twice on the same meeting and the second run is a no-op - no duplicate row. It's the same trick payment systems use to avoid double-charging.

c

Ambiguous? It returns needs_human instead of guessing

em-identity-resolver is deterministic and account-scoped: if it can't be sure who a name refers to, it returns needs_human rather than picking. The toolkit is allowed to refuse to act when confidence is low - bounded autonomy with an explicit escalation path, not a confident wrong answer.

d

Skills hand each other validated JSON, not prose

When one skill feeds another, it passes a schema-checked payload. Malformed output is rejected at the tool layer and the model retries. The validation is deterministic even though the generation isn't - that's how skills chain without small errors compounding into a bad write.

e

Propose → approve → apply for anything irreversible

Risk and task changes use a tick-to-approve loop (the RISK- propose/approve/apply flow, the draft queues). The model proposes, you approve, deterministic code applies. Nothing irreversible happens straight from raw model output.

All five together: the model proposes and reads; deterministic code decides, deduplicates, and applies; you approve anything irreversible. The unpredictable part can't directly cause a bad write.
Plugins & the manifest

Packaging, and why the toolkit is yours after one setup

A plugin is a folder with a plugin.json and subfolders for skills / agents / commands / hooks. The marketplace (qualitara-em) is a set of domain plugins - people management, risk, OKRs, reporting, and more. The plugin is the unit you version, ship, and update.

Config-as-data - skills hold zero hardcoded data

The platform resolves your identity from your Postgres login (em_private.effective_uid()) and your accounts from your assignments; per-EM preferences live in em.em_settings_current. A small file-only em-manifest.json overlay still carries file paths (renderer locations, output directory, Tability slug) - never data ids. That separation buys two things:

It's scoped. Every read and write is scoped to the accounts you're assigned - the same skill points at your data because the database gates it by identity, not because of a hardcoded id.

Code and configuration stay separate - a 50-year-old software principle applied to AI tooling. A skill can be updated for everyone without touching anyone's private setup.

Orchestration

How multi-step work gets done

Three escalating levels - knowing which one is running tells you how much is happening behind a single request:

MechanismWhat it isWhen it kicks in
Single skill auto-triggerOne description matches, one skill runs"log my 1:1"
SubagentA fresh model instance with its own context window; does a scoped job and returns a resultParallel independent work, or keeping a big search out of the main conversation
Orchestrator (Qira)A "boss" skill that plans, confirms once, dispatches specialists in order, then reports backComposite work: "close the quarter for Acme Robotics"
Subagents have isolated context, so one task's noise can't pollute another's. The daily routines (the morning run and the evening closer) are deterministic Python drivers that hand off through Postgres - the morning stages proposals in em.proposals, the evening applies the approved ones. They coordinate through the database, not a shared conversation.
The data flow

One request, end to end

Read it as a loop: the harness assembles context, the model (the only red, unpredictable box) proposes actions, tools read from your systems, and every write passes through the green determinism gate before it lands.

EM message / request CONFIG (FROM GIT) Plugins (domains) Skill index (names + desc) Settings (em.em_settings_current) Hooks (event triggers) deterministic, versioned The harness - holds the loop 1 · Assemble context inject the matched skill body Model (Opus 4.8) stochastic · the only unpredictable box 2 · Execute tool calls feed results back into the model call result DATA + CONNECTORS Postgres (em schema) Fireflies (transcripts) Microsoft 365 Tability (OKRs) reads proposed write DETERMINISM GATE · every write passes through source_key idempotency needs_human on ambiguity propose → approve → apply committed write
Unpredictable (the model) Deterministic harness / config Determinism gate before writes
In one breath: the model never touches a database directly. It reads through tools and emits a proposed write, which only commits after passing the green gate - dedup, ambiguity check, your approval. That gate is why an occasionally-wrong model can't cause a silent bad write.