> ## Documentation Index
> Fetch the complete documentation index at: https://metacognition-fdc534de-master.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Remember conversation turns

> Store turns in a session, with optional observations and metadata.

Use **`tex.conversations.remember`** to store new conversation turns. This is the write side of the loop from the [Quickstart](/quickstart).

```python theme={null}
RememberResponse = tex.conversations.remember(
    turns: list[dict],
    *,
    session_id: str,
    metadata: dict | None = None,
) -> RememberResponse
```

## Parameters

<ParamField path="turns" type="list[dict]" required>
  List of turn dicts. **At least one turn is required**. Empty lists return `422`. Each turn:

  ```python theme={null}
  {
    "role": "user" | "assistant" | str,   # any free-form role
    "text": "the thing said",
    "timestamp": "2026-01-12T14:00:00Z",  # ISO 8601, UTC preferred
    "observations": [...],                 # optional, see below
  }
  ```
</ParamField>

<ParamField path="session_id" type="str" required>
  The conversation, channel, or task this batch belongs to.
</ParamField>

<ParamField path="metadata" type="dict | None">
  Free-form metadata attached to the batch. Deep mode can use it during search.
</ParamField>

## Returns

<ResponseField name="job_id" type="str | None">
  Stable identifier for this write. Use it to match SDK logs with server logs.
</ResponseField>

<ResponseField name="active_fragment_ids" type="list[str]">
  IDs of the active-memory fragments. These are recallable right away.
</ResponseField>

<ResponseField name="passive_job_id" type="str | None">
  Reserved for future async passive job tracking. Currently always `null`.
</ResponseField>

<ResponseField name="usage" type="Usage | None">
  `tokens_in` / `tokens_out` for this call. `tokens_out` is typically 0 on `remember`. Always present in production.
</ResponseField>

## Examples

### Single user turn

```python theme={null}
tex.conversations.remember(
    session_id="chat-1",
    turns=[
        {
            "role": "user",
            "text": "I prefer Python over JavaScript.",
            "timestamp": "2026-05-08T10:00:00Z",
        },
    ],
)
```

### Both sides of a turn

```python theme={null}
tex.conversations.remember(
    session_id="chat-1",
    turns=[
        {"role": "user",      "text": user_msg,   "timestamp": now_iso()},
        {"role": "assistant", "text": assistant_msg, "timestamp": now_iso()},
    ],
)
```

### Backfill historical conversation

```python theme={null}
turns = [
    {"role": t["role"], "text": t["text"], "timestamp": t["ts"]}
    for t in db.fetch_chat_history(conv_id)
]

# One big batch is far cheaper than per-turn calls
tex.conversations.remember(session_id=f"chat-{conv_id}", turns=turns)
```

### Pre-extracted observations

If your app already extracted structured facts, pass them inline:

```python theme={null}
turns = [{
    "role": "user",
    "text": "I'm allergic to shellfish.",
    "timestamp": "2026-05-08T10:00:00Z",
    "observations": [
        {"type": "preference", "predicate": "avoids", "value": "shellfish"},
    ],
}]

tex.conversations.remember(session_id="chat-1", turns=turns)
```

## Behavior

<Steps>
  <Step title="Active write">
    The call returns after active memory is saved, usually around 150ms. The turn is recallable right away.
  </Step>

  <Step title="Background enrichment">
    Tex extracts observations and entities in the background. They appear in later recalls.
  </Step>
</Steps>

## Best practices

* **Batch.** Pass dozens of turns in one call. Don't loop one-per-turn.
* **Use UTC ISO 8601** for timestamps (`...Z` suffix). This keeps temporal queries clear.
* **Skip system messages.** They consume tokens and add noise to recall.
* **Run `remember` off the request path.** Use Celery, RQ, or a `BackgroundTasks` queue when users should not wait.

## Idempotency

Tex computes a stable hash per turn from text, timestamp, and role. Re-sending the same turn is a no-op. It does not create duplicate active memory or double bill the same turn.

This makes retries safe after a network blip.

<Card title="Next: Recall" icon="magnifying-glass" href="/sdk/recall">
  Pull the relevant slice of memory.
</Card>
