VoltAgent is an open source TypeScript framework for building and orchestrating AI agents.
Escape the limitations of no-code builders and the complexity of starting from scratch.
Escape the limitations of no-code builders and the complexity of starting from scratch.
This example demonstrates how to use Valkey as a distributed backing store for both A2A task persistence and resumable streaming in VoltAgent. It uses the @valkey/valkey-glide client library for high-performance access to Valkey (standalone or cluster).
- ValkeyTaskStore — Persists A2A task records to Valkey with configurable key prefixes and TTL-based expiration.
- ValkeyResumableStreamStore — Manages resumable streaming sessions via Valkey pub/sub and key-value operations.
- A minimal VoltAgent project with a
SupportAgentexposed over the A2A protocol, backed entirely by Valkey.
examples/with-valkey-store
├── src/
│ ├── agents/assistant.ts # Example agent definition
│ └── index.ts # VoltAgent bootstrap with Valkey stores
├── .env.example # Environment variable template
├── package.json
├── tsconfig.json
└── README.md
- Node.js 20+
pnpm- A running Valkey instance (or Redis-compatible server)
OPENAI_API_KEYin your environment
docker run -d --name valkey -p 6379:6379 valkey/valkey:8- Copy the environment template and fill in your keys:
cp .env.example .env- Install dependencies and start the dev server:
pnpm install
pnpm --filter voltagent-example-with-valkey-store devThe server listens on http://localhost:3141.
Environment variables:
| Variable | Default | Description |
|---|---|---|
OPENAI_API_KEY |
— | OpenAI API key for the example agent |
VALKEY_HOST |
localhost |
Valkey server hostname |
VALKEY_PORT |
6379 |
Valkey server port |
Both stores accept keyPrefix and ttlSeconds options:
// Task store — keys like "my-tasks:agentId::taskId"
const taskStore = await createValkeyTaskStore({
client: valkeyClient,
keyPrefix: "my-tasks",
ttlSeconds: 3600,
});
// Stream store — keys like "my-streams:active:userId-conversationId"
const streamStore = await createResumableStreamValkeyStore({
client: valkeyClient,
clientConfig: { addresses: [{ host: "localhost", port: 6379 }] },
keyPrefix: "my-streams",
ttlSeconds: 600,
});Both stores accept GlideClient or GlideClusterClient:
import { GlideClusterClient } from "@valkey/valkey-glide";
const clusterClient = await GlideClusterClient.createClient({
addresses: [
{ host: "node1.example.com", port: 6379 },
{ host: "node2.example.com", port: 6379 },
],
useTLS: true,
});
const taskStore = new ValkeyTaskStore({ client: clusterClient });# Fetch the agent card
curl http://localhost:3141/.well-known/supportagent/agent-card.json | jq
# Send a message
curl -X POST http://localhost:3141/a2a/supportagent \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "message/send",
"params": {
"message": {
"kind": "message",
"role": "user",
"messageId": "msg-1",
"parts": [{ "kind": "text", "text": "What time is it?" }]
}
}
}'- Adjust
ttlSecondsto match your retention requirements (or omit it for no expiration). - Use
GlideClusterClientfor production Valkey cluster deployments (e.g., AWS ElastiCache Valkey). - Add TLS by setting
useTLS: truein the client configuration.
Happy hacking! 🚀