An AI Agent Changed a Cache Setting and XKV Kept the Tool Call Behind It
An operations agent watches the product catalog. Its metrics show 4.1% of reads returning stale data, above the 2% target, so it shortens the catalog cache’s time-to-live from 300 seconds to 30. That’s a reasonable move. An hour later the catalog database is at 91% CPU, because the cache now sends ten times as many reads its way. An engineer puts the TTL back.
The next morning the team wants to know what happened. The questions are the usual ones, with a new twist: which change did the agent make, what was it looking at, and which of its tool calls did it? Agents act fast and often, so their changes need a trail at least as good as a person’s.
In XKV an agent writes the same way any other writer does. It gives its reason, names the observation it acted on as the cause, and puts its tool call id in the ref:

What the Agent Writes
The metrics job records what it saw. The agent acts on it and says so:
agent := xkv.WithActor(ctx, "ops-agent")
change, err := db.Put(agent, "cache:catalog:ttl", []byte("30s"),
xkv.Reason("stale reads above the 2% target; shorter TTL"),
xkv.Ref("toolcall_01J9ZK4T3M"),
xkv.Cause(stale.Key, stale.Rev))
The ref ties the store to the agent’s own log. Whoever reviews the change can open that tool call and see the agent’s full reasoning, while the store keeps the short version next to the value.
What the Engineer Writes
The revert points at both things the engineer weighed: the agent’s change, and the CPU reading it caused.
eng := xkv.WithActor(ctx, "dana@platform")
_, err = db.Put(eng, "cache:catalog:ttl", []byte("300s"),
xkv.Reason("revert: 30s TTL tripled catalog DB load"),
xkv.Ref("INC-4512"),
xkv.Cause(change.Key, change.Rev), xkv.Cause(load.Key, load.Rev))
The Morning After
cache:catalog:ttl = 300s r5
│ was 30s · by dana@platform · revert: 30s TTL tripled catalog DB load · ref INC-4512
├─ cache:catalog:ttl = 30s r3
│ │ was 300s · by ops-agent · stale reads above the 2% target; shorter TTL · ref toolcall_01J9ZK4T3M
│ └─ observed:catalog:stale-reads = 4.1% over the last hour r2
│ by metrics-collector · hourly sample
└─ observed:catalog-db:cpu = 91% average r4
by metrics-collector · hourly sample
The tree tells the whole story without anyone reconstructing it. The agent saw stale reads and shortened the TTL. That raised database load, and a person reverted it, citing both. The team now has a concrete lesson to give the agent: weigh database load before shortening a cache TTL.
People and agents leave the same kind of trail here, with the same checks. An agent can’t cite an observation that doesn’t exist, and strict mode refuses its writes without a reason, just as it refuses a person’s.
Run It Yourself
git clone https://github.com/explainable-kv/xkv
cd xkv
go run ./examples/agent-setting
The agent’s change is one of the stories in the live demo.