NewRelease 0.12.3 is out: Engine v0.12.3, Dashboard 0.5.2, Helm 0.12.3, the four SDKs, CLI 0.8.2 and MCP 0.12.3Release 0.12.3 is outSee what's new →
Advanced Lifecycle

Memory Compression

⏰ ~35 min to implement 📦 Requires: Dakera v0.11+

Compress high-volume memory stores by clustering related memories, summarizing each cluster with an LLM, and replacing the verbose originals with compact canonical representations. Maintain recall quality while the agent keeps far fewer memories.

Start Free →
Prerequisites
  • Running Dakera server (Quickstart)
  • An agent ID with 500+ accumulated memories
  • LLM client (OpenAI, Anthropic) for cluster summarization
  • Familiarity with batch operations and scheduled jobs

The Problem: Memory Stores That Grow Faster Than They Age

An analytics agent processing daily reports stores 50–200 new memories per day. Over three months, that is 4,500–18,000 memories. Decay lowers the importance of memories nobody uses, but it never deletes anything, and many of these are legitimately important in the short term. The result: a bloated memory store where recall latency climbs, context windows overflow, and storage costs grow linearly with agent runtime.

Deduplication removes near-exact copies. Decay pushes unused entries down the ranking. But neither handles the class of memories that are individually distinct and important, but collectively redundant at a higher level of abstraction. A week of daily "DAU increased 3.2%" reports is seven distinct facts, but they can be compressed into one: "DAU grew 3.1% average over the week of May 13." Memory compression operates at this higher level.

Compression vs. Deduplication vs. Decay

Decay lowers the importance of unused memories over time (it never deletes them). Deduplication merges near-identical memories. Compression clusters semantically related memories (even if distinct) and replaces them with a denser, higher-level summary. Use all three together for maximum memory hygiene: decay → dedup → compress, in that order.

Architecture: Cluster, Summarize, Replace

The compression pipeline runs in three stages. First, your job lists the raw memories of one past time window (below importance 0.8, so earlier summaries are left alone) and groups them into clusters: by a shared tag or metric, or by semantic similarity on embeddings it computes (recall results carry text, not vectors). Second, each cluster is passed to an LLM for summarization; the output is a single, dense canonical memory that preserves the key facts from all cluster members. Third, the canonical summary is stored at high importance and the originals in the cluster are deleted, or demoted to importance 0.08 when you need an audit trail. Dakera stores, lists and deletes the memories; clustering, the LLM call and validation run in your job.

What Dakera can do server-side

POST /v1/agents/{id}/compress (compress_agent() in Python, compressAgent() in TypeScript) runs a compression pass for an agent; from v0.12.2 each summary is validated before it is written, and a refused one is listed in summaries_skipped with its cluster's originals kept. POST /v1/knowledge/summarize turns memories you choose into one summary memory. AutoPilot, on by default, also merges groups of three or more memories that share at least two tags and are all below importance 0.3, every 12 hours. Build the pipeline on this page when you need control over clustering, the prompt and validation.

Diagram: Before and After Compression

Data flow of an analytics store before and after compression. Before, it holds raw DAU memories (19 day records at importance 0.55 to 0.65), daily revenue memories (0.60) and weekly churn memories (0.58). An LLM summary per cluster, covering May 13 to 31, replaces them with three memories: DAU SUMMARY (0.90, cluster-dau), REVENUE SUMMARY (0.88, cluster-revenue) and CHURN SUMMARY (0.87, cluster-churn). A recall for DAU trend now returns one memory instead of 19 day records.Data flow of an analytics store before and after compression. Before, it holds raw DAU memories (19 day records at importance 0.55 to 0.65), daily revenue memories (0.60) and weekly churn memories (0.58). An LLM summary per cluster, covering May 13 to 31, replaces them with three memories: DAU SUMMARY (0.90, cluster-dau), REVENUE SUMMARY (0.88, cluster-revenue) and CHURN SUMMARY (0.87, cluster-churn). A recall for DAU trend now returns one memory instead of 19 day records.
Three dense summaries replace weeks of day-level records.Full size ↗Full size ↗

Diagram: Compression Pipeline

Workflow of one compression run. A trigger (a schedule or the store size, at most weekly) starts the job, which lists one past window of raw memories with batch_recall(): created more than 30 days ago and below importance 0.8. The job groups them by metric or by similarity; clusters with fewer than 3 members are left as they are. The LLM summarizes each cluster, keeping numbers, dates and the range. The job checks that every value appears in the inputs and retries the LLM if not. store_memory() saves the summary at importance 0.85 to 0.92 with no TTL and the compressed tag, and the originals are deleted with forget, or demoted to 0.08.Workflow of one compression run. A trigger (a schedule or the store size, at most weekly) starts the job, which lists one past window of raw memories with batch_recall(): created more than 30 days ago and below importance 0.8. The job groups them by metric or by similarity; clusters with fewer than 3 members are left as they are. The LLM summarizes each cluster, keeping numbers, dates and the range. The job checks that every value appears in the inputs and retries the LLM if not. store_memory() saves the summary at importance 0.85 to 0.92 with no TTL and the compressed tag, and the originals are deleted with forget, or demoted to 0.08.
Cluster, summarize, validate, then replace the originals.Full size ↗Full size ↗

Real-World Scenario: Analytics Agent Compressing Weeks of Data

Scenario: MetricsMind AI builds an analytics agent that monitors SaaS KPIs. The agent stores one memory per metric per day: DAU, revenue, churn, NPS, support tickets. With 8 metrics tracked daily (those five and three more), it accumulates 240 memories per month. After 3 months: 720 raw data-point memories. Recall for "revenue trend Q1" returns dozens of individual day-level facts, overwhelming the context window.

MetricsMind runs monthly compression. The pipeline clusters memories by metric type (cluster A: all DAU memories, cluster B: all revenue memories, etc.), then calls GPT-4o to summarize each cluster: "DAU grew from 12,400 to 15,200 over Q1 (+22.6%), with a 3-day dip in week 8 due to a login outage." Each month's 240 day-level memories compress to 8 cluster summaries, one per metric; with the originals deleted, that is 97% fewer memories for the month. Recall for any metric now returns one clean, human-readable trend summary.

Step-by-Step Implementation

  1. Set up the compression trigger
    Define when compression runs: on a schedule (weekly/monthly), when memory count exceeds a threshold (e.g., 500 agent memories), or after batch ingestion. For analytics agents, monthly compression after the end-of-month data export is the natural trigger. Do not run compression more than weekly — it is computationally expensive.
  2. Retrieve all candidate memories
    List the window with filter-based batch recall (POST /v1/memories/recall/batch, batch_recall()): no query and no embedding, filtered by tags, importance and creation time (created_after, created_before). Take memories created more than 30 days ago and below importance 0.8: summaries from previous runs (0.85–0.92) are excluded because they are already compressed.
  3. Cluster by semantic similarity
    Group the memories into clusters. Structured data points group by a shared tag or metric, as in the example below. Free-text memories need semantic similarity: compute embeddings with your own model (recall results carry text, not vectors), then for small stores (<500) use greedy clustering (sim > 0.78) and for large ones k-means. Target cluster sizes of 5–30 memories.
  4. Summarize each cluster with an LLM
    For each cluster, pass all member contents to an LLM with a structured summarization prompt. The prompt should instruct the LLM to: preserve all quantitative values (numbers, percentages, dates), identify the time range covered, and produce a single dense paragraph. Validate that the output is non-empty and that every number in it appears in the inputs before storing.
  5. Store compressed summaries at high importance
    Store each cluster summary at importance 0.85–0.92 with tags ["compressed", "cluster-{uuid}", "range-{start}-{end}"]. The range tags enable targeted retrieval (e.g., recall only Q1 summaries). Set no TTL — compressed summaries are the permanent record.
  6. Demote originals to trigger decay
    Use forget (POST /v1/memory/forget takes a list of IDs) for hard delete, or update_importance to set each original to importance 0.08. Soft demotion is preferred when audit requirements exist. Hard delete is appropriate for analytics data where raw day-level points are no longer needed after compression.

Before & After: Analytics Memory Store

Before compression — 6 raw memories (excerpt)
[
  { "id": "m-001", "content": "DAU: 12,421 on May 13",
    "importance": 0.55, "tags": ["dau", "daily"] },
  { "id": "m-002", "content": "DAU: 12,509 on May 14",
    "importance": 0.55, "tags": ["dau", "daily"] },
  { "id": "m-003", "content": "DAU: 12,388 on May 15 (login outage)",
    "importance": 0.65, "tags": ["dau", "daily", "incident"] },
  { "id": "m-004", "content": "Revenue: $48,220 on May 13",
    "importance": 0.60, "tags": ["revenue", "daily"] },
  { "id": "m-005", "content": "Revenue: $49,100 on May 14",
    "importance": 0.60, "tags": ["revenue", "daily"] },
  { "id": "m-006", "content": "Churn: 2.08% week of May 13",
    "importance": 0.58, "tags": ["churn", "weekly"] },
  // ... more similar memories
]
// recall("DAU trend") returns individual day records
// (19 DAU points from May 13 to 31)
// context window filled with raw data points
After compression — 3 summaries
[
  {
    "id": "m-comp-dau-001",
    "content": "DAU SUMMARY May 13-31: avg 12,890/day, peak 13,420 (May 29), low 12,388 (May 15, login outage). Growth +3.8% vs prior period.",
    "importance": 0.90,
    "tags": ["compressed", "cluster-dau", "range-may13-may31", "dau"]
  },
  {
    "id": "m-comp-rev-001",
    "content": "REVENUE SUMMARY May 13-31: avg $48,980/day, total $930,620. Steady +0.95%/day trend. No anomalies.",
    "importance": 0.88,
    "tags": ["compressed", "cluster-revenue", "range-may13-may31", "revenue"]
  },
  {
    "id": "m-comp-churn-001",
    "content": "CHURN SUMMARY May wk2-wk4: stable at 2.1% avg. Slight uptick 2.3% week of May 20 (investigated, no root cause). Within target.",
    "importance": 0.87,
    "tags": ["compressed", "cluster-churn", "range-may13-may31", "churn"]
  }
]
// recall("DAU trend") returns m-comp-dau-001 only
// Full month's insight in one clean memory

Implementation

# 1. List one past window of raw analytics memories (filter-based, no query)
#    created_after / created_before are Unix seconds
curl -X POST http://localhost:3000/v1/memories/recall/batch \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "analytics-bot",
    "filter": {
      "tags": ["daily", "weekly"],
      "max_importance": 0.8,
      "created_after": 1747094400,
      "created_before": 1748736000
    },
    "limit": 1000
  }'

# 2. After LLM summarization, store compressed cluster summary
curl -X POST http://localhost:3000/v1/memory/store \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "analytics-bot",
    "content": "DAU SUMMARY May 13-31: avg 12,890/day, peak 13,420 (May 29), low 12,388 (May 15 login outage). Growth +3.8% vs prior.",
    "importance": 0.90,
    "memory_type": "semantic",
    "tags": ["compressed", "cluster-dau", "range-may13-may31", "dau"]
  }'

# 3a. Hard-delete the originals (analytics: no audit needed)
curl -X POST http://localhost:3000/v1/memory/forget \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "analytics-bot", "memory_ids": ["m-001", "m-002", "m-003"]}'

# 3b. Or demote one original instead, when an audit trail is required
curl -X PATCH http://localhost:3000/v1/memories/m-004/importance \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "analytics-bot", "importance": 0.08}'

# 4. Verify: recall now returns the compressed summary
curl -X POST http://localhost:3000/v1/memory/recall \
  -H "Authorization: Bearer dk-..." \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "analytics-bot", "query": "DAU trend May", "min_importance": 0.7, "top_k": 5}'
from dakera import DakeraClient, BatchRecallRequest, BatchMemoryFilter
import openai
import re
import uuid
from collections import defaultdict
from datetime import datetime, timedelta, timezone

client = DakeraClient(base_url="http://localhost:3000", api_key="dk-...")
oai = openai.OpenAI()
AGENT = "analytics-bot"

def cluster_by_metric(memories):
    """Group data points by metric: the content starts with "DAU:", "Revenue:", ..."""
    clusters = defaultdict(list)
    for m in memories:
        metric = m.content.split(":", 1)[0].strip().lower()
        clusters[metric].append(m)
    return clusters

def summarize_cluster(cluster):
    """LLM summarization of a memory cluster."""
    contents = "\n".join([f"- {m.content}" for m in cluster])
    resp = oai.chat.completions.create(
        model="gpt-4o",
        messages=[{
            "role": "system",
            "content": "Summarize these analytics data points into a single dense paragraph. Preserve all quantitative values, dates, and trends. Highlight anomalies."
        }, {
            "role": "user",
            "content": f"Data points:\n{contents}"
        }]
    )
    return resp.choices[0].message.content

def numbers_are_grounded(summary: str, cluster) -> bool:
    """Every number in the summary must appear in at least one input memory."""
    source = " ".join(m.content for m in cluster)
    return all(n in source for n in re.findall(r"\d[\d,.]*\d|\d", summary))

def compress_window(start: datetime, end: datetime, min_cluster_size: int = 3, hard_delete: bool = True):
    """Compress one time window of raw analytics memories."""
    candidates = client.batch_recall(BatchRecallRequest(
        agent_id=AGENT,
        filter=BatchMemoryFilter(
            tags=["daily", "weekly"],            # raw data points; summaries are not tagged daily
            max_importance=0.8,                  # summaries (0.85-0.92) are excluded
            created_after=int(start.timestamp()),
            created_before=int(end.timestamp()),
        ),
        limit=1000,
    ))

    clusters = cluster_by_metric(candidates.memories)
    print(f"Found {len(clusters)} clusters from {len(candidates.memories)} memories")

    for metric, cluster in clusters.items():
        if len(cluster) < min_cluster_size:
            continue  # Skip tiny clusters: not worth compressing

        summary = summarize_cluster(cluster)
        if not summary or not numbers_are_grounded(summary, cluster):
            continue  # Skip empty summaries and summaries with invented numbers

        cluster_id = str(uuid.uuid4())[:8]
        client.store_memory(
            agent_id=AGENT,
            content=summary,
            importance=0.90,
            memory_type="semantic",
            tags=["compressed", f"cluster-{cluster_id}", f"range-{start:%b%d}-{end:%b%d}".lower(), metric]
        )

        ids = [m.id for m in cluster]
        if hard_delete:
            for memory_id in ids:  # analytics: no audit needed
                client.forget(agent_id=AGENT, memory_id=memory_id)
        else:
            client.update_importance(agent_id=AGENT, memory_ids=ids, importance=0.08)
        print(f"Cluster {cluster_id} ({metric}): {len(cluster)} memories -> 1 summary")

# Run monthly: compress the 4-week window that ended 30 days ago
now = datetime.now(timezone.utc)
compress_window(start=now - timedelta(days=58), end=now - timedelta(days=30))
import { DakeraClient } from '@dakera-ai/dakera';
import OpenAI from 'openai';
import { randomUUID } from 'crypto';

const client = new DakeraClient({ baseUrl: 'http://localhost:3000', apiKey: 'dk-...' });
const oai = new OpenAI();
const AGENT = 'analytics-bot';

// Group data points by metric: the content starts with "DAU:", "Revenue:", ...
function clusterByMetric<T extends { content: string }>(memories: T[]): Map<string, T[]> {
  const clusters = new Map<string, T[]>();
  for (const m of memories) {
    const metric = m.content.split(':')[0].trim().toLowerCase();
    clusters.set(metric, [...(clusters.get(metric) ?? []), m]);
  }
  return clusters;
}

async function summarizeCluster(cluster: { content: string }[]): Promise<string> {
  const contents = cluster.map(m => `- ${m.content}`).join('\n');
  const res = await oai.chat.completions.create({
    model: 'gpt-4o',
    messages: [
      { role: 'system', content: 'Summarize these analytics data points into a single dense paragraph. Preserve all quantitative values, dates, and anomalies.' },
      { role: 'user', content: `Data:\n${contents}` },
    ],
  });
  return res.choices[0].message.content ?? '';
}

// Every number in the summary must appear in at least one input memory
function numbersAreGrounded(summary: string, cluster: { content: string }[]): boolean {
  const source = cluster.map(m => m.content).join(' ');
  return (summary.match(/\d[\d,.]*\d|\d/g) ?? []).every(n => source.includes(n));
}

async function compressWindow(start: Date, end: Date, minClusterSize = 3) {
  const { memories } = await client.batchRecall({
    agent_id: AGENT,
    filter: {
      tags: ['daily', 'weekly'],
      max_importance: 0.8,
      created_after: Math.floor(start.getTime() / 1000),
      created_before: Math.floor(end.getTime() / 1000),
    },
    limit: 1000,
  });

  const clusters = clusterByMetric(memories);
  console.log(`Found ${clusters.size} clusters from ${memories.length} memories`);

  for (const [metric, cluster] of clusters) {
    if (cluster.length < minClusterSize) continue;
    const summary = await summarizeCluster(cluster);
    if (!summary || !numbersAreGrounded(summary, cluster)) continue;

    const clusterId = randomUUID().slice(0, 8);
    await client.storeMemory(AGENT, {
      content: summary,
      importance: 0.90,
      memory_type: 'semantic',
      tags: ['compressed', `cluster-${clusterId}`, metric],
    });

    // Hard-delete the originals (analytics: no audit needed)
    for (const m of cluster) await client.forget(AGENT, m.id);
    console.log(`Cluster ${clusterId} (${metric}): ${cluster.length} memories -> 1 summary`);
  }
}

// Run monthly: compress the 4-week window that ended 30 days ago
const day = 86_400_000;
await compressWindow(new Date(Date.now() - 58 * day), new Date(Date.now() - 30 * day));
use dakera_client::{BatchMemoryFilter, BatchRecallRequest, DakeraClient, ForgetRequest,
    MemoryType, StoreMemoryRequest};
use std::collections::HashMap;

let client = DakeraClient::builder("http://localhost:3000")
    .api_key("dk-...")
    .build()?;
let agent = "analytics-bot";

// 1. List raw data points (summaries are tagged "compressed", not "daily")
let candidates = client.batch_recall(
    BatchRecallRequest::new(agent)
        .with_filter(
            BatchMemoryFilter::default()
                .with_tags(vec!["daily".into(), "weekly".into()])
                .with_max_importance(0.8),
        )
        .with_limit(1000),
).await?;

// 2. Group by metric: the content starts with "DAU:", "Revenue:", ...
let mut clusters: HashMap<String, Vec<_>> = HashMap::new();
for m in &candidates.memories {
    let metric = m.content.split(':').next().unwrap_or("").trim().to_lowercase();
    clusters.entry(metric).or_default().push(m);
}

// 3. For each cluster: summarize with your LLM, store, then delete the originals
for (metric, cluster) in clusters {
    if cluster.len() < 3 { continue; }
    let summary = summarize_with_llm(&cluster).await?; // your LLM call
    let cluster_id = uuid::Uuid::new_v4().to_string()[..8].to_string();

    client.store_memory(
        StoreMemoryRequest::new(agent, summary)
            .with_type(MemoryType::Semantic)
            .with_importance(0.90)
            .with_tags(vec!["compressed".into(), format!("cluster-{}", cluster_id), metric.clone()]),
    ).await?;

    let ids: Vec<String> = cluster.iter().map(|m| m.id.clone()).collect();
    client.forget(ForgetRequest::by_ids(agent, ids)).await?;
    println!("Cluster {} ({}): {} -> 1 summary", cluster_id, metric, cluster.len());
}
package main

import (
    "context"
    "fmt"
    "strings"
    dakera "github.com/dakera-ai/dakera-go"
)

func compressAgentMemories(ctx context.Context, client *dakera.Client, agent string) {
    // 1. List raw data points (summaries are tagged "compressed", not "daily")
    maxImp := float32(0.8)
    candidates, _ := client.BatchRecall(ctx, dakera.BatchRecallRequest{
        AgentID: agent,
        Filter:  dakera.BatchMemoryFilter{Tags: []string{"daily", "weekly"}, MaxImportance: &maxImp},
        Limit:   1000,
    })

    // 2. Group by metric: the content starts with "DAU:", "Revenue:", ...
    clusters := map[string][]dakera.RecalledMemory{}
    for _, m := range candidates.Memories {
        metric := strings.ToLower(strings.TrimSpace(strings.SplitN(m.Content, ":", 2)[0]))
        clusters[metric] = append(clusters[metric], m)
    }
    fmt.Printf("Found %d clusters from %d memories\n", len(clusters), len(candidates.Memories))

    for metric, cluster := range clusters {
        if len(cluster) < 3 { continue }
        summary := summarizeWithLLM(cluster) // your LLM call
        clusterID := randomID(8)
        importance := float32(0.90)

        // Store compressed summary
        client.StoreMemory(ctx, agent, dakera.StoreMemoryRequest{
            Content:    summary,
            Importance: &importance,
            MemoryType: "semantic",
            Tags:       []string{"compressed", "cluster-" + clusterID, metric},
        })

        // Delete the originals
        for _, m := range cluster {
            client.Forget(ctx, agent, m.ID)
        }
        fmt.Printf("Cluster %s (%s): %d memories -> 1 summary\n", clusterID, metric, len(cluster))
    }
}

Fewer, denser memories for analytics agents

Dakera's batch recall, store and forget primitives make compression a short pipeline.

Deploy Free →

SDK Reference

MethodSDKPurpose
batch_recall(BatchRecallRequest(agent_id, filter, limit))PythonList one window of candidate memories, no query
batchRecall({agent_id, filter, limit})TypeScriptList one window of candidate memories, no query
recall(agent_id, query, min_importance, top_k)PythonCheck what a query returns after compression
store_memory(agent_id, content, importance, memory_type, tags)PythonStore the compressed cluster summary
storeMemory(agentId, {content, importance, memory_type, tags})TypeScriptStore the compressed cluster summary
forget(agent_id, memory_id)PythonHard-delete an original after compression
forget(agentId, memoryId)TypeScriptHard-delete an original after compression
update_importance(agent_id, memory_ids, importance)PythonSoft-demote originals (audit-friendly alternative to delete)
updateImportance(agentId, {memory_ids, importance})TypeScriptSoft-demote originals (audit-friendly alternative to delete)

Performance Considerations

0.85–0.92
Importance of compressed summaries
3
Minimum cluster size before calling the LLM
10,000
Most memories one batch recall returns (higher limits are cut)

Edge Cases

Edge Case 1: LLM Hallucinating Metrics in Summaries

LLMs can hallucinate numerical values in summarization, especially when the input data has irregular patterns. Always validate compressed summaries by checking that all numerical values in the output appear in at least one input memory. Use a regex extraction pass to compare input values vs. output values, and re-run the LLM call with a stricter prompt if values diverge by more than 5%.

Edge Case 2: Compressing Memories That Cover Different Time Ranges

Clustering by semantic similarity may group "DAU on May 15" with "DAU on July 22" — same metric, very different time periods. Before clustering, filter memories by a time window first: only cluster memories from the same 4-week period together. Never compress across more than 6 weeks into a single summary or you lose temporal precision.

Edge Case 3: Singleton Clusters After Aggressive Thresholds

With a high similarity threshold (0.90+), many memories end up as singleton clusters — no similar memories found. Compressing singletons produces a "summary" identical to the original. Add a minimum cluster size check (at least 3 members) before calling the LLM. Singletons can be left as-is or demoted with importance decay instead.

Edge Case 4: Preserving Anomalies Through Compression

High-signal anomalies (a login outage on May 15 causing DAU to drop) can be diluted in a summary that averages the normal days around it. Before compressing a cluster, identify anomalous members (importance > 0.75, or tagged "incident") and store them separately as high-importance standalone memories before the cluster is compressed. The summary captures the trend; the anomaly memory captures the exception.

Edge Case 5: Compressing Already-Compressed Summaries

After 3 months, you may have 12 weekly summaries for the same metric. These can themselves be compressed into a quarterly summary. Design a multi-tier compression hierarchy: daily → weekly summary → monthly summary → quarterly summary. Tag each tier: "tier-1", "tier-2", "tier-3". Always exclude higher tiers from lower-tier compression runs to prevent recursive summarization.

Edge Case 6: AutoPilot Merging Low-Importance Originals

AutoPilot consolidation (every 12 hours, on by default) merges groups of three or more memories that share at least two tags and all sit below importance 0.3. Originals demoted to 0.08 that keep their shared tags qualify, and so do raw data points that decay has pushed below 0.3 before your job runs. If the raw points must stay as they are for audit, give them tag sets that do not overlap, run compression before they decay that far, or turn AutoPilot off by setting DAKERA_AUTOPILOT_ENABLED to false.

Advanced Configuration: Clustering Strategies & LLM Prompt Templates

Clustering Strategy by Store Size

Store SizeClustering Method (embeddings from your model)Threshold
<200 memoriesGreedy pairwise0.78
200–1,000 memoriesGreedy pairwise0.80
1,000–5,000 memoriesk-means on embeddings (k=50)0.78
>5,000 memoriesApproximate nearest neighbors + label propagation0.82

Analytics Summarization Prompt

SYSTEM: You are an analytics data summarizer.
Summarize the following data points into a single paragraph.
Rules:
1. Preserve ALL numerical values exactly as given (no rounding beyond source precision)
2. State the date range covered
3. Identify the central metric (DAU, revenue, churn, etc.)
4. Highlight any anomalies or outliers (not just the average trend)
5. End with: overall direction (growing/stable/declining)
6. Keep the summary under 120 words
Do not invent values not present in the source data.

USER: Summarize:
{CLUSTER_CONTENTS}

Compression Schedule by Domain

Agent TypeCompression FrequencyMin Age Before Compress
Analytics / BI agentWeekly (after report cycle)7 days
Customer support agentMonthly30 days
Personal assistantMonthly60 days
Legal / compliance agentQuarterly90 days
Try it live

Run this pattern against a real Dakera.

The Playground executes live API calls in your browser. No account, no install. Then run it on your own server in five minutes.