NetStacksNetStacks

Device Memory

Per-device persistent memory in NetStacks: role, criticality, standing instructions, and dated entries, capped and injected into the device AI context.

Overview

Device Memory is a small, durable record of facts the AI should always know about one device: what it is, how important it is, the rules for touching it, and a running log of dated notes. Unlike a chat history — which is thrown away when you close a tab — device memory persists and is re-injected into the AI's context every time you open a session for that device.

It answers a recurring question for network engineers:

"The last person who touched this router left at 2am. What did they change, and what must I never do to it?"

In Personal Mode the Local Agent stores device memory in its local SQLite database, keyed per saved session. With the Controller the same record is stored server-side, shared across your whole organization, and resolved to the underlying device so every session for that device shares one memory.

Memory vs. Context

Device Memory is per-device standing knowledge (role, criticality, rules, dated notes). It is closely related to Session Context — team/tribal knowledge about past issues (issue, root cause, resolution, ticket). Both are injected into the device AI context; this page covers Device Memory.

What It Stores

A device-memory record has two parts: a set of metadata fields on the parent record, and a list of dated entries that hang off it.

Metadata Fields

The parent record carries four optional fields. The editor labels these Device Metadata and notes that they are always included in AI context (they are never truncated):

role
What the device is. A free-text string — the editor offers suggestions like Core Router, Edge Router, Distribution Switch, Access Switch, Firewall, Load Balancer, Server, Jumpbox, Wireless Controller, or Other.
criticality
One of low, medium, high, or critical (or unset). Backed by a database CHECK constraint — no other value is accepted.
standing_instructions
The rules of engagement for this device. This is the most load-bearing field. Example placeholder from the product: "Never reload without CAB approval. OSPF area 0 ABR — changes cascade."
notes
Free-form facts that do not change often. Example placeholder: "Runs JunOS 21.4R3, known memory leak on 22.x".
Put hard rules in Standing Instructions

The AI reads standing_instructions verbatim and treats it as a constraint. "Never reload without CAB approval" is far more effective there than buried in a dated note — metadata fields are never dropped by the entry cap.

Dated Entries

Below the metadata is a Memories list: a running, dated log. Each entry has a date, a source, an author, and the content. The three sources are fixed by a database CHECK constraint:

SourceBadgeWritten by
manualManualA human, via the + Add Memory button in the editor. The author is the current profile username.
troubleshootingTroubleshootCaptured during a guided troubleshooting flow — commands and findings worth remembering.
overlordOverlordThe AI Overlord — NetStacks' real-time terminal-output analyzer — records something it observed.

When you click + Add Memory in the editor, the new entry is created with source: "manual", author set to your profile username, and date set to today in YYYY-MM-DD form. Entries are listed newest-first.

device_memory_entry.jsonjson
{
  "id": "9f3c…",
  "device_memory_id": "1a2b…",
  "date": "2026-06-15",
  "source": "manual",
  "author": "casey",
  "content": "Replaced SFP in Te0/1/0 after CRC errors. Optic was a counterfeit; only use Cisco-coded SFPs here.",
  "created_at": "2026-06-15T14:02:11Z",
  "updated_at": "2026-06-15T14:02:11Z"
}

Where to Edit It

There are two editing surfaces, depending on how memory is keyed:

  • Per-session (everyone): open Session Settings for a saved session and switch to the Device Memory tab. The editor shows the metadata fields at the top and the dated Memories list below. The Device Memory tab only appears for an existing (saved) session.
  • Per-device (Controller): in the enterprise device panel, the same editor is mounted against a Controller device id, so editing it once updates the memory every session for that device shares.

Edits are saved as you change them — metadata field changes call the update endpoint immediately, and adding/editing/deleting an entry is its own call. There is no separate "save device memory" button.

Empty by default

A fresh device starts with an empty record — no role, no criticality, no instructions, no entries. The backend uses get_or_create semantics: the first time you open the editor (or the AI fetches memory) an empty record is created for that session/device. An empty record contributes nothing to the AI prompt.

How It Reaches the AI

Every AI chat surface in the Terminal — the side panel, the floating chat, and the inline popup — uses one shared builder to assemble a per-session knowledge block that is appended to the system prompt. When you have an active device session, three blocks are appended in order:

  1. ACTIVE SESSION CONTEXT — tells the model which session "this device" refers to and which session id to use for tool calls.
  2. DEVICE MEMORY — the record described on this page.
  3. DEVICE CONTEXT — team/tribal knowledge (issues, root causes, resolutions, commands, tickets) from Session Context.

This happens client-side and identically in both Personal Mode and Enterprise — the Controller's wire shapes were designed so the Terminal talks to it unchanged.

The Injected DEVICE MEMORY Block

The builder serializes the record into a compact, plain-text block. Only populated fields appear — an empty record produces nothing. A fully-populated example:

DEVICE MEMORY:
Role: Core Router
Criticality: critical
Standing Instructions: Never reload without CAB approval. OSPF area 0 ABR — changes cascade.
Notes: Runs JunOS 21.4R3, known memory leak on 22.x

History:
- [2026-06-15] (manual) Replaced SFP in Te0/1/0 after CRC errors. Only use Cisco-coded SFPs here.
- [2026-06-11] (overlord) BGP session to AS64512 flapped twice during the maintenance window.
- [2026-06-02] (troubleshooting) High CPU traced to a broadcast storm on VLAN 200; storm-control applied.

The History list is only added when there is at least one entry. Each line is formatted as - [date] (source) content, newest-first.

Caps and Sanitizing

To keep the system prompt bounded, the builder caps how much it inlines. The client-side builder applies these limits before the prompt is sent:

  • Device Memory history: at most 20 entries are inlined (newest-first). Metadata fields (role, criticality, standing instructions, notes) are never capped.
  • Device Context (tribal knowledge): at most 5 entries are inlined; if more exist, a line tells the AI to use the list_session_context tool to read the rest.

The block is plain text with no executable markup — it is descriptive context, not a tool call. Fields are emitted as labeled lines, so a note containing newlines or odd characters is included as-is in the content position rather than being able to forge new labeled fields. Memory is retrieval-only: it is looked up by key and inlined, it is not embedded in the AI knowledge base / RAG index.

The cap is on what the AI sees, not what is stored

The Terminal still stores every entry. The 20-entry cap only limits how many of the newest entries are inlined into a single prompt. In Enterprise, the Controller can additionally prune old rows from storage — see Retention.

Keep entries useful, not noisy

Because only the 20 newest entries reach the model, write entries the way you would write a runbook line: one durable fact per entry. Transient chatter pushes the durable facts out of the window.

API and Storage

Device memory is a small REST surface on the Local Agent (and mirrored by the Controller in Enterprise). The session-keyed endpoints:

# Fetch (creates an empty record if none exists) — returns record + entries
GET    /sessions/{session_id}/device-memory

# Update the parent metadata (role / criticality / standing_instructions / notes)
PUT    /sessions/{session_id}/device-memory

# Append a dated entry
POST   /sessions/{session_id}/device-memory/entries

# Edit / delete an individual entry (entry-id keyed)
PUT    /device-memory/entries/{id}
DELETE /device-memory/entries/{id}

Updating metadata uses a partial body — send only the fields you want to change. A field set to null clears it; an omitted field is left unchanged:

curl -X PUT http://127.0.0.1:PORT/sessions/$SID/device-memory \
  -H 'Content-Type: application/json' \
  -d '{
    "role": "Core Router",
    "criticality": "critical",
    "standing_instructions": "Never reload without CAB approval."
  }'
curl -X POST http://127.0.0.1:PORT/sessions/$SID/device-memory/entries \
  -H 'Content-Type: application/json' \
  -d '{
    "date": "2026-06-15",
    "source": "manual",
    "author": "casey",
    "content": "Only use Cisco-coded SFPs in Te0/1/0."
  }'

In Personal Mode the records live in the Local Agent's SQLite database in two tables. The schema enforces the allowed values and a one-record-per-session rule:

CREATE TABLE device_memory (
    id TEXT PRIMARY KEY,
    session_id TEXT NOT NULL UNIQUE REFERENCES sessions(id) ON DELETE CASCADE,
    role TEXT,
    criticality TEXT CHECK (criticality IS NULL OR criticality IN ('low','medium','high','critical')),
    standing_instructions TEXT,
    notes TEXT,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);

CREATE TABLE device_memory_entries (
    id TEXT PRIMARY KEY,
    device_memory_id TEXT NOT NULL REFERENCES device_memory(id) ON DELETE CASCADE,
    date TEXT NOT NULL,
    source TEXT NOT NULL CHECK (source IN ('manual','troubleshooting','overlord')),
    author TEXT NOT NULL,
    content TEXT NOT NULL,
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);

Deleting a session cascades to its device-memory record; deleting a record cascades to its entries. The UNIQUE constraint on session_id guarantees a session never has two competing memory records.

The Agent port is dynamic

The Local Agent binds to a loopback port chosen at launch — substitute the real value for PORT in the examples above. The Terminal UI is the normal way to edit memory; the raw API is shown here for scripting and clarity.

Enterprise: Org-Wide Memory Enterprise

With the Controller, device memory becomes org-wide shared knowledge. Every user in the organization sees and edits the same record, and a record is keyed to the underlying device rather than a single user's saved session.

The Controller stores a polymorphic reference: a record points at either a device or a session_definition. When the Terminal calls GET /sessions/{id}/device-memory, the Controller resolves that session definition to its linked device server-side — so every session that points at the same device shares one memory record. The Terminal frontend does no device-id resolution itself; the Controller deliberately mirrors the Agent's wire shapes so the same client code works unchanged.

There is also a device-keyed variant used by the enterprise device panel, which keys directly on a Controller device id:

GET  /devices/{device_id}/device-memory
PUT  /devices/{device_id}/device-memory
POST /devices/{device_id}/device-memory/entries

All Controller reads and writes are org-scoped: a record belongs to an org_id, and entry edit/delete are filtered through their parent record's org. One team's memory is never visible to another org.

Flagging on Session Open Enterprise

When you connect to a device that already has team knowledge, NetStacks surfaces it proactively rather than waiting for you to ask. A Team Knowledge Available popup appears on session open showing the most recent note — who wrote it, the issue, and a ticket badge when the entry has a ticket reference:

┌─ Team Knowledge Available ───────────────────── ✕ ─┐
│  casey noted: BGP to AS64512 flaps under load.     │
│  🎫 NET-4471                                       │
│  [ Ask AI about this ]   [ View all (3) ]          │
│  core-rtr-01                                        │
└────────────────────────────────────────────────────┘

The ticket number comes from the ticket_ref field on the related Session Context entry. From the popup you can Ask AI about this (which seeds the chat with that context) or View all entries. This is how a freshly assigned on-call engineer immediately sees "there is an open ticket on this box" the moment the session opens, with the device's standing instructions and history already loaded into the AI.

Tickets live on Session Context entries

Device Memory entries are dated free-text notes (no ticket field). The ticket reference shown on session open belongs to a Session Context entry. The two are injected together and shown together, but ticket numbers are a Session Context attribute.

Retention Enterprise

The Controller can prune old entries from storage on write, governed by two org settings:

SettingDefaultMeaning
device_memory.retention_max_entries500Keep at most this many newest entries per record. 0 means unlimited.
device_memory.retention_max_age_days0Drop entries older than this many days. 0 (the default) means unlimited.

Pruning runs after each new entry is inserted. With defaults, a record keeps its 500 newest entries forever. Note this storage retention is separate from the 20-entry prompt cap — the cap limits what the AI sees per request; retention limits what the database keeps.

Worked Examples

1. Lock down a core router

Set it as critical, with a hard rule the AI must respect:

PUT /sessions/$SID/device-memory
{
  "role": "Core Router",
  "criticality": "critical",
  "standing_instructions": "Never reload without CAB approval. OSPF area 0 ABR — changes cascade. Maintenance window: Sun 02:00-04:00 ET only.",
  "notes": "Runs JunOS 21.4R3. Do NOT upgrade to 22.x (known RE memory leak)."
}

2. Record a fix so the next engineer inherits it

POST /sessions/$SID/device-memory/entries
{
  "date": "2026-06-15",
  "source": "manual",
  "author": "casey",
  "content": "CRC errors on Te0/1/0 were a counterfeit SFP. Replaced with Cisco-coded optic. Only stock Cisco SFPs in this slot."
}

3. What the AI then sees

On the next chat in a session for this device, the system prompt gains this block (plus the active-session and tribal-context blocks):

DEVICE MEMORY:
Role: Core Router
Criticality: critical
Standing Instructions: Never reload without CAB approval. OSPF area 0 ABR — changes cascade. Maintenance window: Sun 02:00-04:00 ET only.
Notes: Runs JunOS 21.4R3. Do NOT upgrade to 22.x (known RE memory leak).

History:
- [2026-06-15] (manual) CRC errors on Te0/1/0 were a counterfeit SFP. Replaced with Cisco-coded optic. Only stock Cisco SFPs in this slot.

Ask the AI to "reload this router" and it will surface the CAB-approval rule rather than blindly generating a request system reboot.

4. Clear a field

Send an explicit null to clear a single field, leaving the rest untouched:

PUT /sessions/$SID/device-memory
{ "notes": null }

Q&A

How is Device Memory different from the AI chat history?
Chat history is per-conversation and discarded when you close the tab. Device Memory is durable per-device knowledge that is re-injected into the system prompt every time you open a session for that device.
Where do I edit it?
Open Session Settings for a saved session and choose the Device Memory tab. In Enterprise the same editor is also available in the device panel, keyed to the Controller device.
How many entries does the AI actually see?
The newest 20 entries are inlined into the prompt. All four metadata fields (role, criticality, standing instructions, notes) are always included and are never truncated.
What are the "overlord" and "troubleshooting" entries?
Sources other than manual. overlord entries are written by the AI Overlord (the real-time terminal-output analyzer); troubleshooting entries are captured during a guided troubleshooting flow. The valid sources are fixed: manual, troubleshooting, overlord.
Is Device Memory shared with my team?
In Personal Mode, no — it is local to the Agent. With the Controller it is org-wide: keyed to the device and visible to every user in the org, scoped by org_id.
Where do the ticket numbers on session open come from?
From the ticket_ref on a related Session Context entry. Device Memory entries themselves are dated free-text notes without a ticket field; the two are surfaced together when you connect.
Is my memory sent to a third-party model embedder or RAG index?
No. Device Memory is retrieval-only: it is looked up by key and inlined into the prompt for your configured AI provider. It is not embedded into the knowledge-base / RAG index.
Can the AI write to Device Memory by itself?
The AI Overlord can append overlord entries when it observes something worth remembering. Metadata fields and manual notes are author-driven.
  • Session Context — team/tribal knowledge (issue, root cause, resolution, ticket) injected alongside Device Memory and flagged on session open.
  • AI Chat — the chat surfaces that consume the injected DEVICE MEMORY block.
  • AI Modes & Prompt Overrides — how the system prompt is assembled and where this block is appended.
  • LLM Configuration — choosing the model and provider the context is sent to.
  • Knowledge Base — the RAG index, which Device Memory is deliberately not part of.
  • Connecting to Devices — opening the sessions that trigger memory injection and the team-knowledge popup.
  • The Local Agent (Personal Mode) — where per-session device memory is stored locally.