0% 0% 0% 0%

State & Storage

Index
  1. 01. Concepts
  2. 02. Architecture
  3. 03. State & Storage
  4. 04. Tools
  5. 05. BigQuery
  6. 06. Cloud Storage
  7. 07. Compute & Containers
  8. 08. Cloud Run
  9. 09. Pub/Sub
  10. 10. Databases
  11. 11. Observability
  12. 12. Access & Billing
  13. 13. Secret Manager
  14. 14. Networking
  15. 15. Scheduling & Tasks
  16. 16. Build & Artifacts
  17. 17. Guardrails
  18. 18. Setup
  19. 19. Deploy to Cloud Run

State & Storage

enoki is built to keep as little as possible, for as short as possible, inside your own project. This page is the full inventory of what it stores, where, and for how long — and how that changes between a single-instance dev run and a horizontally-scaled deployment.

What enoki stores

StateContentsBackendLifetime
Conversation contextThe agent’s messages for a threadin-memory or Firestore24h TTL
Pending approvalsPaused write runs awaiting Approve/Denyin-memory or Firestore1h TTL
Event idempotencySlack event ids already handledin-memory or Firestoreshort TTL
Audit logOne record per GCP tool calllocal sink or Firestoreappend-only
Google tokensPer-user Fernet-encrypted refresh tokenfile per user (mounted bucket)until you disconnect
Slack installsPer-workspace OAuth installfile per install (mounted bucket)until uninstall

Everything above lives in the operator’s own Google Cloud project. Nothing is sent to a third party, and nothing about the message beyond short-lived context is ever persisted.

Conversation context

Each thread’s history is keyed by (channel_id, thread_ts) and holds the agent’s ModelMessage list — enough for follow-ups like “now stop it” to resolve. It carries a 24-hour TTL and is re-fetched live rather than mined from history.

  • Single instance — an in-memory, per-process store. Never touches disk; gone on restart.
  • Multi-instance (ENOKI_STORE=firestore) — a Firestore collection so any instance can read the thread. Still TTL-bounded and still inside your project.

Pending approvals

When the model calls a write tool, the run pauses and its state is stashed as a pending approval until you click Approve or Deny. Because an approval click can land on any Cloud Run instance, this store is Firestore-backed in production — the paused run must be visible to whichever instance handles the button. It carries a 1-hour TTL.

Idempotency

Slack retries an event if it doesn’t get a fast enough ack. enoki records each event id and skips duplicates. In multi-instance mode the claim is an atomic Firestore create() — the first instance to write the id wins, so a retry that lands elsewhere is still deduped.

Audit log

Every GCP tool call is appended to a structured, append-only audit record: Slack user, Google email, tool, read-or-write, arguments, and result — including denied approvals. In Firestore mode each event is its own document, which is safe under concurrent writes from many instances.

Tokens and installs

Per-user Google refresh tokens are Fernet-encrypted and written one file per user; Slack installs are one file per workspace. These are file-per-key and safe for concurrent access across instances, so they stay on a mounted Cloud Storage bucket rather than Firestore.

Next: Tools — every action enoki can take.