Skip to content

AI agent security and audit Provable, not promised.

actionlake controls what AI agents can do in your systems with mechanisms you can test: credentials encrypted per tenant and never shown to the agent, keys scoped to a system, an action or read-only, spending caps refused before a request is sent, human approval for chosen actions, and a hash-chained audit ledger sealed daily. Where something is not yet true, this page says so. The machine-readable version is actionlake-trust.json.

An engineer reads it. Or inspect it yourself first: start free, 100,000 calls, no card.

  • AES-256-GCMon every credentialunder a per-tenant data key, wrapped
  • sha256chains every run to the one before itchain head sealed to storage daily
  • 24hto notify a security incidentat most; the DPA summary says so
  • 0endpoints that return a credentialto an agent, or to any API caller

What the system enforces

Mechanisms, not adjectives.

Eight controls. Under each one, the field of the trust document that states it, quoted. Click through: the document is the page, in JSON.

Sealed on arrival. Unwrapped for one call.

A secret is posted once and encrypted before it is stored: AES-256-GCM under a per-tenant data key, wrapped by a master key (envelope encryption). The agent holds an ActionLake API key, never a vendor token.

credentials.in_useunwrapped in memory for the length of one upstream call; never logged; never returned by any endpoint; never in a prompt or a model's context

Refused before it leaves.

Every key carries a cap in calls and only the actions it was minted with. At the cap the request is refused before it is sent, so it costs nothing and nothing moved.

code · api/gate/caps.pya cap on every key, in upstream calls; a child's calls count against every parent; the call is refused before dispatch

The big ones wait for a yes.

A key's confirm policy and its approval rules name who decides. Under human policy the agent key cannot confirm itself. The run pauses; a person decides; it resumes or ends with nothing sent.

code · api/run/approvals.pya run suspends until a named person decides, in the console or from an emailed signed link

The record

Everything it did. And why.

run 7f3a9ckey "desk agent" · scope read:* + service.ticket.create · cap 500
  1. intent"the user asked which clients are 30+ days overdue and have an urgent ticket"the caller's one sentence, on the run
  2. vaultxero · unwrapped in memory · 1 call · discardednever logged, never returned, never in a prompt
  3. dispatchapi.xero.com · allowed by xero.json · TLS · no redirectone outbound module; private ranges refused
  4. receipt1 upstream call · 142 ms · $0.002 · MISSthe meter is on the response
  5. sealprev 5e2b…7d04 → hash c8a0…13f6 · chain head sealed dailychange a past row and every hash after it stops matching
  6. 90 daysintent cleared · hashes, ids, cost and outcome staythe record is permanent; the reason is kept 90 days
Illustrative run. Hashes and timings are an example of the shape, not real values.
  1. Intent

    It starts with a reason.

    Every run records the caller's one-sentence intent beside the key, the action and the connection. Not what the agent did only: why it said it was doing it.

  2. The vault

    The credential is unwrapped for one call.

    AES-256-GCM under a per-tenant data key, wrapped by a master key (envelope encryption). Decrypted in memory for the length of one upstream call, never logged, never returned by any endpoint, never in a prompt or a model's context.

  3. Dispatch

    One door out, and it is guarded.

    The request goes to a host the connector names, over TLS. Private ranges are refused and every redirect is re-checked. The cap was checked before this point; at the cap, nothing leaves.

  4. The receipt

    The meter is on the response.

    Calls, cost, cache verdict and timing come back on the response itself, and the same numbers are the row in the ledger. A cached answer is a call that never happened, and costs nothing.

  5. The seal

    Each row hashes the one before it.

    One row per run in `runs`: tenant, key, action, connection, status, cost, cache verdict, timing; each row stores sha256(prev_hash + row). The chain head per tenant is written to object storage once a day. Every run page shows prev_hash, hash and the hashed fields, so any run can be checked against the one before it.

  6. 90 days

    The record stays. The reason is kept 90 days.

    Hashes, identifiers, cost and outcome are permanent. The agent's stated reason is cleared after 90 days. Request and response bodies live in the trace store for your plan's window, then are deleted.

    Not yet true: an anchor outside our own infrastructure, and an export of the whole chain for recomputing it yourself. The seal proves the history to anyone who holds a copy; the console's CSV export carries the table, not the hashes. Both are in the honest-status list below.

What is kept, and for how long

Receipts stay. Bodies are on a timer.

The ledger.

Identifiers, hashes, costs and outcomes. The agent's stated reason is kept for 90 days. The record of the run is permanent.

Traces.

Each run's request and response, secrets removed, sealed under your tenant's key in Sydney, for your plan's window, then deleted. Readable only by the key that made the run, the root key, or a key granted traces:*.

The cache.

A cacheable read's response, keyed by your tenant and connection, for the action's declared TTL. A write invalidates the reads it affects. A body over 32 KB is sealed in the bucket instead.

Trace window per plan · from the price book
  1. Free24 hours
  2. Starter72 hours
  3. Pro7 days
  4. Team14 days
  5. Business30 days
  6. Enterprise30 days

Isolation and egress

Structural, not policy.

The tenant id is on every query and the cache key carries the connection id, so a cache hit can never serve another tenant's answer: by construction, not by review.

Nothing to probe.
Another tenant's run, key or connection is answered as if it never existed. The error does not confirm existence. Cross-tenant access is tried in the suite on every endpoint and expected to fail; no third-party test yet.
Your own address.
With the Dedicated IP add-on, every request to your vendors leaves from one static address of your own, private to your tenant, in Sydney, and is refused rather than sent from any other address when that one is unavailable.
Never training data.
Your traffic trains nothing. That is in the terms, not only on this page. No model sits between your agent and your systems.

The Dedicated IP, drawn: one static address, yours, that your vendors allow-list. HTTPS and the three database protocols leave from it; with the address unavailable, the request is refused.

In progress

Honest status.

SOC 2 Type II, ISO 27001 and a third-party penetration test are in progress. Until each report or certificate is issued, nothing on this page is an attestation. Every open item below is the trust document's own absences list, with what closes it.

  1. service_status.status_url

    No public status page exists yet.

    publish one at status.actionlake.com, with the cache hit rate and latency split by hit and miss

  2. subprocessors

    Stripe is not listed because no Stripe account is connected: billing.add_card records a token and the plan change, and no card is charged, so no customer data reaches Stripe from ActionLake.

    list Stripe (card tokenisation and invoicing; card details never touch ActionLake), with notice, before the first charge

  3. audit_record.external_witnesses

    The daily seal proves the history to anyone who holds a copy, but it is not yet anchored outside ActionLake's own infrastructure.

    publish the chain head to an independent, append-only location under a separate credential

  4. credentials.byok

    Envelope encryption per tenant under one environment master key is what exists. A customer-held key is not offered.

    a KMS-backed master key, when a customer needs it

  5. certifications.held

    No certification is held yet. SOC 2 Type II, ISO 27001 and a third-party penetration test are in progress.

    complete each one and list the report or certificate under `held`, with its date and scope

  6. dpa.document_url

    https://actionlake.com/legal/dpa describes what the DPA commits us to; the signable document is not published.

    publish the DPA and its technical measures annex

  7. disclosure.encrypted_channel

    No OpenPGP key exists for [email protected]. A published fingerprint for a key nobody holds is worse than none.

    generate the key, publish it, add Encryption to security.txt

  8. credentials.per_connection_key

    Credentials are sealed under the tenant's data key. Deleting a connection deletes its row, but a backup copy of that row stays decryptable until the backup ages out.

    a per-connection data key, wrapped by the tenant's and destroyed with the row

  9. audit_record.verifiable_by_customer

    A run can be checked against its neighbour on its page; the whole chain cannot yet be recomputed by a customer, because no export or endpoint returns a range of rows with their hashes.

    a chain export: every hashed field and both hashes, for a range

  10. availability.sla_in_force

    99.9% is a published availability target for team, business, enterprise, not a commitment with credits. Managed MySQL daily backups with 7 days of point-in-time recovery, kept in the region; a restore to a scratch database is exercised monthly and the chain verified from the seal.

    an SLA written into the agreement, with credits

  11. personnel_access.production

    No product screen shows your content to anyone outside your tenant. Production access is limited to named ActionLake engineers, for operations; the master key is an environment key on the API service, so those engineers could decrypt customer content. That is the position, stated plainly.

    the KMS-backed master key that also closes credentials.byok

  12. isolation.cross_tenant_access_tested

    Tenant id on every query; cache key carries the connection id; cross-tenant access is tested in the test suite, on the endpoints; no third-party test yet.

    the third-party penetration test above

Security incidents are notified within 24 hours. Role under the DPA: processor. The DPA summary is at /legal/dpa; the signed document is part of the enterprise agreement.

Sub-processors

Who else sees traffic.

Data is stored in Sydney. In transit it passes through Cloudflare's global edge, which terminates TLS for actionlake.com and the api, mcp, connect and auth hosts. Approval mail goes through SendGrid in the United States. Three names; the full list is also in the privacy policy.

Sub-processorPurposeRegionCountry
DigitalOcean, LLCcompute, managed MySQL, managed Valkey, object storage (traces, seals, spilled cache bodies), the static sitesyd1Australia
Cloudflare, Inc.DNS, TLS termination, CDN and WAF for actionlake.com and the api, mcp, connect and auth hosts; sees traffic in transit, including API keys, tokens and credentials posted to connections.createglobalUnited States
Twilio Inc. (SendGrid)approval mail: the approver's address, the request summary, and the action's input with credential-named keys maskedglobalUnited States

Pending: Stripe is not listed because no Stripe account is connected: billing.add_card records a token and the plan change, and no card is charged, so no customer data reaches Stripe from ActionLake.

Machine-readable

Your agent can read this page.

Every claim here is a field in one public JSON document, absences included, with no placeholders. Point a procurement agent, or a procurement team, at it before anyone signs anything.

{
  "document": {
    "version": 6,
    "updated": "2026-10-24"
  },
  "credentials": {
    "at_rest": "AES-256-GCM under a per-tenant data key, wrapped by a master key (envelope encryption)",
    "byok": false
  },
  "model_on_data_path": false,
  "certifications": {
    "held": [],
    "soc2": "in progress (Type II)"
  },
  "residency": {
    "regions": [
      "syd1"
    ],
    "single_region": true
  },
  "availability": {
    "published_sla_pct": "99.9",
    "sla_in_force": false
  },
  "incident_notification_hours": 24,
  "absences": "[ 9 items, each with what closes it ]"
}
An excerpt. The document holds 22 top-level fields and 9 named absences.

Disclosure

Security research, welcome.

An engineer reads every report. Write to [email protected]. A sandbox tenant for testing is one unauthenticated call away.

"Good-faith research that follows this policy will not be met with legal action from ActionLake, and we will say so in writing to anyone who asks."

In scope
the MCP and REST surfaces, the OAuth 2.1 server, tenant-isolation testing across two identities you own, the egress guard, and tamper attempts on the run ledger
Out of scope
  • Testing against another customer's data or another customer's connected systems. Ask for a sandbox tenant instead - one unauthenticated call creates one.
  • Denial of service and volumetric testing.
  • Social engineering of ActionLake people or ActionLake's vendors.
  • Findings in a third-party product rather than in ActionLake.
Window
90 days to coordinated disclosure.
Encryption
No OpenPGP key exists yet; a fingerprint for a key nobody holds is worse than none. Send reports in plain text until security.txt says otherwise.

Bring us your security review.

An engineer reads it. The DPA summary is published; the signed document is part of the enterprise agreement.