State & Storage
Index ▾
- 01. Concepts
- 02. Architecture
- 03. State & Storage
- 04. Tools
- 05. BigQuery
- 06. Cloud Storage
- 07. Compute & Containers
- 08. Cloud Run
- 09. Pub/Sub
- 10. Databases
- 11. Observability
- 12. Access & Billing
- 13. Secret Manager
- 14. Networking
- 15. Scheduling & Tasks
- 16. Build & Artifacts
- 17. Guardrails
- 18. Setup
- 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
| State | Contents | Backend | Lifetime |
|---|---|---|---|
| Conversation context | The agent’s messages for a thread | in-memory or Firestore | 24h TTL |
| Pending approvals | Paused write runs awaiting Approve/Deny | in-memory or Firestore | 1h TTL |
| Event idempotency | Slack event ids already handled | in-memory or Firestore | short TTL |
| Audit log | One record per GCP tool call | local sink or Firestore | append-only |
| Google tokens | Per-user Fernet-encrypted refresh token | file per user (mounted bucket) | until you disconnect |
| Slack installs | Per-workspace OAuth install | file 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.