Skip to main content

AI Agent Memory

Use Arc Cloud as a persistent memory layer for AI agents and chatbots -- fast retrieval, SQL flexibility, and structured conversation storage.

Why Arc Cloud for AI Agents

AI agents need persistent memory that goes beyond in-memory context windows. Arc Cloud provides:

  • Fast Retrieval: Sub-second SQL queries to fetch relevant conversation history
  • SQL Flexibility: Query by session, time range, content keywords, role, or any custom metadata
  • Persistent Storage: Conversations survive restarts, deployments, and scaling events
  • Schema Flexibility: Store structured metadata alongside conversation content
  • Scalable: Handle millions of messages across thousands of sessions
  • Integration with Memtrace: Use Memtrace for higher-level memory abstractions built on Arc

Schema Design

Conversation History Schema

Conversations map to a messages measurement with tags for indexed lookups and fields for content:

ColumnTypeDescription
timetimestamp (ns)When the message was created
session_idtagConversation session identifier
roletagsystem, user, assistant, or tool
contentfield (string)Message text content
message_idfield (string)Unique message identifier
modelfield (string)LLM model used (e.g., claude-sonnet-4-20250514)
tokens_infield (integer)Input token count
tokens_outfield (integer)Output token count
metadatafield (string)JSON-encoded additional context (tool calls, user info, tags)

Memory/Knowledge Schema

For agent long-term memory and learned facts, use a memories measurement:

ColumnTypeDescription
timetimestamp (ns)When the memory was stored
agent_idtagAgent that created this memory
categorytagMemory type: fact, preference, instruction, summary
contentfield (string)The memory content
memory_idfield (string)Unique memory identifier
source_sessionfield (string)Session that originated this memory
relevance_scorefield (float)Agent-assigned importance (0.0 to 1.0)

Storing Conversation History

Line Protocol (curl)

Store each message as it occurs in the conversation:

curl -X POST "https://<instance-id>.arc.<region>.basekick.net/api/v1/write/line-protocol?db=ai_memory" \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: text/plain" \
-d 'messages,session_id=sess_abc123,role=user content="What were our Q1 revenue numbers?",message_id="msg_001",metadata="{\"user_id\":\"u_8f3k2\",\"channel\":\"slack\"}" 1711195200000000000
messages,session_id=sess_abc123,role=assistant content="Based on the data I have access to, Q1 revenue was $2.4M, up 18% from last quarter.",message_id="msg_002",model="claude-sonnet-4-20250514",tokens_in=1250i,tokens_out=340i,metadata="{\"tool_calls\":[\"query_revenue_db\"],\"confidence\":0.95}" 1711195202000000000'

Storing Long-Term Memories

curl -X POST "https://<instance-id>.arc.<region>.basekick.net/api/v1/write/line-protocol?db=ai_memory" \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: text/plain" \
-d 'memories,agent_id=agent_support_01,category=fact content="User u_8f3k2 prefers Python for data pipelines",memory_id="mem_001",source_session="sess_abc123",relevance_score=0.9 1711195200000000000
memories,agent_id=agent_support_01,category=preference content="User u_8f3k2 prefers concise answers",memory_id="mem_002",source_session="sess_abc123",relevance_score=0.85 1711195200000000000'

Python SDK Integration

from arc_tsdb_client import ArcClient
from datetime import datetime

class ArcMemory:
"""Persistent memory store for AI agents using Arc Cloud."""

def __init__(self, arc_url: str, arc_token: str, database: str = "ai_memory"):
self.client = ArcClient(
url=arc_url,
token=arc_token,
database=database,
)

def store_message(self, session_id: str, role: str, content: str, **kwargs):
"""Store a single message in conversation history."""
fields = {"content": content}
fields.update(kwargs)

self.client.write(
measurement="messages",
tags={"session_id": session_id, "role": role},
fields=fields,
)

def store_memory(self, agent_id: str, category: str, content: str, **kwargs):
"""Store a long-term memory or learned fact."""
fields = {"content": content}
fields.update(kwargs)

self.client.write(
measurement="memories",
tags={"agent_id": agent_id, "category": category},
fields=fields,
)

def get_recent_messages(self, session_id: str, limit: int = 20) -> list:
"""Retrieve recent messages from a session."""
result = self.client.query(
sql=f"""
SELECT role, content, time
FROM ai_memory.messages
WHERE session_id = '{session_id}'
ORDER BY time DESC
LIMIT {limit}
""",
format="json",
)
result.reverse() # Return in chronological order
return result

def search_by_content(self, keywords: str, limit: int = 10) -> list:
"""Search across all sessions for messages matching keywords."""
return self.client.query(
sql=f"""
SELECT session_id, role, content, time
FROM ai_memory.messages
WHERE content ILIKE '%{keywords}%'
ORDER BY time DESC
LIMIT {limit}
""",
format="json",
)

def get_time_window(self, session_id: str, hours: int = 24) -> list:
"""Retrieve messages from a session within a time window."""
return self.client.query(
sql=f"""
SELECT role, content, time
FROM ai_memory.messages
WHERE session_id = '{session_id}'
AND time > NOW() - INTERVAL '{hours} hours'
ORDER BY time ASC
""",
format="json",
)

def get_agent_memories(self, agent_id: str, category: str = None, limit: int = 50) -> list:
"""Retrieve long-term memories for an agent."""
where_clause = f"WHERE agent_id = '{agent_id}'"
if category:
where_clause += f" AND category = '{category}'"

return self.client.query(
sql=f"""
SELECT category, content, relevance_score, time
FROM ai_memory.memories
{where_clause}
ORDER BY relevance_score DESC, time DESC
LIMIT {limit}
""",
format="json",
)

Retrieving Context

Query your data using SQL via the /api/v1/query endpoint:

curl -X POST "https://<instance-id>.arc.<region>.basekick.net/api/v1/query" \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: application/json" \
-d '{"sql": "SELECT role, content, time FROM ai_memory.messages WHERE session_id = '\''sess_abc123'\'' ORDER BY time DESC LIMIT 20", "format": "json"}'

Recent Messages for a Session

SELECT role, content, time
FROM ai_memory.messages
WHERE session_id = 'sess_abc123'
ORDER BY time DESC
LIMIT 20;

Search by Content

Find all messages mentioning a topic across sessions:

SELECT session_id, role, content, time
FROM ai_memory.messages
WHERE content ILIKE '%revenue%'
ORDER BY time DESC
LIMIT 20;

Time-Windowed Retrieval

Get the last 24 hours of conversation for a session:

SELECT role, content, time
FROM ai_memory.messages
WHERE session_id = 'sess_abc123'
AND time > NOW() - INTERVAL '24 hours'
ORDER BY time ASC;

Session Summary

Get a high-level view of all sessions for a user:

SELECT
session_id,
MIN(time) AS started_at,
MAX(time) AS last_message_at,
COUNT(*) AS message_count,
COUNT(*) FILTER (WHERE role = 'user') AS user_messages,
COUNT(*) FILTER (WHERE role = 'assistant') AS assistant_messages
FROM ai_memory.messages
WHERE metadata ILIKE '%u_8f3k2%'
GROUP BY session_id
ORDER BY last_message_at DESC;

Agent Memory Retrieval

Fetch learned facts and preferences for context injection:

SELECT category, content, relevance_score
FROM ai_memory.memories
WHERE agent_id = 'agent_support_01'
AND category IN ('fact', 'preference')
AND relevance_score > 0.7
ORDER BY relevance_score DESC
LIMIT 10;

Integration with Memtrace

Memtrace is Basekick Labs' structured AI memory system built on top of Arc. It provides higher-level abstractions for managing agent memory:

  • Session management with automatic context windowing
  • Memory extraction that identifies and stores key facts from conversations
  • Relevance ranking for memory retrieval
  • Multi-agent memory sharing across agent instances

If you need more than raw SQL queries for memory management, Memtrace adds a structured layer on top of Arc Cloud.

from memtrace import MemtraceClient

client = MemtraceClient(
arc_url="https://<instance-id>.arc.<region>.basekick.net",
arc_token="<your-token>",
)

# Store a conversation turn with automatic memory extraction
client.add_message(
session_id="sess_abc123",
role="user",
content="My preferred language is Python and I work on data pipelines.",
)

# Memtrace automatically extracts and stores:
# - fact: "User prefers Python"
# - fact: "User works on data pipelines"

# Retrieve relevant memories for context injection
memories = client.recall(agent_id="agent_01", query="coding preferences", limit=5)

See the Memtrace documentation for setup instructions, SDK reference, and integration guides.

Example: Chatbot with Persistent Memory

A complete example of a chatbot that stores conversation history in Arc Cloud and uses it to maintain context across sessions.

from arc_tsdb_client import ArcClient
from datetime import datetime
import time

ARC_URL = "https://<instance-id>.arc.<region>.basekick.net"
ARC_TOKEN = "<your-token>"

client = ArcClient(url=ARC_URL, token=ARC_TOKEN, database="ai_memory")

def get_context(session_id: str, max_messages: int = 10) -> list:
"""Fetch recent conversation history for context."""
rows = client.query(
sql=f"""
SELECT role, content
FROM ai_memory.messages
WHERE session_id = '{session_id}'
ORDER BY time DESC
LIMIT {max_messages}
""",
format="json",
)
rows.reverse()
return [{"role": m["role"], "content": m["content"]} for m in rows]

def store_message(session_id: str, role: str, content: str, **extra):
"""Persist a message to Arc Cloud."""
fields = {"content": content}
fields.update(extra)

client.write(
measurement="messages",
tags={"session_id": session_id, "role": role},
fields=fields,
)

def chat(session_id: str, user_message: str) -> str:
"""Process a user message with full conversation context."""
# 1. Store user message
store_message(session_id, "user", user_message)

# 2. Retrieve context from Arc Cloud
history = get_context(session_id)

# 3. Call your LLM with the full context
response = call_llm(messages=history)

# 4. Store assistant response
store_message(
session_id, "assistant", response,
model="claude-sonnet-4-20250514",
tokens_in=len(user_message.split()),
tokens_out=len(response.split()),
)

return response

# Usage
session = f"sess_{int(time.time())}"
reply = chat(session, "Hello! Can you help me with Python data pipelines?")
print(reply)

# Later, in a new process, the context is still available
reply = chat(session, "What libraries would you recommend?")

Next Steps