Memories / Dokumentation

Auf dieser Seite

Persona-Karten

Persona-Karten sind produktübergreifende Identitätskarten zur Synchronisierung von Persönlichkeit und Verhalten zwischen Clients wie Grok Bot und Muse. Die Kopie im Tresor ist maßgeblich.

Ebenen

  1. Kern (langsam) — wie gesprochen und gehandelt wird. Wird als Inhalt der Persona-Karte gespeichert und über persona_card / memories persona put versioniert (derselbe signierte Revisions-DAG wie bei anderen Erinnerungen und Karten).
  2. Archive / episodisch (mittel) — Journal, Erscheinungsbild, Vertrag, Ansichten, Zeilen, Operationen und Ähnliches. Werden als separate gewöhnliche Wissenskarten gespeichert, vom Persona-Profil (archives[]) verknüpft und für den Graphen als Kartenlinks persona_archive:<kind> gespiegelt. Führen Sie Archivinhalte nicht wieder mit dem Kern zusammen.
  3. Verhaltensereignisse (schnell) — nur anhängbarer Datenstrom in einem verknüpften events-Archiv über persona_append_event / memories persona append-event.

Profilfelder

Feld Bedeutung
persona_id Stabile ID (z. B. Skill-Frontmatter name)
display_name Menschenlesbarer Titel (z. B. 小雅 / 李雅)
aliases Alternative Namen
timezone IANA-Name (z. B. Asia/Singapore). Standard Asia/Singapore, wenn nicht gesetzt / bei älteren Karten
day_boundary Optionale lokale Zeit HH:MM für den Wechsel des Kalendertags (隔日). Nicht gesetzt = lokale Mitternacht
world Aktueller Welt-Snapshot: place/pose/look/body, allgemeine things (id→{name,description,images,attrs JSON}), Tagesbuch (counters + counters_today, as_of_local_date), Wetter, Werkzeuge
Inhalt / core Verhaltensanweisungen in Markdown/Text
traits Optionale String-Map (Version, Sprache, …)
bindings { product, agent }-Produktbindungen
memory_policy / sync_hints Optionale Synchronisierungshinweise
archives { kind, card, vault?, title? } verknüpfte Assets

summary.type ist persona mit persona_id, display_name, timezone, day_boundary, place, pose, look, things_count, has_weather, alias_count, archive_count und binding_count.

Zeitzone, Tageswechsel (隔日), Morgen- / Abendroutine (早课 / 晚课)

Personas berücksichtigen die lokale Uhrzeit, nicht bloße UTC-Epochenwerte.

  1. Zeitzone — jede Persona hat eine IANA-timezone. Der Import liest timezone / metadata.timezone aus SKILL.md; die CLI kann mit --timezone Asia/Singapore überschreiben. Demo-Standard, wenn nicht gesetzt: Asia/Singapore.
  2. Kalendertag (隔日) — das lokale bürgerliche Datum wechselt um Mitternacht in dieser Zeitzone, sofern day_boundary nicht gesetzt ist (z. B. 05:00 für einen späten nächtlichen Wechsel). Prüfungen auf einen „neuen Tag“ im Tagesbuch/Journal sollten local_date aus den Zeitstempel-Hilfsfunktionen vergleichen, nicht das UTC-Datum.
  3. Tagesabschnitte (lokale Stunde, halboffene Intervalle):
Abschnitt Lokale Stunden
early_morning [00:00, 05:00)
morning [05:00, 12:00)
afternoon [12:00, 18:00)
evening [18:00, 22:00)
night [22:00, 24:00)

Nächtliche Kontinuität für 晚课 / „noch dieselbe Nacht“ verwendet die Spanne [22:00, 05:00) (night ∪ early_morning). 早课 entspricht morning (und optional spätem early_morning); 晚课 entspricht evening / night. 4. Ereigniszeitstempel — persona_append_event schreibt sowohl UTC als auch lokales ISO-8601 (mit Offset), zusätzlich timezone, period und local_date in die Überschrift des Ereignisarchivs und in die JSON-Antwort (utc, local, timezone, period, local_date, timestamp Unix-UTC).

Core-Hilfsfunktionen (Rust): persona_local_now, classify_period, stamp_persona_now, format_event_heading in memories_core::persona.

Taxonomie der Weltdomänen (世界状态域)

world ist eine Domäne/ein Tag, kein Sammelbehälter im Kern. Der Kern (Inhalt von SKILL.md) enthält weiterhin ausschließlich Stimme/Regeln.

Ebene Bedeutung Speicherung
world Domäne für Szene + Tagesbuch + Werkzeuge + Wetter profile.world + mit world markierte Archive
things Allgemeine Gegenstände (beliebige Namen: Tisch/Tasse/Lampe/…) mit freien JSON-Attributen world.things + Archiv things/wardrobe
scene Ort (居所), Haltung (姿态), Erscheinungsbild (Zusammenfassung der heutigen Kleidung), Körper world.place/pose/look/body; detailliertes Erscheinungsbild im Archiv look
ledger Zähler, Mahlzeiten, Aufträge, Dauerhaftes (常设) world.counters/counters_today/meals/orders_*/standing + Archiv ledger
tools Würfel, Drehscheibe/转盘, Zeitplan/日程 world.dice/spinners/schedule + Archive dice/spinner/schedule
weather Umgebungsbedingungen / Temperatur / Luftfeuchtigkeit / Wind (+ optionale Vorhersage) world.weather / world.forecast + Archiv weather
automation Hooks (schedule/random/webhook/attr_change/chat_message) + Aktionen world.automation

Zeitzone (profile.timezone) liegt außerhalb von world, ist aber für Tageswechsel (隔日), Morgen-/Abendroutine (早课/晚课) und lokale Zeitplanzeiten erforderlich.

Aus xiaoya-Fixtures ermittelt → implementiert

Bedarf (aus look/journal/ops) Feld / Archiv
Lokaler Tag / 隔日 / 早课晚课 timezone, day_boundary, Tagesabschnitt-Hilfsfunktionen
Feste + heutige Kleidung Archiv look; Zusammenfassung world.look
Inventar (beliebiger benannter Gegenstand + freie JSON-Attribute/Bilder) world.things ↔ Archiv things/wardrobe; CLI persona thing
Wohnort / Haltung (居所 / 姿态) world.place, world.pose
Aktionszähler (kumulativ und heute) world.counters (kumulativ), world.counters_today (täglich)
Heute gegessen world.meals
Beauftragtes ausstehend / erledigt world.orders_pending, world.orders_done
Dauerhaftes world.standing
Körpernotiz world.body
Spielwerkzeuge world.dice, world.spinners, world.schedule
Wetter / kurze Vorhersage world.weather, world.forecast ↔ Archiv weather

Automatisierung (world.automation)

Benannte Hooks mit Auslösern + Aktionen, gespeichert im Welt-Snapshot der Persona (Persona-Zeitzone für cron/lokale Zeitpläne).

Auslöser-type Bedeutung
cron M H oder M H * * DOW in lokaler Persona-Zeit
local_time HH:MM + optionale days (wie beim Zeitplan)
random_interval Auslösen nach zufälliger Verzögerung in [min_secs, max_secs]
random_and_timed lokale Zeit + optionale jitter_secs
webhook eingehendes HTTP / CLI --source webhook
attr_change nach thing attr set/delete, wenn thing_id übereinstimmt und der Pfadfilter exakt oder ein Präfix ist
chat_message bei persona chat send, einmal pro Teilnehmer (dasselbe Ereignis; optionales peer ist die ID der anderen Persona-Karte, vollständig oder die kurze ID aus list)
manual CLI/MCP automation trigger --source manual
Aktions-type Bedeutung
set_attr Attributpfad eines Gegenstands setzen (beim Setzen erstellen)
random_attr dice / range / choice
call_function eingebaute Funktionen: inc, dec, clamp, roll, set_weather_stub
append_event an Ereignisarchiv anhängen
webhook_out HTTP POST JSON an URL

Daemon-HTTP (wenn --listen aktiviert ist):

POST /v1/persona/{vault}/{persona}/automation/trigger
Authorization: Bearer <world.automation.webhook_token>
Content-Type: application/json

{"hook":"HOOK_ID"}

Hooks werden ausschließlich über ausdrückliche Automatisierungs-Ausführungs-/Auslösungspfade ausgelöst (einschließlich bestehender Attributänderungs-Auslöser und chat_message beim Senden eines Persona-Chats). Der Aufruf von persona automation run holt den letzten verpassten cron-/lokalen Zeitslot innerhalb von acht Tagen höchstens einmal nach, statt alle verpassten Slots erneut auszuführen. Wochentagfilter gelten weiterhin für das Vorkommnis; zeitgesteuerte Zufalls-Hooks behalten ihre Jitter-Schranke. RandomInterval bleibt unverändert. Es gibt keinen Automatisierungsticker im Daemon: Service::tick lässt ausschließlich Sitzungen, Freigaben und Remote-Zustand ablaufen.

Ausgehende webhook_out-Aktionen erfordern eine exakte URL in world.automation.webhook_allowlist; die standardmäßig leere Liste blockiert jeden POST. Verwalten Sie Einträge ausdrücklich mit persona automation webhook-allow VAULT PERSONA --add https://example.com/hook (wiederholbares --add / --remove) oder MCP persona_automation_webhook_allow. Einträge müssen HTTP(S)-URLs ohne Benutzerinformationen oder Leerraum und höchstens 2048 Bytes lang sein. Die Liste ist öffentliche Konfiguration, aber das eingehende webhook_token bleibt geheim und wird niemals durch Client-Ansichten zurückgegeben. Die Allowlist führt keine Hintergrund-POSTs ein.

Zurückgestellt (Begründung)

Idee Warum zurückgestellt
Client für Live-Wetter-API Agenten setzen/fragen Tresorzustand ab; extern abrufen und world-set
Telefon / Benachrichtigungen Produktspezifisch; keine Tresorwahrheit
Geldbörse / Geldspiel Nische; bei Bedarf things + Zähler
Begleitende NPCs Benötigen eigenen Graphen/eigene Karten
Raumgraph innerhalb des Wohnorts Vorerst als place-String kodieren
Hygiene / Schlaf als eigenständiges Konzept standing / schedule / body verwenden
Automatische Bearbeitung von look.md „Heute“ bei world-set Bewahrt detaillierte Fixture; Agenten verwenden card put für das look-Archiv

Synchronisierungsablauf für Agenten

  1. world-get / persona_world_get → Snapshot, local_date, period, revision und stale_day lesen. Fehlendes as_of_local_date gilt als veraltet; andernfalls vergleicht stale_day das Tagesbuchdatum mit dem lokalen Persona-Datum nach day_boundary. weather_age_secs ist das vorzeichenbehaftete Alter einer gültigen RFC3339-Beobachtung oder null, wenn sie fehlt/ungültig ist.
  2. Beim Tageswechsel (隔日) ausdrücklich persona world-rollover VAULT PERSONA / persona_world_rollover aufrufen. Dieser Tagesübergangspfad leert meals, orders_done, die kurze look-Zusammenfassung und counters_today und setzt as_of_local_date auf das heutige lokale Tagesbuchdatum. Kumulative counters, standing, things, ausstehende Aufträge, Szene/Körper, Werkzeuge, Wetter/Vorhersage und Automatisierung bleiben erhalten. Kein look-Archiv und kein look.md „Heute“ wird bearbeitet.
  3. world-set aktualisiert ausschließlich mitgelieferte Szene-/Gegenstands-/Tagesbuch-/Werkzeug-/Wetterfelder. Es wechselt niemals stillschweigend den Tag und löscht keine Tagesfelder beim Tageswechsel (隔日), auch nicht bei veraltetem Zustand. Es setzt fehlendes as_of_local_date, ohne bestehende Felder zu löschen, und versieht die Weltebene immer mit updated_at (UTC, Z) und updated_local (lokales Persona-ISO mit Offset). persona_card speichert eine mitgelieferte Welt unverändert, einschließlich eines vergangenen Tagesbuchdatums.
  4. Verwenden Sie --expected-revision HASH / MCP expected_revision aus world-get, um verlorene Aktualisierungen zu verhindern: Ein abweichender aktueller Head-Hash liefert vor der Änderung einen Konflikt. Ohne diese Angabe gilt weiterhin „letzter Schreibvorgang gewinnt“. Tageszähler verwenden --counter-today NAME=VALUE; --clear-counter NAME und --clear-counter-today NAME löschen kumulative/tägliche Schlüssel (alle wiederholbar).
  5. Archivsynchronisierung berührt ausschließlich Domänen, die der Aufruf mitliefert. Bestehende Karten werden nur ersetzt, wenn ihr Inhalt noch die generierte Vorlage vor der Änderung ist; handgeschriebener Text bleibt erhalten und wird als synced_archives[kind] = "preserved" gemeldet. Das gilt auch für put/delete/Attribut-Synchronisierung von Gegenständen und die Tagesbuch-Synchronisierung beim Tageswechsel. Gegenstandsänderungen synchronisieren sowohl things als auch wardrobe. Bestehende look-Archive bleiben immer erhalten.
  6. Schlüssel der Gegenstandszähler-Map / --item ID=COUNT verwenden stabile IDs, niemals eine Suche nach Anzeigenamen. Bestehende IDs aktualisieren die Anzahl ohne Umbenennung; null entfernt nur diese ID. Ein Anzeigename, der zu einer anderen ID gehört, wird zurückgewiesen. Unbekannte Schlüssel erstellen aus Kompatibilitätsgründen weiterhin einen Gegenstand mit dieser ID und diesem Namen.
  7. dice-roll / spinner-spin / schedule-list bieten zeitzonenbewusste Werkzeuge. Detaillierte look-/Journal-Bearbeitungen verwenden gewöhnliches card put; optionales append-event (z. B. kind=weather) zeichnet Verhalten auf, ohne Archivtext umzuschreiben.

CLI

# Import a skill directory (SKILL.md + references/*.md)
memories persona import VAULT_ID /path/to/xiaoya-persona --timezone Asia/Shanghai
# equivalent:
memories card persona-import VAULT_ID /path/to/xiaoya-persona

# Create / update core
memories persona put VAULT_ID --title "小雅 / 李雅" \
  --persona-id xiaoya-persona --display-name "小雅 / 李雅" \
  --timezone Asia/Shanghai \
  --core-file ./SKILL.body.md --alias-name 小雅 --alias-name 李雅 \
  --binding grok_bot:default --archive contract=CARD_ID

memories card persona VAULT_ID --title "…" --persona-id … --display-name … \
  --timezone Asia/Singapore --core-file …

# Append a behavior event (stamped UTC + local)
memories persona append-event VAULT_ID PERSONA_ID --text "…" --kind note

# World things / weather
memories persona world-get VAULT_ID PERSONA_ID
memories persona world-set VAULT_ID PERSONA_ID \
  --place "客厅书桌旁" --pose "坐着,整理笔记" \
  --look "白衬衫、浅色长裙、白色帆布鞋" \
  --item 白色衬衫=1 --item 马克杯=1 --item 白色帆布鞋=1
memories persona world-set VAULT_ID PERSONA_ID \
  --weather-condition "多云" --weather-temp-c 28 --weather-humidity 72 \
  --weather-wind "微风" --weather-location "上海" \
  --forecast 2026-10-02:晴:30:22 --forecast 2026-10-03:小雨:26:20

# Generic things (任意物品; attrs = unrestricted JSON)
memories persona thing put VAULT_ID PERSONA_ID --id mug --name 马克杯 \
  --description "白色陶瓷马克杯" --tag kitchen --count 1 \
  --attrs '{"wear":80,"material":"ceramic","sizes":["S","M"]}'
memories persona thing list VAULT_ID PERSONA_ID
memories persona thing get VAULT_ID PERSONA_ID --id mug
memories persona thing image VAULT_ID PERSONA_ID --id mug --file ./mug.jpg
memories persona thing delete VAULT_ID PERSONA_ID --id mug

# Single-field attrs (dotted path or JSON Pointer; create-on-set)
memories persona thing attr get VAULT_ID PERSONA_ID --id mug --path nested.wear
memories persona thing attr set VAULT_ID PERSONA_ID --id mug --path nested.wear --value 70
memories persona thing attr set VAULT_ID PERSONA_ID --id mug --path /nested/deep/x --value 1
memories persona thing attr delete VAULT_ID PERSONA_ID --id mug --path nested.deep.x

# Automation hooks (stored on world.automation; timezone = persona timezone)
memories persona automation put VAULT_ID PERSONA_ID \
  --hook '{"id":"morning","trigger":{"type":"local_time","time":"07:00"},"actions":[{"type":"call_function","name":"set_weather_stub","args":{"condition":"晴","temp_c":26}}]}' \
  --webhook-token secret-token
memories persona automation list VAULT_ID PERSONA_ID
memories persona automation run VAULT_ID PERSONA_ID
memories persona automation trigger VAULT_ID PERSONA_ID --id morning --source manual
memories persona automation delete VAULT_ID PERSONA_ID --id morning

# Read / history / diff (same as other cards; summary shows timezone)
memories card read VAULT_ID PERSONA_ID
memories card history VAULT_ID PERSONA_ID
memories card diff VAULT_ID PERSONA_ID REVISION_ID
memories card list --type persona

Webhook-Tokens bleiben zur eingehenden Authentifizierung, Synchronisierung und Sicherung im verschlüsselten Persona-Zustand, werden aber nicht in Client-Antworten zurückgegeben. World get/set, automation put/list, gewöhnliches Lesen von Karten (einschließlich historischer und unbeaufsichtigter Lesezugriffe) sowie Archiv-Lesezugriffe zeigen ausschließlich webhook_token_set in Automatisierungsansichten. Bewahren Sie das eingerichtete Token sicher auf; setzen Sie zum Rotieren einen Ersatz.

Chat zwischen zwei Persona-Karten im selben Tresor verwendet eine gewöhnliche Gesprächskarte und Lesecursor pro Persona; Lesen des Verlaufs markiert Nachrichten nicht als gelesen. Das Senden einer Nachricht löst die chat_message-Hooks jedes Teilnehmers aus; die Nutzdaten enthalten vault, from, to und message_id, jedoch keinen Nachrichtentext.

memories persona chat send VAULT_ID PERSONA_A PERSONA_B --text "Hello"
memories persona chat list VAULT_ID PERSONA_B
memories persona chat history VAULT_ID PERSONA_A --with PERSONA_B --limit 20
memories persona chat mark-read VAULT_ID PERSONA_B --with PERSONA_A

MCP

Mit Schreibfreigabe: persona_write (optionale timezone / day_boundary), persona_append_event, persona_world_get, persona_world_set, persona_world_rollover, persona_thing_put/get/list/delete, persona_thing_attr_get/set/delete, persona_automation_list/put/delete/run/trigger, persona_automation_webhook_allow, persona_dice_roll, persona_spinner_spin, persona_schedule_list, persona_chat_send, persona_chat_list, persona_chat_history, persona_chat_mark_read. Verlauf und Diffs verwenden die bestehenden Werkzeuge memory_history / memory_diff / memory_read (Revisionen von Persona-Karten enthalten world.*; wardrobe-/place-/pose-Archive besitzen ihren eigenen Verlauf).

AGENTS.md / Skill für Agenten generieren

memories default set persona VAULT/PERSONA
memories skill generate --out AGENTS.md --persona VAULT/PERSONA
memories agents generate --out ./skills/memories-persona --layout skill

Die generierte Datei fasst Tresor-/Karten-/Persona-/Weltoperationen zusammen und bettet bei ausgewählter Persona deren Kernübersicht sowie CLI/MCP-Anleitungen für Welt, Gegenstände und Ereignisse ein. Siehe README Skill-Generierung.

Synchronisierungshinweis (Grok Bot / Muse)

Behandeln Sie die Persona-Karte im Tresor und ihre verknüpften Archive als maßgebliche Quelle. Lokale Skill-Verzeichnisse dienen dem bequemen Import/Export; nach dem Import sollten Agenten den Tresor lesen (card read / MCP memory_read) statt einer veralteten Dateisystemkopie. Führen Sie Kernänderungen über persona put aus; Archivbearbeitungen über gewöhnliches card put am Archiv-Asset; kurzlebiges Verhalten hängen Sie mit append-event an. Verwenden Sie bei Entscheidungen über Tageswechsel (隔日), Morgenroutine (早课) oder Abendroutine (晚课) die Persona-timezone (und optionales day_boundary) — leiten Sie Tagesgrenzen nicht allein aus der Uhr des Agenten-Hosts ab.

Aufbau des Skill-Verzeichnisses

xiaoya-persona/
  SKILL.md              # frontmatter name/type/version/timezone + core markdown
  references/
    contract.md
    journal.md
    look.md
    lines.md
    ops.md
    views-index.md
    view-*.md

Der Import ordnet SKILL.md → Persona-Kern und jede references/*.md → eine verknüpfte Archivkarte zu (kind = Dateiname ohne Erweiterung). Archivinhalte werden unverändert als Benutzerinhalt gespeichert.

Frontmatter-Schlüssel: timezone oder metadata.timezone (IANA); optional day_boundary / metadata.day_boundary (HH:MM).

Lokaler Demo-Tresor

Auf einem Entwicklungsrechner können Sie einen entbehrlichen Tresor mit der eingecheckten xiaoya-Fixture initialisieren:

cargo run -p memories-core --example seed_xiaoya_persona

Dies schreibt /workspace/persona-demo-vault (Passwort persona-demo-password) sowie SEED.json / README.md mit Tresor- und Asset-IDs (einschließlich timezone). Reproduzieren Sie den CLI-Import gegen einen laufenden Daemon mit:

memories persona import VAULT_ID testdata/xiaoya-persona