Custom Storage — Agentuity Documentation

Custom Storage

Local development storage and custom runtime storage implementations

Agentuity uses local runtime storage when you are unauthenticated or when local mode is enabled, and managed runtime storage when your app runs with cloud credentials. You can override the runtime implementations for key-value, vector, and stream storage.

Local Development

During local development, KV, vector, and stream storage are backed by a local SQLite database and project-scoped by the project path. This happens automatically when you're not authenticated, or when you explicitly enable local mode:

import { createApp } from '@agentuity/runtime';
 
const app = await createApp({
  services: {
    useLocal: true,  // Force local storage even when authenticated
  },
});
 
export default app;

Local data is stored in ~/.config/agentuity/local.db, with stream buffers under ~/.config/agentuity/streams. It persists between runs without affecting cloud data.

Production

When deployed to Agentuity, your agents use managed KV, vector, and stream storage unless you pass custom implementations in createApp().

Custom Storage Implementations

You can replace runtime storage services with your own implementations. This is useful when you need to:

  • Use existing infrastructure: Connect to your company's Redis, Postgres, or vector database
  • Meet compliance requirements: Keep data in specific regions or systems
  • Self-host: Run entirely on your own infrastructure

Pass your implementation to createApp():

import { createApp } from '@agentuity/runtime';
import { MyRedisKV, MyPineconeVector } from './my-storage';
 
const app = await createApp({
  services: {
    keyvalue: new MyRedisKV(),
    vector: new MyPineconeVector(),
    // stream uses the Agentuity default
  },
});
 
export default app;

Storage Interfaces

Your implementation must satisfy the interface for the storage type you override. When your agent calls ctx.kv.get(), the SDK calls your implementation's get() method.

These interfaces are exported from @agentuity/core:

KeyValueStorage

interface KeyValueStorage {
  get<T>(name: string, key: string): Promise<DataResult<T>>;
  set<T = unknown>(
    name: string,
    key: string,
    value: T,
    params?: { ttl?: number | null; contentType?: string }
  ): Promise<void>;
  delete(name: string, key: string): Promise<void>;
  getStats(name: string): Promise<KeyValueStats>;
  getAllStats(
    params?: GetAllStatsParams
  ): Promise<Record<string, KeyValueStats> | KeyValueStatsPaginated>;
  getNamespaces(): Promise<string[]>;
  search<T = unknown>(
    name: string,
    keyword: string
  ): Promise<Record<string, KeyValueItemWithMetadata<T>>>;
  getKeys(name: string): Promise<string[]>;
  deleteNamespace(name: string): Promise<void>;
  createNamespace(name: string, params?: CreateNamespaceParams): Promise<void>;
}

VectorStorage

interface VectorStorage {
  upsert(name: string, ...documents: VectorUpsertParams[]): Promise<VectorUpsertResult[]>;
  get<T extends Record<string, unknown> = Record<string, unknown>>(
    name: string,
    key: string
  ): Promise<VectorResult<T>>;
  getMany<T extends Record<string, unknown> = Record<string, unknown>>(
    name: string,
    ...keys: string[]
  ): Promise<Map<string, VectorSearchResultWithDocument<T>>>;
  search<T extends Record<string, unknown> = Record<string, unknown>>(
    name: string,
    params: VectorSearchParams<T>
  ): Promise<VectorSearchResult<T>[]>;
  delete(name: string, ...keys: string[]): Promise<number>;
  exists(name: string): Promise<boolean>;
  getStats(name: string): Promise<VectorNamespaceStatsWithSamples>;
  getAllStats(
    params?: VectorGetAllStatsParams
  ): Promise<Record<string, VectorNamespaceStats> | VectorStatsPaginated>;
  getNamespaces(): Promise<string[]>;
  deleteNamespace(name: string): Promise<void>;
}

StreamStorage

interface StreamStorage {
  create(namespace: string, props?: CreateStreamProps): Promise<Stream>;
  get(id: string): Promise<StreamInfo>;
  download(id: string): Promise<ReadableStream<Uint8Array>>;
  list(params?: ListStreamsParams): Promise<ListStreamsResponse>;
  delete(id: string): Promise<void>;
}

Next Steps