Key-Value Storage

Small, structured state that an agent or app needs to remember between runs, without sending it through an LLM turn.

Overview

Key-value storage is for the small, structured state your agent or app needs to keep between runs.

Use it when something is true and worth remembering, but does not belong in conversational memory or in a config file:

  • a dedupe marker so the agent does not act twice on the same input
  • a counter, a last-seen timestamp, or a "last deploy SHA"
  • a short flag that another script needs to read on the next run
  • the result of a one-off lookup you do not want to repeat

Key-value storage is deterministic. You read what you wrote. There is no LLM in the loop.

Memory, key-value storage, and configs

Each home for state has its own job. The shape of what you are storing tells you which one to reach for.

Diagram comparing three places state can live in ArchAgents: agent memory for durable facts, key-value storage for small structural state, and configs for source-controlled setup

When to use it (and when not to)

Use key-value storage for Use Agent Memory for
Structural state, flags, counters, IDs, hashes Durable facts the agent should know across conversations
Logic that needs an exact value back Soft context like preferences or recurring project facts
Cheap, fast reads inside scripts Information the agent uses to behave more consistently

If the value is something a teammate would expect the agent to "remember," it probably belongs in memory. If it is something the agent's own logic needs to look up to do its job, it belongs in key-value storage.

For project-wide configuration that should be reviewable in source control, reach for Configs instead.


In scripts: the storage namespace

Inside a script, the storage namespace gives you read and write access to the calling agent's own bucket.

let storage = import("storage")

// Has this PR already been reviewed?
let existing = storage.get("pr_" + prNumber.toString() + "_reviewed")
if existing.ok {
 return "SKIP"
}

// Remember the deploy we just acted on
unwrap(storage.set("last_deploy_sha", commitSha))

// Mark a transient flag that expires
unwrap(storage.set("alert_sent", "true", { remember_until: "1 day" }))

The available functions are:

Function Returns Notes
storage.get(key) Result with {key, value} or not-found Use for full reads
storage.set(key, value) Result with {key, value} Upsert. Adds or replaces
storage.set(key, value, { remember_until }) Result with {key, value} TTL form. See remember_until below
storage.exists(key) Result with boolean Cheaper than get when you only need a yes/no
storage.delete(key) Result with {key, value} Removes the entry
storage.list() Result with {entries, count} Returns this agent's full bucket

remember_until accepts "1 hour", "1 day", "7 days", "14 days" (default), "30 days", "forever", or an ISO 8601 timestamp. Values without an explicit remember_until use the default of 14 days.

The script must be running in an agent context (the viewer needs to be an agent). Routine handlers and workflow-attached scripts already meet that requirement.


In the developer portal: browse and edit

The developer portal exposes the KV store under Dashboard -> Apps -> your app -> Storage -> Key-Value. From there you can:

  • search by key prefix or by user
  • inspect a value, including its expiry
  • create, edit, or delete entries by hand

Reach for it when you're debugging: to confirm a flag was actually set, clear a stuck dedupe marker, or seed a value for a test.


From the SDK

The developer SDK exposes the same store programmatically, useful when your app needs to read or write entries on behalf of a specific user.

import { ArchAstro } from "@archastro/developer-platform-sdk";

const archastro = new ArchAstro({ secretKey: process.env.ARCHASTRO_SECRET_KEY });

// List entries for one user
const page = await archastro.kv.list(appId, { user: userId });

// Read or write a single entry
const entry = await archastro.kv.upsert(appId, userId, "feature_flag.beta", { value: "true" });

This is the right surface when the value is set or read by your product code rather than by an agent script.


A practical pattern

A daily release-notification automation can use storage to make sure the agent does not double-post:

  1. Each morning, the automation reads last_announced_release from storage.
  2. If the latest release matches, the automation returns early.
  3. Otherwise it posts the announcement and writes the new value back.

That is the whole job: one read, one comparison, one write. The agent stays deterministic, the channel does not get spammed, and a human can inspect the value in the portal at any time.


Best practices

A good key-value setup is:

  • specific: keys describe what is stored, not where it came from
  • bounded: values are short, structured, and rarely larger than a few hundred bytes
  • intentional: every write has a clear reason, every read has a clear use
  • reviewable: a teammate can look at the keys in the portal and follow the agent's logic

Avoid using key-value storage as a general document store or a fallback for things that should live in Knowledge. The store is small on purpose.


Where to go next

  1. Agent Memory: when "remember this fact" is the right framing instead of "store this value."
  2. Scripts: the surface where most key-value reads and writes live.
  3. Configs: for setup that belongs in source control rather than a runtime store.