ActessiaBook a 30-day pilot
Documentation

The security model, technical version

The exact checks behind the security page, for the engineer who will read it closely: the intent shape, validation, identity signing, confirmations, idempotency, encryption, refusal reasons.

The security page is written for founders. This page is the same model with the mechanics left in. Every item here is enforced by the broker, a separate non-AI service that sits between the model and your API, regardless of what the model decided.

The intent, and what happens to it

The model never calls anything. It emits an intent:

{ "tool": "reschedule_appointment", "args": { "id": "apt_8812", "starts_at": "2026-09-17T16:00:00+03:00" } }

The broker then, in order:

  1. Validates the arguments against the tool's JSON Schema (the one generated from your OpenAPI operation): no additional properties, bounded string lengths and object depth, path segments that cannot escape the operation's path, numbers within the ranges you set.
  2. Recomputes the idempotency key from the session, the tool and a hash of the arguments. A key seen before in the same conversation is refused as a replay.
  3. Checks the allowlist: the tool is enabled on this site; its classification (read, write, destructive) is permitted by your plan and your tenant switch; the session is identified and the identified user belongs to this site.
  4. Checks the confirmation for write and destructive tools: a single-use token bound to the tenant, site, session, user, intent, tool and argument hash, with a short expiry.
  5. Attaches the credential and calls your API (see auth schemes below).
  6. Filters the response to the fields you allowed for that tool, and writes the call, its arguments and the filtered result to the audit log.

Identity

Actions exist only for identified users. Your server signs the identify payload with the site's secret: HMAC-SHA256 over the canonical JSON of the payload (RFC 8785), with an issued-at timestamp. The broker accepts five minutes of clock skew and a maximum age of one hour. A client-asserted user id is never trusted; a wrong or stale signature is a 401 and the session stays anonymous. The signing snippets, one per language, are on the identify() page.

Auth schemes

  1. Token exchange (preferred): your app exposes an endpoint the broker calls with the identified user's id and receives a short-lived, narrowly scoped token for that user. It lives in the broker's memory for its lifetime and is never logged.
  2. Service credential with on-behalf-of: a credential you store in the dashboard, envelope-encrypted under your tenant's data encryption key; the broker sends it with an X-On-Behalf-Of header carrying the user's id, and your API decides what that user may do.
  3. Bearer per user (last resort): a long-lived per-user key. It works; it is the least safe option.

Whatever the scheme, the credential exists only inside the broker, is never placed in model context, never logged, and is scrubbed from every error message.

Classification and confirmations

Every imported operation is classified from its HTTP method and wording; you can override any classification on the tool's page.

  • read runs when the model asks, within the grant's per-session and per-day limits.
  • write needs the confirmation card, which states every field that will change before anything is sent.
  • destructive (delete, cancel, refund, anything moving money) is off for the whole tenant by default, needs the card, and is written to the audit log with the complete before and after payload.

A timed-out call whose outcome is unknown is reported as unknown to the user and is never retried blindly.

The audit log

Append-only: the table has no update or delete grant for any role, including our own services. A row records the actor (end user, dashboard user, service, or platform admin), the action, the target, the before and after state, a reason when one was given, and the trace id that joins it to the conversation. Staff impersonation requires a written reason and appears in your log with that reason. You can filter and export it from the dashboard.

Hostile content

Retrieved passages and tool results are wrapped in delimiters and labelled untrusted; the system prompt instructs the model to treat instructions inside them as data. That is the soft layer. The hard layer is the broker: allowlist, classification and confirmation rules apply whatever the model decided, so a successful injection can produce a bad suggestion, never a completed destructive action. Outbound links in answers are restricted to the domains you registered. Every blocked tool call is logged, and the blocked-call rate is a dashboard metric.

Spend and abuse

  • The site key works only on the origins you registered; the check is server-side.
  • Rate limits per session, IP address, site and tenant, per minute, hour and day.
  • A per-tenant daily spend cap with a hard stop; the agent closes gracefully and offers a person.
  • Ceilings on turns and tokens per conversation.
  • A bot challenge only on anomalous patterns, never shown to normal users.
  • Anonymous visitors use the cheapest model tier and have no tools.

Data

  • Customer data lives in the EU. The runtime and the broker run in an EU region.
  • Transcripts are redacted before long-term storage (card numbers, IBANs, emails, phone numbers, addresses, tokens). The original is envelope-encrypted under your tenant's key; revealing it is a dashboard action by an admin, with a reason, written to the audit log.
  • Per-tenant data encryption keys are wrapped by our key-encryption key. A tenant's secrets (the identify secret, API credentials, your own model key) are encrypted under its key and never returned to any client beyond their last four characters.
  • Retention is per tenant, 90 days by default, with hard deletion, plus a deletion endpoint.
  • Data leaves the EU only for model inference and embeddings, under the DPA.

Refusal reasons

Each refusal is one row in the audit log with one of these codes, and one plain sentence in the widget.

Code Meaning
classification_not_permitted a tool whose classification your plan does not include
destructive_disabled any destructive tool while the tenant-level switch is off
anonymous_session any tool for a visitor who has not been identified
end_user_mismatch a session or user id that does not belong to this site
confirmation_missing, confirmation_invalid, confirmation_expired a write without a valid, single-use confirmation
args_invalid, args_out_of_bounds arguments outside the schema, or outside sane bounds
idempotency_replay the same write again in the same conversation
tool_rate_limited, tenant_rate_limited, circuit_open more calls than the grant, the tenant, or your API's health allows

Questions and reports: security@actessia.ai.