Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.emergence.ai/llms.txt

Use this file to discover all available pages before exploring further.

Memory Integration

This guide shows how to integrate the platform Memory Service into your agents and workflows. Memory lets agents remember information across sessions, accumulate domain knowledge, and personalize responses.

Prerequisites

  • A valid JWT token from the platform (user or service account)
  • The JWT must contain an org_id claim for organization scoping

Basic Integration Pattern

The most common integration pattern is:
  1. Before responding, search memories for relevant context
  2. After responding, extract and store new memories from the conversation
import httpx

API_BASE = "https://api.example.com/v2/api"

async def agent_respond(user_message: str, token: str, pack_id: str) -> str:
    headers = {"Authorization": f"Bearer {token}"}

    async with httpx.AsyncClient() as client:
        # Step 1: Search for relevant memories (two-phase search)
        search_resp = await client.post(
            f"{API_BASE}/search/retrieve",
            headers=headers,
            json={
                "context_pack_id": pack_id,
                "query": user_message,
                "limit": 5,
            },
        )
        memories = search_resp.json()

        # Step 2: Build context from memories
        context = "\n".join(f"- {m['content']}" for m in memories)

        # Step 3: Call LLM with memory context
        prompt = f"Relevant context:\n{context}\n\nUser: {user_message}"
        response = await call_llm(prompt)

        # Step 4: Store new memories from this interaction
        if should_memorize(user_message, response):
            await client.post(
                f"{API_BASE}/memories",
                headers=headers,
                json={
                    "content": extract_memorable_fact(user_message, response),
                    "memory_type": "fact",
                    "context_pack_id": pack_id,
                },
            )

    return response

Storing Memories

The following snippets show individual API calls. In an async agent, wrap them in async with httpx.AsyncClient() as client: and use await client.post(...) / await client.get(...) as shown in the integration pattern above.

Basic Memory Creation

# Store a user preference
await client.post(
    f"{API_BASE}/memories",
    headers=headers,
    json={
        "content": "User prefers metric definitions before SQL queries",
        "memory_type": "preference",
        "name": "metric_explanation_style",
        "context_pack_id": pack_id
    }
)

Memory Types

Choose the type based on the nature of the information:
TypeWhen to useExample
factFactual knowledge”The orders table has 50M rows”
experienceLearned behaviors”Query optimization worked better with CTEs”
observationObserved patterns”Revenue spikes every Q4”
instructionDirectives / guidelines”Always include date filters for large tables”
preferenceUser/system preferences”Prefers concise output without verbose explanations”
summaryCondensed summaries”Session covered revenue analysis across 3 regions”
glossaryBusiness terms”ARR = Annual Recurring Revenue”
joinTable relationships”Table orders has FK to customers
ontologyDomain classifications”Column status uses enum: active, inactive, churned”
policyGovernance rules”PII columns must not appear in SQL results”
textual_patternText patterns in data”Email column matches a standard email regex pattern”
kpiKPI definitions”Churn Rate = lost customers / total customers x 100”
exemplarRepresentative examples”Typical order: id=1234, amount=49.99, status=completed”
numeric_patternNumeric distributions”Revenue column: mean=1250, median=980, stddev=450”

Named Memories

Use name for memories you want to retrieve directly (without semantic search):
# Store with a name for direct retrieval
await client.post(
    f"{API_BASE}/memories",
    headers=headers,
    json={
        "content": "User's primary data source is Snowflake, database: analytics_prod",
        "memory_type": "fact",
        "name": "user_data_source_primary",
        "context_pack_id": pack_id
    }
)

# Retrieve by ID
response = await client.get(
    f"{API_BASE}/memories/{memory_id}",
    headers=headers,
)

Searching Memories

The Memory Service uses a two-phase search pattern:

Phase 1: Discover Context Packs

Find which context packs contain relevant memories:
response = await client.post(
    f"{API_BASE}/search/discover",
    headers=headers,
    json={
        "query": "database schema information",
        "limit": 5
    }
)
packs = response.json()
for pack in packs:
    print(f"Pack: {pack['name']} (score: {pack.get('score', 'N/A')})")

Phase 2: Retrieve Memories from a Pack

Once you know the relevant pack, retrieve specific memories:
response = await client.post(
    f"{API_BASE}/search/retrieve",
    headers=headers,
    json={
        "context_pack_id": pack_id,
        "query": "database schema information",
        "limit": 10
    }
)
memories = response.json()

for memory in memories:
    print(f"[{memory['memory_type']}] {memory['content']}")
    print(f"  Score: {memory.get('score', 'N/A')}")

Context Packs

For more structured memory management, use Context Packs to group related memories:
# Create a domain knowledge pack
pack_resp = await client.post(
    f"{API_BASE}/context-packs",
    headers=headers,
    json={
        "name": "user_data_domain",
        "type": "domain",
        "description": "User's data domain knowledge: schema, metrics, business rules"
    }
)
pack_id = pack_resp.json()["id"]

# Add a memory to the pack
await client.post(
    f"{API_BASE}/memories",
    headers=headers,
    json={
        "content": "Revenue metric = sum of completed order amounts, excluding refunds",
        "memory_type": "fact",
        "context_pack_id": pack_id
    }
)

# Search the pack for relevant memories
response = await client.post(
    f"{API_BASE}/search/retrieve",
    headers=headers,
    json={
        "context_pack_id": pack_id,
        "query": "revenue metric definition",
        "limit": 3
    }
)
memories = response.json()

Updating and Deleting

Update a Memory

# When a fact changes, update rather than delete
await client.patch(
    f"{API_BASE}/memories/{memory_id}",
    headers=headers,
    json={
        "content": "User's primary data source is BigQuery, project: analytics_prod (migrated from Snowflake)",
        "metadata": {"updated_reason": "user confirmed migration completed"}
    }
)

Delete a Memory

# Remove incorrect or outdated memories
await client.delete(
    f"{API_BASE}/memories/{memory_id}",
    headers=headers
)

Best Practices

Each memory should make sense without knowing the conversation that produced it. Instead of “Yes, that’s right” store “User confirmed that the ‘revenue’ column uses gross revenue, not net.”
Typed memories retrieve more accurately. If you know a memory is a preference, mark it preference, use specific types for better retrieval.
Before creating a new memory, search for existing ones that might cover the same information. Update existing memories rather than creating duplicates.
For domain-specific knowledge bases (data dictionaries, business rules, entity relationships), group memories into typed Context Packs. This improves retrieval precision and enables pack-level operations.
Memories are scoped by the org_id claim in the JWT token. Ensure each agent uses a token scoped to the correct organization to prevent information leakage.

Memory Service

Concepts overview and API reference.

Context Packs

Detailed Context Pack architecture and management.