Use vector storage when exact keys or SQL filters are not enough, for example knowledge search, RAG retrieval, recommendations, or long-lived memory. Start with VectorClient; Hono apps can use c.var.vector after installing the Agentuity middleware.
npm install @agentuity/vectorimport { VectorClient } from '@agentuity/vector';
const vector = new VectorClient();
await vector.upsert(
'docs',
{
key: 'deploy-guide',
document: 'Deploy framework apps to Agentuity with agentuity deploy.',
metadata: { category: 'guide', source: 'docs' },
},
{
key: 'service-clients',
document: 'Agentuity services can be used through dedicated client packages.',
metadata: { category: 'api', source: 'docs' },
}
);
const results = await vector.search('docs', {
query: 'How do I use Agentuity services from my app?',
limit: 3,
similarity: 0.7,
});VectorClient reads AGENTUITY_SDK_KEY, then AGENTUITY_CLI_KEY, from the environment. Agentuity project code can keep that key in .env for local development and deployed environments can receive it through project environment configuration.
When to use vector storage
| Need | Use |
|---|---|
| semantic search or RAG retrieval | Vector |
| exact key lookup | Key-Value |
| relational joins or transactions | Database |
| files or binary data | Object Storage |
| append-only ordered data | Durable Streams |
Upsert Data
Pass document when you want Agentuity to generate embeddings. Pass embeddings when you already have vectors from another model.
await vector.upsert('products', {
key: 'chair-001',
document: 'Ergonomic office chair with lumbar support',
metadata: { category: 'furniture', source: 'catalog' },
ttl: 60 * 60 * 24 * 90,
});
await vector.upsert('custom-embeddings', {
key: 'embedding-001',
embeddings: [0.12, 0.34, 0.56, 0.78],
metadata: { source: 'external-model' },
ttl: null,
});The operation is idempotent by key: upserting the same key updates the stored vector.
TTL
Vectors expire after 30 days unless you pass ttl.
| Value | Behavior |
|---|---|
| omitted | expire after 30 days |
null or 0 | never expire |
>= 60 | expire after that many seconds |
Managed vector storage clamps TTL values below 60 seconds to 60 seconds and values above 90 days to 90 days.
Search
Search accepts a natural-language query, optional result limit, optional similarity threshold, and optional metadata filter.
const furniture = await vector.search('products', {
query: 'comfortable seating for a desk',
limit: 5,
similarity: 0.65,
metadata: { category: 'furniture', source: 'catalog' },
});
const rankedKeys = furniture.map((result) => result.key);Search results include id, key, similarity, optional metadata, and optional expiresAt.
You can pass document and let Agentuity embed text, or pass embeddings from your own model. Keep a namespace on one embedding strategy so similarity scores remain comparable.
Type-Safe Metadata
get(), getMany(), and search() accept a metadata generic. The constraint is Record<string, unknown>, so define metadata types as a type intersection or as an interface that extends the record.
type ProductMetadata = {
readonly category: 'furniture' | 'electronics';
readonly source: string;
} & Record<string, unknown>;
const typed = await vector.search<ProductMetadata>('products', {
query: 'comfortable seating for a desk',
metadata: { category: 'furniture', source: 'catalog' },
});
const document = await vector.get<ProductMetadata>('products', 'chair-001');
if (document.exists) {
const category = document.data.metadata?.category;
void category;
}Retrieve and Delete
Use get() when you already know the key, getMany() for batches, and delete() when you want to remove one or more vectors.
const document = await vector.get('products', 'chair-001');
if (document.exists) {
const metadata = document.data.metadata;
}
const batch = await vector.getMany('products', 'chair-001', 'desk-001');
const deleted = await vector.delete('products', 'chair-001', 'desk-001');Namespaces and Stats
Vector namespaces are created on first upsert. Use stats and namespace methods to inspect or clean up stored data.
const hasProducts = await vector.exists('products');
const stats = await vector.getStats('products');
const allStats = await vector.getAllStats({ limit: 25, sort: 'size' });
const namespaces = await vector.getNamespaces();
await vector.deleteNamespace('old-products');getStats() returns sum (bytes), count, optional createdAt/lastUsed, and sampledResults with up to 20 vectors and their embeddings. Use the samples for quick inspection without running a search.
deleteNamespace() permanently removes the namespace and all vectors inside it.
Local vector storage is useful for development and API-shape checks. Validate embedding quality, ranking, and TTL behavior against the managed vector service before relying on search relevance.
Hono
In Hono apps, @agentuity/hono initializes VectorClient once and exposes it on c.var.vector.
npm install @agentuity/hono honoimport { Hono } from 'hono';
import { agentuity } from '@agentuity/hono';
import type { Services } from '@agentuity/hono';
type Variables = Pick<Services, 'vector'>;
const app = new Hono<{ Variables: Variables }>();
app.use('*', agentuity());
app.get('/search', async (c) => {
const query = c.req.query('q');
if (!query) {
return c.json({ error: 'Missing q query parameter' }, 400);
}
const results = await c.var.vector.search('docs', {
query,
limit: 5,
});
return c.json({ results });
});
export default app;Next Steps
- Key-Value Storage: store exact-key cache and state
- Database: store relational data with SQL and transactions
- Agents: use retrieved context in a model-backed workflow
- Vector API Reference: inspect REST fields and lower-level method details