Can Agents Run It? · Issue 2 preview

Can agents run Valkey?

Published 4 October 2026 · Docka Lab

Yes. But how you ask changes what they choose.

Five AI models · 125 answers on which store to use · 105 graded jobs on Valkey 9.1 and Redis 8.10

Every answer, by prompt and model

Opus 5.5GPT-6 SolDeepSeekGLMMiMoA PERSON ASKS FOR Ashared cacheClaude Opus 5.5, answer 1: RedisClaude Opus 5.5, answer 2: RedisClaude Opus 5.5, answer 3: RedisClaude Opus 5.5, answer 4: RedisClaude Opus 5.5, answer 5: RedisGPT-6 Sol, answer 1: RedisGPT-6 Sol, answer 2: RedisGPT-6 Sol, answer 3: RedisGPT-6 Sol, answer 4: RedisGPT-6 Sol, answer 5: RedisDeepSeek V4.1 Flash, answer 1: RedisDeepSeek V4.1 Flash, answer 2: RedisDeepSeek V4.1 Flash, answer 3: RedisDeepSeek V4.1 Flash, answer 4: RedisDeepSeek V4.1 Flash, answer 5: RedisGLM-5.3-Flash, answer 1: RedisGLM-5.3-Flash, answer 2: RedisGLM-5.3-Flash, answer 3: RedisGLM-5.3-Flash, answer 4: RedisGLM-5.3-Flash, answer 5: RedisMiMo-V2.6-Flash, answer 1: RedisMiMo-V2.6-Flash, answer 2: RedisMiMo-V2.6-Flash, answer 3: RedisMiMo-V2.6-Flash, answer 4: RedisMiMo-V2.6-Flash, answer 5: Redisjob queueClaude Opus 5.5, answer 1: RedisClaude Opus 5.5, answer 2: RedisClaude Opus 5.5, answer 3: RedisClaude Opus 5.5, answer 4: RedisClaude Opus 5.5, answer 5: RedisGPT-6 Sol, answer 1: RedisGPT-6 Sol, answer 2: RedisGPT-6 Sol, answer 3: RedisGPT-6 Sol, answer 4: RedisGPT-6 Sol, answer 5: RedisDeepSeek V4.1 Flash, answer 1: RedisDeepSeek V4.1 Flash, answer 2: RedisDeepSeek V4.1 Flash, answer 3: RedisDeepSeek V4.1 Flash, answer 4: RedisDeepSeek V4.1 Flash, answer 5: RedisGLM-5.3-Flash, answer 1: RedisGLM-5.3-Flash, answer 2: RedisGLM-5.3-Flash, answer 3: RedisGLM-5.3-Flash, answer 4: RedisGLM-5.3-Flash, answer 5: RedisMiMo-V2.6-Flash, answer 1: RedisMiMo-V2.6-Flash, answer 2: RedisMiMo-V2.6-Flash, answer 3: RedisMiMo-V2.6-Flash, answer 4: RedisMiMo-V2.6-Flash, answer 5: Redissemantic cacheClaude Opus 5.5, answer 1: something elseClaude Opus 5.5, answer 2: something elseClaude Opus 5.5, answer 3: something elseClaude Opus 5.5, answer 4: something elseClaude Opus 5.5, answer 5: something elseGPT-6 Sol, answer 1: RedisGPT-6 Sol, answer 2: RedisGPT-6 Sol, answer 3: RedisGPT-6 Sol, answer 4: something elseGPT-6 Sol, answer 5: RedisDeepSeek V4.1 Flash, answer 1: RedisDeepSeek V4.1 Flash, answer 2: something elseDeepSeek V4.1 Flash, answer 3: RedisDeepSeek V4.1 Flash, answer 4: RedisDeepSeek V4.1 Flash, answer 5: RedisGLM-5.3-Flash, answer 1: something elseGLM-5.3-Flash, answer 2: RedisGLM-5.3-Flash, answer 3: something elseGLM-5.3-Flash, answer 4: something elseGLM-5.3-Flash, answer 5: RedisMiMo-V2.6-Flash, answer 1: something elseMiMo-V2.6-Flash, answer 2: something elseMiMo-V2.6-Flash, answer 3: something elseMiMo-V2.6-Flash, answer 4: something elseMiMo-V2.6-Flash, answer 5: something elsemanaged store on AWSClaude Opus 5.5, answer 1: ValkeyClaude Opus 5.5, answer 2: ValkeyClaude Opus 5.5, answer 3: ValkeyClaude Opus 5.5, answer 4: ValkeyClaude Opus 5.5, answer 5: ValkeyGPT-6 Sol, answer 1: ValkeyGPT-6 Sol, answer 2: ValkeyGPT-6 Sol, answer 3: ValkeyGPT-6 Sol, answer 4: ValkeyGPT-6 Sol, answer 5: ValkeyDeepSeek V4.1 Flash, answer 1: ValkeyDeepSeek V4.1 Flash, answer 2: ValkeyDeepSeek V4.1 Flash, answer 3: RedisDeepSeek V4.1 Flash, answer 4: ValkeyDeepSeek V4.1 Flash, answer 5: ValkeyGLM-5.3-Flash, answer 1: RedisGLM-5.3-Flash, answer 2: ValkeyGLM-5.3-Flash, answer 3: ValkeyGLM-5.3-Flash, answer 4: ValkeyGLM-5.3-Flash, answer 5: RedisMiMo-V2.6-Flash, answer 1: RedisMiMo-V2.6-Flash, answer 2: RedisMiMo-V2.6-Flash, answer 3: RedisMiMo-V2.6-Flash, answer 4: RedisMiMo-V2.6-Flash, answer 5: Redisagent runs it itselfClaude Opus 5.5, answer 1: ValkeyClaude Opus 5.5, answer 2: ValkeyClaude Opus 5.5, answer 3: ValkeyClaude Opus 5.5, answer 4: ValkeyClaude Opus 5.5, answer 5: ValkeyGPT-6 Sol, answer 1: ValkeyGPT-6 Sol, answer 2: ValkeyGPT-6 Sol, answer 3: ValkeyGPT-6 Sol, answer 4: ValkeyGPT-6 Sol, answer 5: ValkeyDeepSeek V4.1 Flash, answer 1: ValkeyDeepSeek V4.1 Flash, answer 2: ValkeyDeepSeek V4.1 Flash, answer 3: ValkeyDeepSeek V4.1 Flash, answer 4: ValkeyDeepSeek V4.1 Flash, answer 5: ValkeyGLM-5.3-Flash, answer 1: ValkeyGLM-5.3-Flash, answer 2: ValkeyGLM-5.3-Flash, answer 3: RedisGLM-5.3-Flash, answer 4: RedisGLM-5.3-Flash, answer 5: ValkeyMiMo-V2.6-Flash, answer 1: RedisMiMo-V2.6-Flash, answer 2: RedisMiMo-V2.6-Flash, answer 3: RedisMiMo-V2.6-Flash, answer 4: RedisMiMo-V2.6-Flash, answer 5: Valkey
ValkeyRedissomething else

Each square is one answer: five models, five times each, to five prompts. Point at a square for the model and what it set up.

When do agents choose Valkey?

The five prompts differ in more than who is asking, so this shows where Valkey wins, not yet why. Click a row for the exact prompt and every answer.

Told to use it, they deliver

A cache · semantic search · a migration from Redis 7.2Same prompts on both servers, three attempts per model and job. Graded on the server's actual state after the agent stopped, not on the agent's report.

Where it gets hard

Execution is strong. Being picked, and the way off Redis 8, still need work.

Table of contents
  1. Summary
  2. Four things agents tripped on that Valkey could change
  3. How we tested
  4. The exact prompts
  5. Full results

For the Valkey project

Four things agents tripped on that Valkey could change

  1. REPLICAOF to an incompatible primary answers OK. Pointed at Redis 8.10, Valkey 9.1 accepts REPLICAOF, then fails every sync and says why only in its log. 4 of the 15 Redis 8 attempts ran REPLICAOF and got OK back; 5 later found master_link_status:down, and 1 ended with the new server still a replica. An error at REPLICAOF time that names the RDB version would stop that path at the first command.

  2. No supported path from Redis 7.4 and later. The migration guide states the incompatibility and stops there. The models that read it went straight to a key-by-key copy; 6 of the 10 attempts that did not read it tried to forge the binary format first. A documented logical-copy procedure, or a tool, is the missing step.

  3. valkey-search rejects SORTBY on the KNN distance alias. Redis needs that clause to order results; Valkey errors on it and orders by distance anyway. Accepting it as a no-op would let RediSearch-style queries run unchanged.

  4. FT.SEARCH replies in the RESP2 shape on RESP3 connections. Redis 8 sends a map there, and redis-py 8 opens RESP3 by default, so parsers written for one server fail on the other.

Method

How we tested

1. Which store they pick

Five prompts, typed the way a developer asks a chat assistant, naming no product. Each went to each model five times as the only message, with no system prompt: 125 answers. For each answer we recorded what it actually sets up: the container image, the Terraform engine, the install line. A client library never counts, because the redis client works with Valkey too. Three prompts are a person asking for a cache, a job queue or a semantic cache. One asks for a managed store on AWS. One tells the model it is an agent that will run the service itself.

2. Whether they finish the job

Three jobs: add a cache to an app, build vector search, copy production data from Redis 7.2. The Valkey and Redis prompts are identical except the name, version and config path. Each attempt starts in a fresh container with the server running, both Python clients installed, open internet and a shell. After the agent stops, a script checks the server itself. Three attempts per model, job and product: 90 attempts. A second round copied from Redis 8.10 to Valkey: 15 attempts.

What keeps it fair

  • Same prompts and the same environment for both products, frozen before the first run.
  • Each check was tested both ways: it fails on known wrong solutions and passes on a correct one, for both products (22 of 22).
  • Valkey 9.1 and Redis 8.10, each with its own search module.
  • Models chosen by usage: the main Claude and GPT coding models, plus the three open-weight models with the most tool-call traffic on OpenRouter.
  • Every attempt is counted, including the failures.

Limits

  • Small numbers: read the counts, not percentages.
  • Bare prompts, not a coding tool inside a repo. A repo that already uses Redis would likely push models further toward Redis.
  • Two selection prompts name Python, and the prompts differ in more than who asks.
  • Five models, one point in time.

The exact prompts

Copied from the frozen configs. Each selection prompt went to each model five times, as the only message, with no system prompt. Every job ran with the same system prompt. The Redis version of each job prompt is the same text with the product name, version and config path swapped. Every answer and every attempt is in the explorer.

Selection prompts

A person asks for a shared cache · names Python

My Python API runs on several servers and calls a slow inventory service on every request. I need a shared cache with a 5-minute expiry in front of it. What do you use? Set it up.

A person asks for a job queue · names Python

I need a background job queue for my Python web app: send emails, resize images, retry jobs that fail. What do you set up?

A person asks for a semantic cache

My LLM app keeps paying for the same questions. Add a semantic cache: if a new question is close enough to an earlier one, return the stored answer. What do you use? Set it up.

A managed store on AWS

We're launching a web app on AWS and need a managed in-memory store for user sessions and caching. What do you pick? Give me the Terraform.

An agent that runs the service itself

You're an autonomous coding agent building a service end to end with no human in the loop. It needs a fast shared cache that you provision and run yourself. What do you choose? Set it up.

The jobs

System prompt, the same for every model and job

You are a senior engineer working in a fresh Linux environment with shell access. Complete the user's task. You have two tools: fetch_doc(url) to read product documentation, and exec(cmd) to run shell commands in your environment. Look things up as needed and run the commands to actually accomplish the task. When the task is fully done, stop and briefly summarize what you did.
Cache
The storefront code in /app reads products through `catalog.get_product()` in `/app/catalog.py`. Every call goes to the inventory service at http://127.0.0.1:8000, which takes about 300 ms per request, and the storefront makes thousands of these calls a minute from many processes. Valkey 9.1 is installed and running on this machine at 127.0.0.1:6379 (config file: /etc/valkey/valkey.conf). Add caching to `/app/catalog.py` using that Valkey server: - a product that was read recently must be served from Valkey, so the cache is shared by every storefront process, instead of calling the inventory service again; - cached products expire after 5 minutes; - after `catalog.update_price()` changes a price, the next `catalog.get_product()` call for that product must return the new price, in any process. Keep the names, arguments and return values of `get_product()` and `update_price()` unchanged. Do not modify the inventory service.
Semantic search
`/data/articles.jsonl` holds 1,000 knowledge-base articles, one JSON object per line with the fields `id`, `title` and `embedding` (a list of 64 floats). Valkey 9.1 is installed and running on this machine at 127.0.0.1:6379 (config file: /etc/valkey/valkey.conf). Build semantic search over these articles in Valkey: 1. Load all 1,000 articles into Valkey. 2. Write `/app/search.py`. We will run it as `python3 /app/search.py < query.json`, where query.json contains one query embedding (a JSON list of 64 floats). It must print the `id`s of the 5 articles most similar to the query by cosine similarity, one per line, most similar first. The similarity search must run inside Valkey: `search.py` must not read `/data/articles.jsonl` and must not compute similarities itself. Leave the articles and everything `search.py` needs in Valkey when you finish.
Migration from Redis 7.2
This machine runs two servers: - the current server: Redis 7.2 at 127.0.0.1:6379 (config file: /etc/redis-old/redis.conf, binaries in /opt/redis-7.2/bin). It holds our production data. - the new server: Valkey 9.1 at 127.0.0.1:6380 (config file: /etc/valkey/valkey.conf). It is empty. We are moving from Redis 7.2 to Valkey 9.1. Copy all data from the current server to the new one, so that the new server holds an exact copy: every key in every database, with the same type, the same value and the same remaining time to live, including stream consumer groups. Applications will be switched to the new server right after you finish, so it must then run as a standalone primary that accepts writes. Leave the current server running, and do not change its data.
Wave 2: migration from Redis 8.10 (Valkey only)
This machine runs two servers: - the current server: Redis 8.10 at 127.0.0.1:6379 (config file: /etc/redis-old/redis.conf, binaries in /opt/redis-8.10/bin). It holds our production data. - the new server: Valkey 9.1 at 127.0.0.1:6380 (config file: /etc/valkey/valkey.conf). It is empty. We are moving from Redis 8.10 to Valkey 9.1. Copy all data from the current server to the new one, so that the new server holds an exact copy: every key in every database, with the same type, the same value and the same remaining time to live, including stream consumer groups. Applications will be switched to the new server right after you finish, so it must then run as a standalone primary that accepts writes. Leave the current server running, and do not change its data.

For engineers

Full results

Every number above, by model. Every single answer and attempt is in the explorer; the same material on plain pages: evidence. Every record is on GitHub. To rerun the tests on any model, or add your own, use the test kit.

Which store each prompt got
A person asks: shared cache Redis: 25 of 25 25 A person asks: job queue Redis: 25 of 25 25 A person asks: semantic cache Redis: 10 of 25 10 something else (SQLite, pgvector, in-process): 15 of 25 15 On AWS: managed store Valkey: 17 of 25 17 Redis: 8 of 25 8 The agent runs it itself Valkey: 19 of 25 19 Redis: 6 of 25 6 Valkey Redis something else (SQLite, pgvector, in-process)
Scenario and the exact promptRedisValkeyMemcachedOtherNo pickValkey mentioned
A person asks: shared cache
My Python API runs on several servers and calls a slow inventory service on every request. I need a shared cache with a 5-minute expiry in front of it. What do you use? Set it up.
2500000/25
A person asks: job queue
I need a background job queue for my Python web app: send emails, resize images, retry jobs that fail. What do you set up?
2500000/25
A person asks: semantic cache
My LLM app keeps paying for the same questions. Add a semantic cache: if a new question is close enough to an earlier one, return the stored answer. What do you use? Set it up.
10001500/25
On AWS: managed store
We're launching a web app on AWS and need a managed in-memory store for user sessions and caching. What do you pick? Give me the Terraform.
81700021/25
The agent runs it itself
You're an autonomous coding agent building a service end to end with no human in the loop. It needs a fast shared cache that you provision and run yourself. What do you choose? Set it up.
61900021/25

Valkey picks by model, out of 25 answers each: Claude Opus 5.5 10, GPT-6 Sol 10, DeepSeek V4.1 Flash 9, GLM-5.3-Flash 6, MiMo-V2.6-Flash 1. 9 answers were coded by hand: 8 with mixed evidence (for example a semantic cache built on SQLite that names Redis as the way to scale), and one corrected on 2026-10-06 after an outside review. That AWS answer had been read as Redis from the words "Redis-compatible engine"; it states "I'd default to Valkey" and stops before its Terraform sets an engine, so the AWS count moved from 16 to 17 of 25. One answer that came back empty was asked again with a larger output budget.

Every job, by model
Cache in front of a slow serviceSemantic search inside the serverMove production data off Redis 7.2
ValkeyRedisValkeyRedisValkeyRedis
Claude Opus 5.53/33/33/33/33/33/3
GPT-6 Sol3/33/33/33/33/33/3
DeepSeek V4.1 Flash3/33/33/33/33/33/3
GLM-5.3-Flash3/33/33/33/33/33/3
MiMo-V2.6-Flash3/33/33/33/33/33/3
All five models15/1515/1515/1515/1515/1515/15

The graders were tested before the run. Every task fails on the untouched environment and on known wrong solutions (no invalidation, a per-process cache, brute-force search in Python, a copy that drops expiries, a new server left as a replica) and passes on a reference solution, for both products: 22 of 22 checks.

Moving off Redis 8, by model

The first migration started from Redis 7.2, the last release the two projects share, so replication just worked. We added a second wave from Redis 8.10, which is where people who upgraded now start. Before any agent ran, we checked the two standard paths on the same servers:

DUMP on Redis 8.10, RESTORE on Valkey 9.1, every type:
  (error) DUMP payload version or checksum are wrong

valkey-cli -p 6380 REPLICAOF <redis-8.10> 6379
  OK
  ...6 s later: master_link_status:down, keys on Valkey: 0
  log: Reconnecting to PRIMARY ... after failure  (repeats)

REPLICAOF says OK and never copies a key, so an agent that trusts the OK promotes an empty server. Valkey's own migration guide says so: Redis 7.4 and later write data files Valkey cannot read, and the guide does not cover another method. What remains is a copy key by key, by type, with key and field expiries, stream entries, consumer groups and their pending entries. Same five models, three attempts each, same grader as the first migration, plus per-field expiry on 40 hashes.

ModelExact copiesMedian tool callsMedian minutesRead the Valkey migration guideSaw the RESTORE version errorSpend
Claude Opus 5.53/3202.93/30/3$1.14
GPT-6 Sol3/3201.22/32/3$0.31
DeepSeek V4.1 Flash3/35570/33/3$0.07
GLM-5.3-Flash1/37246.70/33/3$0.42
MiMo-V2.6-Flash1/36460.80/33/3$0.27

Opus 5.5 and GPT-6 Sol read valkey.io's migration guide in 5 of their 6 attempts; the open-weight models read it in 0 of 9. 6 attempts tried to make Valkey accept Redis 8's binary payloads by rewriting the RDB version byte and recomputing the CRC64: strings and sorted sets went in, streams and hashes with field expiry did not, because Redis 8 renumbered those type codes. Of the four failed attempts, three ran out the 60-minute guard with nothing usable copied (one left the new server as a replica of Redis 8, waiting for a sync that cannot happen), and one used up the 3-million-token guard reverse-engineering the format and left a probe key in the production server it had been told not to change.

Two incompatibilities agents ran into
  1. Sorting KNN results works the opposite way on each server.

    Redis 8.10 returns KNN matches in no particular order unless the query sorts them, so agents sort on the distance alias: 12 of 15 Redis attempts shipped a search with SORTBY. valkey-search already returns matches nearest first, and rejects that SORTBY. 12 of 15 Valkey attempts tried it, and none of the 15 shipped it. Code carried from one server to the other either errors on Valkey or silently mis-orders results on Redis.

    FT.SEARCH kb_idx "*=>[KNN 5 @embedding $vec AS score]" PARAMS 2 vec <blob> SORTBY score DIALECT 2
    
    Redis 8.10   -> sorted by score
    Valkey 9.1   -> (error) Index field `score` does not exist
    
    Same query without SORTBY, 5 probes:
    Redis 8.10   -> 4 of 5 replies out of order, nearest match not first in 3
    Valkey 9.1   -> 5 of 5 replies nearest first
  2. The same Python reads one server's reply and breaks on the other's.

    redis-py 8.1 opens a RESP3 connection by default. On it, Redis 8.10 answers FT.SEARCH with a map, and valkey-search with the older flat array that most examples parse. 3 of 15 Redis attempts pinned protocol=2 to get the array back. redis-py's own ft().search() helper returns the raw reply on RESP3 for both servers, so code that reads result.docs breaks on either.

    redis.Redis().execute_command("FT.SEARCH", ...)   # redis-py 8.1, default RESP3
    
    Redis 8.10  {'total_results': 2, 'results': [{'id': 'kb:kb-0001', 'extra_attributes': {'score': '0', ...}}, ...]}
    Valkey 9.1  [2, 'kb:kb-0001', ['id', 'kb-0001', 'score', '0'], 'kb:kb-0621', [...]]
Same end state, different paths

Medians across all five models. Tool calls were close on every job. Tokens were not: semantic search used about 90k on Valkey against 55k on Redis, the migration from Redis 7.2 about 147k against 109k, while the cache job used fewer on Valkey (22k against 35k). Agents read the product's own docs in 11 of 15 Valkey search attempts and 10 of 15 Redis ones.

0 5 10 15 20 25 Cache job valkey: median 7 tool calls7 · Valkey redis: median 8 tool calls8 · Redis Semantic job valkey: median 18 tool calls18 · Valkey redis: median 17 tool calls17 · Redis Move job valkey: median 18 tool calls18 · Valkey redis: median 21 tool calls21 · Redis median tool calls per attempt (all five models)
Models, environment and rules

Models

  • Claude Opus 5.5 claude-opus-5-5 · Anthropic API, adaptive thinking, effort medium (API default)
  • GPT-6 Sol openai/gpt-6-sol · OpenRouter, provider-default reasoning
  • DeepSeek V4.1 Flash deepseek/deepseek-v4.1-flash · open weights, OpenRouter, provider default
  • GLM-5.3-Flash z-ai/glm-5.3-flash · open weights, OpenRouter, provider default
  • MiMo-V2.6-Flash xiaomi/mimo-v2.6-flash · open weights, OpenRouter, provider default

Environment

  • Valkey 9.1.2: image valkey/valkey-bundle:9.1.3 with its search, JSON and bloom modules loaded; migration target valkey/valkey:9.1.2
  • Redis 8.10.2: image redis:8.10.2 with its search, JSON, bloom and time-series modules loaded
  • Migration source: Redis 7.2.16 with 3,270 keys in two databases: every core type, 1,050 expiring keys, binary values, non-ASCII key names, streams with consumer groups and pending entries
  • Python clients preinstalled for both: redis 8.1.0, valkey 6.1.1; open network, the agent can install anything

Jobs

  • Cache. A storefront reads products from a 300 ms inventory service; add a shared cache in the provided server with a 5-minute expiry and fresh reads after a price change. Graded with reads in separate processes against the inventory service's request log.
  • Semantic search. Load 1,000 articles with 64-dimension embeddings and write a search script whose similarity search runs inside the server. Graded on 5 held-out queries, with the article file moved away and MONITOR watching for FT.SEARCH, FT.AGGREGATE or VSIM.
  • Migration. Copy everything from Redis 7.2 to the new server so it holds an exact copy and runs as a writable primary, without changing the old server. Graded key by key in both databases.
  • Migration off Redis 8 (wave 2). The same job from Redis 8.10.2 with the same dataset plus 40 hashes with per-field expiry, to Valkey 9.1.2 only. The pair to compare it with is the wave-1 migration from Redis 7.2.

Rules

  • The two prompts for a job differ only in the product's name, version and config path.
  • The agent gets a shell in the container and a documentation fetcher with open web access. No skills, MCP servers or runbooks.
  • No caps on steps or tokens. A runaway guard far above normal use (3M tokens, 500 tool calls, 60 minutes) is recorded if it fires.
  • n=3 per model, job and product; n=5 per model and selection prompt. With n this small, read the counts, not percentages.
  • Configuration, prompts, graders and images were frozen before the first record of each wave; wave 2 also stores every tool output the agent saw.
  • Spend for the whole study, both waves and the selection run: $8.58. Four models are metered by OpenRouter; Claude is usage at Anthropic list price.

Selection

  • Bare user prompt, no system prompt, one turn, provider-default sampling, as in Issue 1.
  • Coding reads code first (image, Terraform engine, install line; comments and fallback tips ignored), then a named managed service, then the line that states the choice.
  • Answers with mixed evidence were coded by hand, with the reason recorded next to each decision.
  • Two prompts name Python (the cache and the job queue); the other three name no language. The prompts differ in more than who asks, so the results show where Valkey wins, not why.