> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Gentleman-Programming/engram/llms.txt
> Use this file to discover all available pages before exploring further.

# mem_suggest_topic_key

> Generate a stable topic key for memory upserts

## Overview

Generate a stable `topic_key` that allows evolving topics (like architecture decisions) to update a single observation over time instead of creating duplicates. The tool analyzes the type, title, and content to suggest a normalized, cross-session key.

<Note>
  This tool is part of the **agent** profile and uses deferred loading to optimize performance.
</Note>

## Parameters

<ParamField path="type" type="string">
  Observation type/category (e.g., architecture, decision, bugfix, pattern)

  Recognized types that map to topic families:

  * `architecture`, `design`, `adr`, `refactor` → `architecture/*`
  * `bug`, `bugfix`, `fix`, `incident`, `hotfix` → `bug/*`
  * `decision` → `decision/*`
  * `pattern`, `convention`, `guideline` → `pattern/*`
  * `config`, `setup`, `infra`, `infrastructure`, `ci` → `config/*`
  * `discovery`, `investigation`, `root_cause` → `discovery/*`
  * `learning`, `learn` → `learning/*`
  * `session_summary` → `session/*`
</ParamField>

<ParamField path="title" type="string">
  Observation title (preferred input for stable keys)

  The title is the primary source for generating the topic segment. It's normalized by:

  * Converting to lowercase
  * Removing special characters
  * Replacing spaces with hyphens
  * Stripping private tags (anything in `[brackets]`)
</ParamField>

<ParamField path="content" type="string">
  Observation content (used as fallback if title is empty)

  If no title is provided, the first 8 words of the content are used to generate the topic segment.
</ParamField>

## Response

<ResponseField name="topic_key" type="string">
  Suggested topic key in the format `family/segment`
</ResponseField>

The suggested key follows the pattern: `{family}/{normalized-segment}`

Examples:

* `architecture/jwt-auth-model`
* `bug/fts5-query-sanitization`
* `pattern/structured-memory-format`
* `config/sqlite-fts5-setup`

## Topic Key Generation Logic

### 1. Infer Topic Family

The algorithm first determines the topic family based on:

1. The `type` parameter (if it matches a known category)
2. Keywords in the `title` and `content` (if type doesn't match)
3. Defaults to `"topic"` if no match

### 2. Normalize Segment

From the title (or content fallback):

1. Strip private tags in `[brackets]`
2. Convert to lowercase
3. Replace spaces and special chars with hyphens
4. Remove redundant family prefix (e.g., "bug-" from segment if family is "bug")
5. Default to `"general"` if empty

### 3. Combine

Returns `{family}/{segment}`

## Usage Examples

### Architecture Decision

```json theme={null}
{
  "type": "architecture",
  "title": "JWT authentication model",
  "content": "Replaced session-based auth with JWT tokens..."
}
```

**Response:**

```
Suggested topic_key: architecture/jwt-authentication-model
```

### Bug Fix

```json theme={null}
{
  "type": "bugfix",
  "title": "FTS5 query sanitization"
}
```

**Response:**

```
Suggested topic_key: bug/fts5-query-sanitization
```

### Pattern Without Type

```json theme={null}
{
  "title": "Structured memory format for What/Why/Where/Learned"
}
```

**Response:**

```
Suggested topic_key: pattern/structured-memory-format-for-what-why-where-learned
```

### Fallback to Content

```json theme={null}
{
  "type": "config",
  "content": "Set up SQLite with FTS5 extension for full-text search on observations table"
}
```

**Response:**

```
Suggested topic_key: config/set-up-sqlite-with-fts5-extension-for
```

## When to Use

* **Before `mem_save`**: When you want evolving topics to update a single observation
* **Architectural decisions**: Track how decisions evolve over time
* **Ongoing bugs**: Update the same memory as investigation progresses
* **Living documentation**: Keep a single observation for patterns or conventions

## Workflow

```typescript theme={null}
// 1. Get suggestion
const suggestion = await mem_suggest_topic_key({
  type: "architecture",
  title: "Database schema design"
});
// Returns: "architecture/database-schema-design"

// 2. Use in mem_save
await mem_save({
  title: "Database schema design",
  type: "architecture",
  content: "...",
  topic_key: "architecture/database-schema-design"
});

// 3. Later updates with same topic_key will revise the observation
await mem_save({
  title: "Database schema design [updated]",
  type: "architecture",
  content: "[Updated approach]...",
  topic_key: "architecture/database-schema-design"
});
// This updates the existing observation instead of creating a duplicate
```

<Warning>
  Topic keys must be consistent across saves to enable upserts. Use this tool to ensure stability.
</Warning>

## Related Tools

* [`mem_save`](/mcp/mem-save) - Save or upsert observations with topic keys
* [`mem_update`](/mcp/mem-update) - Update observations by ID
