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

# 30min User Workshop: Memory Agent

> Plug an agent into your data — manifest workspace, profiles, MCP, and memory layers with zero glue code.

<Note>
  This workshop is a docs transcript of the `demos/user/` onboarding track. Each step maps to a runnable script in the HeavenBase repository.
</Note>

You will open a workspace from a manifest, query data three ways, configure a declarative MCP profile, and use `memory` / `memstate` profiles as a persistent note layer. No API keys are required.

<br />

## 1. Prerequisites

Install HeavenBase and sync the environment from a source checkout:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
git clone https://github.com/Magolor/HeavenBase.git
cd HeavenBase
rtk bash scripts/sync-env.bash
```

All demo artifacts write under `demos/.temp/` only.

<br />

## 2. Open a Workspace from a Manifest

**Script:** `demos/user/01_workspace_from_manifest.py`

Write `workspace.yaml`, open it with `WorkspaceManifest`, and CRUD a first entity:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import heavenbase as hb
from heavenbase.utils.files import pj, touch_dir

TEMP = touch_dir(pj("demos/.temp/user-01", abs=True))

manifest = hb.WorkspaceManifest(
    id="user-01-manifest",
    config={"backends": {"main": {"type": "inmem"}}},
    entities=[
        {
            "entity_id": "product",
            "name": "Product",
            "fields": {
                "object_id": {"type": "identifier", "pk": True},
                "name": {"type": "short-text"},
                "price": {"type": "float"},
                "body": {"type": "long-text"},
            },
        }
    ],
)
manifest.save(pj(TEMP, "workspace.yaml", abs=True))

ws = hb.HeavenBase.from_manifest(hb.WorkspaceManifest.load(pj(TEMP, "workspace.yaml", abs=True)))
desk_id = ws.upsert("product", {"object_id": "p-desk", "name": "Oak Desk", "price": 95.0, "body": "compact oak desk"})
ws.set(desk_id, {"price": 89.0}, entity="product")

frame = ws.query("product").where({"price": {"$lte": 100}}).select("name", "price").execute()
print(frame.to_str())
```

Run:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
rtk uv run python demos/user/01_workspace_from_manifest.py
```

<br />

## 3. Query Three Ways

**Script:** `demos/user/02_query_three_ways.py`

Ask the same product question with the Python DSL, Mongo-style `where({...})`, and `query_json`, then inspect routing with `explain()`:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import heavenbase as hb

ws = hb.HeavenBase("user-02-query", backends={"main": {"type": "inmem"}})
# register Product entity, seed rows ...

py_frame = (
    ws.query("product")
    .where({"price": {"$lte": 130}, "body": {"$match": "audio"}})
    .select("name", "price")
    .limit(2)
    .execute()
)

json_frame = ws.query_json(
    "product",
    {
        "filter": {"price": {"$lte": 130}, "body": {"$match": "audio"}},
        "select": ["name", "price"],
        "limit": 2,
    },
).execute()

explain = ws.query("product").where({"body": {"$match": "audio"}}).explain()
print(explain)
```

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
rtk uv run python demos/user/02_query_three_ways.py
```

<br />

## 4. Profiles and MCP

**Script:** `demos/user/03_profiles_and_mcp.py`

Enable `agent` and `memory`, register a config `ProfileSpec`, print MCP serve JSON, and simulate agent tool calls in-process:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import heavenbase as hb
import heavenbase.ext as ext
from heavenbase.extensions.system.toolkit.profiles import profile_spec_from_mapping, register_profile

register_profile(
    profile_spec_from_mapping(
        "user-demo",
        {
            "extends": ["agent"],
            "entities": ["agent-product"],
            "skills": ["*"],
            "serializer": "markdown",
        },
    ),
    replace=True,
)

ws = hb.HeavenBase("user-03-profiles", backends={"main": {"type": "inmem"}})
ws.enable_extension("agent")
ws.enable_extension("memory")
ws.register({...})  # agent-product entity
ws.upsert("agent-product", {"object_id": "p1", "name": "Desk", "price": 80})

print(ws.to_mcp_json(name="user-03-heavenbase", profile="user-demo", host="127.0.0.1", port=7011))

toolkit = ws.to_mcp(profile="user-demo")
print(toolkit.run_to_str("query", entity="agent-product", spec={"select": ["name", "price"]}))
print(toolkit.run("read_skill", skill_name="workspace-guide")["text"].splitlines()[0])

memory = ws.to_mcp(profile="memory")
memory.run("remember", key="onboarding", text="Profiles v2 scope entities, skills, and serializers.")
```

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
rtk uv run python demos/user/03_profiles_and_mcp.py
```

<br />

## 5. Memory and Memstate Layers

**Script:** `demos/user/04_memory_layer.py`

Use `profile="memory"` for flat notes and `profile="memstate"` for versioned project keypaths:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import heavenbase as hb

ws = hb.HeavenBase("user-04-memory", preset="debug")
memory = ws.to_mcp(profile="memory")
memstate = ws.to_mcp(profile="memstate")

memory.run("remember", key="setup", text="Use uv sync; demos write only to demos/.temp/.", tags=["setup"])
memory.run("search_memory", text="uv sync")

memstate.run("memstate_set", project_id="demo", keypath="prefs.theme", value="dark")
memstate.run("memstate_remember", project_id="demo", keypath="docs/readme", content="v2 notes")
memstate.run("memstate_history", project_id="demo", keypath="docs/readme")
memstate.run("memstate_delete", project_id="demo", keypath="docs/readme")
```

Both profiles auto-enable the optional `memory` extension on first use.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
rtk uv run python demos/user/04_memory_layer.py
```

<br />

## Summary

* You opened a workspace from a manifest, queried data three ways, and inspected routes with `explain()`.
* Declarative `ProfileSpec` objects scope entities, skills, and serializers for MCP agents.
* `memory` and `memstate` profiles store agent notes as normal HeavenBase rows.

<br />

## Further Exploration

<Tip>
  **Related resources:**

  * [Workspace manifests](/features/workspace-manifest) — Replay construction config and extensions
  * [First MCP](/quickstart/first-mcp) — Serve workspace and Capsule toolkits
  * [Agent extension](/features/agent-extension) — Persistent sessions, skills, and recipes
  * [User demo track](https://github.com/Magolor/HeavenBase/tree/master/demos/user) — Full runnable scripts
</Tip>

<br />
