> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognee.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Sessions and Caching

> Understanding how Cognee maintains conversational memory through sessions and cache adapters

In Cognee, a session defines the scope for a single conversation or agent run. It maintains a cache of short-term information, including recent queries, responses, and the context used to answer them.

## What Is a Session?

A session is Cognee's short-term memory for a specific user. It is identified by `(user_id, session_id)` and stores an ordered list of recent interactions.

In the v1.0 API, you interact with sessions through [`remember()`](/core-concepts/main-operations/remember) and [`recall()`](/core-concepts/main-operations/recall):

* `cognee.remember(data, session_id="my_session")` — writes content directly into the session cache for fast retrieval.
* `cognee.recall(query_text, session_id="my_session")` — searches session cache entries first, then falls through to the permanent graph if nothing matches.

The lower-level [`cognee.search()`](/core-concepts/main-operations/legacy-operations/search) also accepts `session_id`. Session-aware retrieval is used across the main completion-oriented search paths, including graph-completion variants, RAG, triplet, summaries, temporal, cypher, and natural-language retrieval.

When you omit `session_id`, Cognee uses `default_session` and still stores the turn when caching is enabled.

Cognee reads from session memory at the start of a retrieval to recover earlier turns. When the retrieval finishes, it writes a new interaction to the session so the history grows over time.

Using the same `session_id` across calls allows Cognee to include previous interactions as conversational history in the LLM prompt, enabling follow-up questions and contextual awareness.

To inspect stored history, use `cognee.session.get_session(session_id=..., last_n=...)`. To annotate a stored entry, use `cognee.session.add_feedback(...)` and `cognee.session.delete_feedback(...)`.

<Note>
  Sessions require caching to be enabled. See the next sections and Configuration Details below. If caching is disabled or unavailable, searches still work but without access to previous interactions.
</Note>

## How Sessions Work

Sessions integrate with both the v1.0 operations and the lower-level search pipeline.

**v1.0 session flow (via `recall`):**

When you call `cognee.recall(query_text, session_id="my_session")`:

1. **Check session cache** – Cognee searches the session cache for matching entries using keyword matching
2. **Fall through to graph** – If no session entries match, retrieval continues against the permanent knowledge graph
3. **Return tagged results** – Results include a `_source` field indicating whether they came from `"session"` or `"graph"`

**Lower-level session flow (via `search`):**

When you call `cognee.search()` with a `session_id`:

1. **Retrieve context** – Cognee finds relevant graph elements for your query
2. **Load conversation history** – If caching is enabled, previous interactions for `(user_id, session_id)` are loaded
3. **Generate answer** – The LLM receives the query, graph context, and retrieved history
4. **Save interaction** – A new Q\&A entry is stored in the session cache

## Cache Adapters

Cognee supports two cache adapters for storing sessions. Redis is recommended for distributed or multi-process setups, while Filesystem can be used when you need a simple local cache without network dependencies. Both provide the same functionality; only the storage backend differs. Below are the configuration options for each adapter with additional details.

<Tabs>
  <Tab title="Redis">
    Add to your `.env` file:

    ```dotenv theme={null}
    CACHING=true
    CACHE_BACKEND=redis
    CACHE_HOST=localhost
    CACHE_PORT=6379
    ```

    **Start Redis:**

    ```bash theme={null}
    # Using Docker
    docker run -d -p 6379:6379 redis:latest

    # Or using local installation
    redis-server
    ```

    * Fast in-memory storage
    * Supports shared locks for Kuzu (multi-process coordination)
    * Requires a running Redis instance and network connectivity
  </Tab>

  <Tab title="Filesystem">
    **Configuration:**

    Add to your `.env` file:

    ```dotenv theme={null}
    CACHING=true
    CACHE_BACKEND=fs
    ```

    * Sessions are stored in `{DATA_ROOT_DIRECTORY}/.cognee_fs_cache/sessions_db`.
    * Stores session data on the local filesystem using `diskcache`
    * No network dependency
    * Does not provide shared locks for Kuzu
    * Not designed for multi-node coordination
  </Tab>
</Tabs>

<AccordionGroup>
  <Accordion title="Session Lifecycle Persistence (Relational DB)">
    In addition to the cache layer, Cognee persists session lifecycle metadata to the relational database (SQLite or Postgres). Running database migrations — either via `await cognee.run_startup_migrations()` or `alembic upgrade head` — creates the required relational tables for this metadata.

    Two tables are created:

    <Tabs>
      <Tab title="session_records">
        One row per `(user_id, session_id)`:

        | Column             | Type                 | Description                                                                 |
        | ------------------ | -------------------- | --------------------------------------------------------------------------- |
        | `session_id`       | String (PK)          | The caller-supplied session identifier.                                     |
        | `user_id`          | UUID (PK)            | The owning user. Same `session_id` from two users is two separate sessions. |
        | `dataset_id`       | UUID (nullable)      | Associated dataset, if any.                                                 |
        | `status`           | String               | Stored status: `running`, `completed`, or `failed`.                         |
        | `started_at`       | Timestamp            | When the session started.                                                   |
        | `last_activity_at` | Timestamp            | When the session last received an LLM call.                                 |
        | `ended_at`         | Timestamp (nullable) | When the session was marked completed or failed.                            |
        | `tokens_in`        | Integer              | Cumulative input tokens across all LLM calls in this session.               |
        | `tokens_out`       | Integer              | Cumulative output tokens.                                                   |
        | `cost_usd`         | Float                | Estimated cumulative cost in USD.                                           |
        | `error_count`      | Integer              | Number of errors recorded in this session.                                  |
        | `last_model`       | Text (nullable)      | Most recently used LLM model name.                                          |
      </Tab>

      <Tab title="session_model_usage">
        One row per `(session_id, user_id, model)`:

        | Column       | Type        | Description                                 |
        | ------------ | ----------- | ------------------------------------------- |
        | `session_id` | String (PK) | The session.                                |
        | `user_id`    | UUID (PK)   | The owning user.                            |
        | `model`      | Text (PK)   | The model name (e.g. `openai/gpt-4o-mini`). |
        | `tokens_in`  | Integer     | Input tokens attributed to this model.      |
        | `tokens_out` | Integer     | Output tokens attributed to this model.     |
        | `cost_usd`   | Float       | Cost attributed to this model.              |
        | `updated_at` | Timestamp   | When this row was last updated.             |
      </Tab>
    </Tabs>

    Splitting per-model usage out of `session_records` allows mixed-model sessions (e.g. a completion model plus an embedding model) to attribute cost correctly.

    **Session status lifecycle:**

    Sessions move through: `running` → `completed` or `failed`. The `abandoned` status is never written to the database — it is computed at read time: a session whose `last_activity_at` is older than the abandonment threshold and is still in `running` state is reported as `abandoned`. The threshold defaults to 30 minutes and is configurable:

    ```dotenv theme={null}
    SESSION_ABANDON_AFTER_SECONDS=1800  # default: 30 minutes
    ```

    This means no background sweeper is needed to mark stale sessions. Reads include the effective status automatically.

    <Note>
      Token counts use a character-based estimate (`len(text) // 4`) when the LLM client does not return exact usage counts. These are approximate and suitable for dashboard aggregates rather than precise billing.
    </Note>
  </Accordion>

  <Accordion title="Session Data Structure">
    Sessions store interactions as JSON entries in a list. Each item returned by `cognee.session.get_session()` is a `SessionQAEntry` model with the following fields:

    | Field                    | Type                             | Description                                                                                  |
    | ------------------------ | -------------------------------- | -------------------------------------------------------------------------------------------- |
    | `time`                   | `str`                            | ISO 8601 timestamp when the entry was created.                                               |
    | `qa_id`                  | `Optional[str]`                  | Unique identifier for the entry. Required for feedback operations and updates.               |
    | `question`               | `str`                            | The user's original query text.                                                              |
    | `context`                | `str`                            | Retrieved context used to answer the question. May be empty if summarization is not enabled. |
    | `answer`                 | `str`                            | The generated answer.                                                                        |
    | `feedback_text`          | `Optional[str]`                  | Free-form feedback text, or `None` if not set.                                               |
    | `feedback_score`         | `Optional[int]`                  | Integer rating from `1` to `5`, or `None` if not set.                                        |
    | `used_graph_element_ids` | `Optional[Dict[str, List[str]]]` | Graph node and edge IDs used during retrieval. Keys are `node_ids` and `edge_ids`.           |
    | `memify_metadata`        | `Optional[Dict[str, bool]]`      | Session persistence and memify status flags, such as `feedback_weights_applied`.             |

    Sessions are keyed by `agent_sessions:{user_id}:{session_id}`.

    Each user can have multiple sessions, each maintaining its own cache of short-term information.
  </Accordion>

  <Accordion title="Configuration Details">
    **Environment Variables:**

    * `CACHING` (bool): Enable/disable caching (default: `true`). Set to `false` to disable session storage and conversational memory.
    * `CACHE_BACKEND` (str): `"redis"`, `"fs"`, or `"tapes"` (default: `"fs"`). When set to `"fs"`, sessions are stored on local disk; when set to `"redis"`, sessions are stored in Redis and shared across processes; when set to `"tapes"`, sessions are stored locally and new Q\&A turns are mirrored to a running Tapes ingest service.
    * `CACHE_HOST` (str): Redis hostname (default: `"localhost"`)
    * `CACHE_PORT` (int): Redis port (default: `6379`)
    * `CACHE_USERNAME` (str, optional): Redis username
    * `CACHE_PASSWORD` (str, optional): Redis password
    * `SESSION_TTL_SECONDS` (int, optional): Time-to-live for cached session entries in seconds (default: `604800` — 7 days). Set to `0` to disable expiry.

    **Conversation history window:**

    * Cognee includes up to the last 10 session entries when building LLM conversation history.

    Sessions expire automatically after `SESSION_TTL_SECONDS` when that value is greater than `0`. If you set `SESSION_TTL_SECONDS=0`, sessions persist until the cache is cleared (e.g. via prune or by wiping the cache backend).

    **Graceful fallback behavior:**

    * If no cache backend is configured or the cache is unavailable, `cognee.session.get_session()` returns `[]`.
    * In the same situation, `cognee.session.add_feedback()` and `cognee.session.delete_feedback()` return `False`.
  </Accordion>

  <Accordion title="Adapter Comparison">
    | Feature          | Redis                   | Filesystem             | Tapes                                    |
    | ---------------- | ----------------------- | ---------------------- | ---------------------------------------- |
    | Storage          | In-memory (Redis)       | Local disk (diskcache) | Local disk + mirrored ingest             |
    | Performance      | Very fast               | Fast (local I/O)       | Fast local writes + network mirror       |
    | Multi-process    | ✅ Supported             | ❌ Not supported        | ❌ Not supported                          |
    | Shared locks     | ✅ Yes                   | ❌ No                   | ❌ No                                     |
    | Network required | ✅ Yes                   | ❌ No                   | ⚠️ Only for mirroring to Tapes           |
    | Setup complexity | Medium                  | Low                    | Medium                                   |
    | Best for         | Production, distributed | Development, local     | Local session cache with Tapes ingestion |
  </Accordion>
</AccordionGroup>

<Note>
  Cached sessions can be persisted into the knowledge graph for long-term retrieval using the [session persistence memify pipeline](/guides/memify-session-persistence).
</Note>

<Columns cols={3}>
  <Card title="Search" icon="search" href="/core-concepts/main-operations/legacy-operations/search">
    Learn how sessions integrate with search
  </Card>

  <Card title="Sessions Guide" icon="code" href="/guides/sessions">
    Practical examples with Redis and filesystem
  </Card>

  <Card title="Setup Configuration" icon="settings" href="/setup-configuration/overview">
    Configure cache adapters
  </Card>
</Columns>
