Skip to content

Concepts

The action layer

The single write path every actor uses — human, AI, integration, workflow. Why it exists, what it guarantees, and how to think about it.


The action layer is the single write path in Servanex. Every state change — booking a job, capturing a payment, merging a customer, sending an SMS, posting a ledger entry — happens through a tool defined in the action layer. There is no direct database write. There is no “back door.”

What runs in a tool

Every tool, when invoked, runs through the same pipeline:

  1. Validation. The input is parsed and validated against a Zod schema. Invalid input fails before any work is done.
  2. Permission check. The actor (human, AI, integration, or workflow) is checked against the tool’s required permission and any applicable approval policy.
  3. Idempotency lookup. If the tool is configured as idempotent, the request’s idempotency key is checked. Duplicate requests return the original result without re-executing.
  4. Tenant context. The Postgres connection sets app.tenant_id to the actor’s tenant — this is what RLS reads from to enforce isolation.
  5. Execute. The tool body runs: reads from this module’s repositories, calls other modules’ tools as needed, emits domain events via the outbox.
  6. Audit. The action log records actor, source, reason, input, output, outcome, latency, and (for AI calls) model, prompt version, tokens, and cost.
  7. Publish. Domain events flow from the Postgres outbox to EventBridge, where consumers (workflows, AI agents, integrations) react.

What this guarantees

  • No bypass. Nothing writes to the database without going through this pipeline. There is no service-account script, no integration shortcut, no ORM raw write.
  • Symmetric AI safety. The AI is constrained by the same rules as humans. If a CSR can’t refund over $1k without manager approval, neither can the AI.
  • Auditability. Every action is in the log. You can answer “who changed this, when, and why” for every record in the platform.
  • Event replay. Because every state change emits an event, you can replay history for analytics, debugging, or rebuilding caches.

How to think about it

If you’re coming from a traditional CRM or FSM, the closest mental model is: “every action is a function call, and every function call is logged.” If you’re coming from event-sourced systems, the closest model is: “the action log and event log are the source of truth, and the database is a projection.”

The platform was built this way from the first commit. It isn’t an audit feature bolted on later — it’s the foundation everything else depends on.