Unified Store Tools
Unified Store Tools
In v0.5.0, the 19 plugin-specific CRUD tools (memory_store, context_set, instructions_set, user_info_set, etc.) were replaced with 5 generic store_* tools that work across all stores. This reduces tool clutter, simplifies the LLM's decision-making, and makes it trivial to add new stores.
The 5 Generic Tools
| Tool | Signature | Description |
|---|---|---|
store_get |
store_get(store, key?) |
Read one value by exact key; omitting key returns a store-specific view, which may contain only metadata |
store_set |
store_set(store, key, data) |
Create or update an entry |
store_delete |
store_delete(store, key) |
Remove an entry by key |
store_list |
store_list(store, filter?) |
List entries with optional filters |
store_action |
store_action(store, action, params?) |
Store-specific operations (query, clear, etc.) |
The store parameter is a string identifying which store to target. The data parameter is an object whose shape depends on the store.
For "notes", a keyless store_get({ store: "notes" }) returns only keys,
descriptions, and tiers. Read each source's contents with
store_get({ store: "notes", key: "<exact index key>" }), including the displayed
tier prefix and any collision suffix. store_list discovers entries omitted from
the visible index. Other stores retain their own keyless behavior.
Available Stores
| Store | Feature Flag | Description | Data Shape for store_set |
|---|---|---|---|
"notes" |
workingMemory: true |
Tiered working memory (raw/summary/findings) | { description, value, tier?, priority? } |
"whiteboard" |
inContextMemory: true |
Key-value pairs visible directly in LLM context | { description, value, priority? } (showInUI is host-owned metadata; see below) |
"instructions" |
persistentInstructions: true |
Agent instructions persisted to disk | { content } |
"user_info" |
userInfo: true |
User-scoped preferences across agents | { value, description? } |
"workspace" |
sharedWorkspace: true |
Multi-agent coordination workspace | { summary, content?, references?, status?, tags? } |
When to Use Each Store
| Need | Store | Why |
|---|---|---|
| Large data, external retrieval | "notes" |
Index in context, full data via store_get |
| Small live state, instant access | "whiteboard" |
Full values rendered directly in context |
| Cross-session agent rules | "instructions" |
Persists to disk, auto-loaded on start |
| User preferences shared across agents | "user_info" |
User-scoped, not agent-scoped |
| Multi-agent data sharing | "workspace" |
Versioned entries with author tracking |
Migration from Old Tool Names
| Old Tool | New Equivalent |
|---|---|
memory_store(key, desc, value, ...) |
store_set("notes", key, { description, value, tier?, ... }) |
memory_retrieve(key) |
store_get("notes", key) |
memory_delete(key) |
store_delete("notes", key) |
memory_query(...) |
store_action("notes", "query", { pattern?, tier?, ... }) |
memory_cleanup_raw() |
store_action("notes", "cleanup_raw") |
context_set(key, desc, value, ...) |
store_set("whiteboard", key, { description, value, priority? }) |
context_delete(key) |
store_delete("whiteboard", key) |
context_list() |
store_list("whiteboard") |
instructions_set(key, content) |
store_set("instructions", key, { content }) |
instructions_remove(key) |
store_delete("instructions", key) |
instructions_list() |
store_list("instructions") |
instructions_clear(confirm) |
store_action("instructions", "clear", { confirm: true }) |
user_info_set(key, value, desc?) |
store_set("user_info", key, { value, description? }) |
user_info_get(key?) |
store_get("user_info", key?) |
user_info_remove(key) |
store_delete("user_info", key) |
user_info_clear(confirm) |
store_action("user_info", "clear", { confirm: true }) |
Note: TODO tools (
todo_add,todo_update,todo_remove) are unchanged.
Example Usage by Store
Memory Store
// Store data in working memory
// Tool call from LLM:
{
"name": "store_set",
"arguments": {
"store": "notes",
"key": "api_response",
"data": {
"description": "Full API response from /users endpoint",
"value": { "users": ["Alice", "Bob", "Charlie"] },
"tier": "findings",
"priority": "high"
}
}
}
// Retrieve data
{
"name": "store_get",
"arguments": {
"store": "notes",
"key": "api_response"
}
}
// Query memory entries
{
"name": "store_action",
"arguments": {
"store": "notes",
"action": "query",
"params": { "tier": "findings", "pattern": "api_*" }
}
}
// Clean up raw tier
{
"name": "store_action",
"arguments": {
"store": "notes",
"action": "cleanup_raw"
}
}
Context Store
// Store live state visible directly in context
{
"name": "store_set",
"arguments": {
"store": "whiteboard",
"key": "current_state",
"data": {
"description": "Processing state for current task",
"value": { "step": 3, "status": "active" },
"priority": "high"
}
}
}
// Delete an entry
{
"name": "store_delete",
"arguments": {
"store": "whiteboard",
"key": "temp_data"
}
}
// List all entries
{
"name": "store_list",
"arguments": {
"store": "whiteboard"
}
}
Instructions Store
// Set a persistent instruction
{
"name": "store_set",
"arguments": {
"store": "instructions",
"key": "personality",
"data": {
"content": "Always be friendly and helpful. Use clear, simple language."
}
}
}
// Remove an instruction
{
"name": "store_delete",
"arguments": {
"store": "instructions",
"key": "personality"
}
}
// Clear all instructions
{
"name": "store_action",
"arguments": {
"store": "instructions",
"action": "clear",
"params": { "confirm": true }
}
}
User Info Store
// Store user preference
{
"name": "store_set",
"arguments": {
"store": "user_info",
"key": "theme",
"data": {
"value": "dark",
"description": "User preferred theme"
}
}
}
// Get all user info
{
"name": "store_get",
"arguments": {
"store": "user_info"
}
}
// Clear all user info
{
"name": "store_action",
"arguments": {
"store": "user_info",
"action": "clear",
"params": { "confirm": true }
}
}
Creating a Custom Store Plugin
Any plugin that implements IContextPluginNextGen and IStoreHandler automatically becomes available as a store target. The IStoreHandler interface defines the CRUD operations:
// Documentation check: complete example
import {
BasePluginNextGen,
type IStoreHandler,
type StoreEntrySchema,
type StoreGetResult,
type StoreSetResult,
type StoreDeleteResult,
type StoreListResult,
type StoreActionResult,
} from 'oneringai';
class SnippetsPlugin extends BasePluginNextGen implements IStoreHandler {
readonly name = 'snippets';
private snippets = new Map<string, { text: string; createdAt: number }>();
getStoreSchema(): StoreEntrySchema {
return {
storeId: 'snippets',
displayName: 'Snippets',
description: 'Text snippets keyed by name',
usageHint: 'Use for: quick reusable text snippets.',
setDataFields: 'text (required): Snippet content',
};
}
// IStoreHandler implementation
async storeGet(key?: string): Promise<StoreGetResult> {
if (key) {
const snippet = this.snippets.get(key);
return snippet ? { found: true, key, entry: snippet } : { found: false, key };
}
// For this custom snippets store only, return all entries when key is omitted
const entries = Array.from(this.snippets.entries()).map(([k, v]) => ({ key: k, ...v }));
return { found: true, entries };
}
async storeSet(key: string, data: Record<string, unknown>): Promise<StoreSetResult> {
const text = data.text as string;
if (!text) return { success: false, key, error: 'Missing "text" field' };
this.snippets.set(key, { text, createdAt: Date.now() });
return { success: true, key, message: `Snippet "${key}" saved` };
}
async storeDelete(key: string): Promise<StoreDeleteResult> {
const deleted = this.snippets.delete(key);
return { deleted, key };
}
async storeList(filter?: Record<string, unknown>): Promise<StoreListResult> {
const entries = Array.from(this.snippets.entries()).map(([k, v]) => ({
key: k,
text: v.text,
createdAt: v.createdAt,
}));
return { entries, total: entries.length };
}
async storeAction(action: string, params?: Record<string, unknown>): Promise<StoreActionResult> {
if (action === 'clear') {
if (!params?.confirm) return { success: false, action, error: 'Requires confirm: true' };
this.snippets.clear();
return { success: true, action, message: 'All snippets cleared' };
}
return { success: false, action, error: `Unknown action: ${action}` };
}
// Standard plugin methods
getInstructions(): string | null { return 'Use store_set("snippets", key, { text }) to save text snippets.'; }
async getContent(): Promise<string | null> { return null; }
getContents(): unknown { return Object.fromEntries(this.snippets); }
getTools() { return []; } // No plugin-specific tools needed; store_* tools handle everything
}
Register and use:
const ctx = AgentContextNextGen.create({ model: 'gpt-4.1' });
ctx.registerPlugin(new SnippetsPlugin());
// Now the LLM can use:
// store_set("snippets", "meeting", { text: "Discussed Q3 roadmap" })
// store_get("snippets", "meeting")
// store_list("snippets")
// store_action("snippets", "clear", { confirm: true })