Memories / Documentación

En esta página

Tarjetas de persona

Las tarjetas de persona son tarjetas de identidad entre productos que sincronizan la personalidad y el comportamiento entre clientes como Grok Bot y Muse. La copia de la bóveda es la autoridad.

Capas

  1. Núcleo (lento) — cómo hablar y actuar. Se guarda como cuerpo de la tarjeta de persona y se versiona mediante persona_card / memories persona put (el mismo DAG de revisiones firmadas que las demás memorias y tarjetas).
  2. Archivos / episódicos (medio) — diario, apariencia, contrato, opiniones, frases, operaciones y similares. Se guardan como tarjetas de conocimiento normales separadas, enlazadas desde el perfil de persona (archives[]) y reflejadas como enlaces de tarjetas persona_archive:<kind> para el grafo. No reincorpore el contenido de los archivos al núcleo.
  3. Eventos de comportamiento (rápido) — flujo de solo adición en un archivo events enlazado mediante persona_append_event / memories persona append-event.

Campos del perfil

Campo Significado
persona_id ID estable (p. ej., name en los metadatos iniciales de la habilidad)
display_name Título legible (p. ej., 小雅 / 李雅)
aliases Nombres alternativos
timezone Nombre IANA (p. ej., Asia/Singapore). Predeterminado: Asia/Singapore si no se establece o en tarjetas antiguas
day_boundary HH:MM local opcional en que cambia el día del calendario. Sin establecer = medianoche local
world Instantánea actual del mundo: place/pose/look/body, objetos genéricos things (id→{name,description,images,attrs JSON}), registro (counters + counters_today, as_of_local_date), tiempo meteorológico, herramientas
cuerpo / core Instrucciones de comportamiento en Markdown/texto
traits Mapa opcional de cadenas (versión, idioma, …)
bindings Vinculaciones de producto { product, agent }
memory_policy / sync_hints Orientaciones opcionales de sincronización
archives Recursos enlazados { kind, card, vault?, title? }

summary.type es persona, con persona_id, display_name, timezone, day_boundary, place, pose, look, things_count, has_weather, alias_count, archive_count y binding_count.

Zona horaria, cambio de día y sesiones matutinas / nocturnas

Las personas razonan con la hora local del reloj, no con épocas UTC sin contexto.

  1. Zona horaria — cada persona tiene una timezone IANA. La importación lee timezone / metadata.timezone de SKILL.md; CLI puede sobrescribirla con --timezone Asia/Singapore. Valor predeterminado de la demostración si no se establece: Asia/Singapore.
  2. Día del calendario — la fecha civil local cambia a medianoche en esa zona horaria, salvo que se establezca day_boundary (p. ej., 05:00 para un cambio de día de madrugada). Las comprobaciones de «nuevo día» del registro o diario deben comparar local_date de las funciones de marcas temporales, no la fecha UTC.
  3. Períodos del día (hora local, intervalos semiabiertos):
Período Horas locales
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)

La continuidad nocturna para las sesiones nocturnas o «sigue siendo la misma noche» usa [22:00, 05:00) (night ∪ early_morning). La sesión matutina corresponde a morning (y opcionalmente al final de early_morning); la sesión nocturna corresponde a evening / night. 4. Marcas de eventos — persona_append_event escribe tanto UTC como ISO-8601 local (con desplazamiento), además de timezone, period y local_date, en el encabezado del archivo de eventos y la respuesta JSON (utc, local, timezone, period, local_date, timestamp Unix UTC).

Funciones del núcleo (Rust): persona_local_now, classify_period, stamp_persona_now, format_event_heading en memories_core::persona.

Taxonomía de dominios del mundo

world es un dominio/etiqueta, no un volcado en el núcleo. El núcleo (cuerpo de SKILL.md) solo contiene voz y reglas.

Capa Significado Almacenamiento
world Dominio para escena + registro + herramientas + tiempo meteorológico profile.world + archivos etiquetados world
things Objetos genéricos (cualquier nombre: mesa/taza/lámpara/…) con atributos JSON libres world.things + archivo things/wardrobe
scene lugar (residencia), postura, apariencia (resumen del atuendo de hoy), cuerpo world.place/pose/look/body; apariencia detallada en el archivo look
ledger contadores, comidas, órdenes, condiciones permanentes world.counters/counters_today/meals/orders_*/standing + archivo ledger
tools dados, ruleta, agenda world.dice/spinners/schedule + archivos dice/spinner/schedule
weather Condiciones ambientales / temperatura / humedad / viento (+ pronóstico opcional) world.weather / world.forecast + archivo weather
automation Hooks (schedule/random/webhook/attr_change/chat_message) + acciones world.automation

La zona horaria (profile.timezone) está fuera de world, pero es necesaria para el cambio de día, las sesiones matutinas/nocturnas y las horas locales de la agenda.

Investigado a partir de las muestras xiaoya → implementado

Necesidad (de apariencia/diario/operaciones) Campo / archivo
Día local / cambio de día / sesiones matutinas y nocturnas timezone, day_boundary, funciones de períodos
Atuendo fijo + atuendo de hoy archivo look; resumen world.look
Inventario (cualquier objeto con nombre + atributos JSON/imágenes libres) world.things ↔ archivo things/wardrobe; CLI persona thing
Residencia / postura world.place, world.pose
Contadores de acciones (acumulados y de hoy) world.counters (acumulados), world.counters_today (diarios)
Comidas de hoy world.meals
Órdenes pendientes / completadas world.orders_pending, world.orders_done
Condiciones permanentes world.standing
Nota sobre el cuerpo world.body
Utilidades de juego world.dice, world.spinners, world.schedule
Tiempo meteorológico / pronóstico breve world.weather, world.forecast ↔ archivo weather

Automatización (world.automation)

Hooks con nombre, desencadenadores y acciones, guardados en la instantánea del mundo de la persona (zona horaria de la persona para cron y horarios locales).

Desencadenador type Significado
cron M H o M H * * DOW en hora local de la persona
local_time HH:MM + days opcional (igual que la agenda)
random_interval se activa tras un retraso aleatorio en [min_secs, max_secs]
random_and_timed hora local + jitter_secs opcional
webhook HTTP entrante / CLI --source webhook
attr_change después de thing attr set/delete cuando coincide thing_id y el filtro de ruta es exacto o un prefijo
chat_message al ejecutar persona chat send, una vez por participante (mismo evento; peer opcional es el ID de la tarjeta de la otra persona, completo o abreviado del listado)
manual CLI/MCP automation trigger --source manual
Acción type Significado
set_attr establece la ruta de atributos del objeto (crea al establecer)
random_attr dice / range / choice
call_function funciones integradas: inc, dec, clamp, roll, set_weather_stub
append_event añade al archivo de eventos
webhook_out HTTP POST JSON a una URL

HTTP del daemon (cuando está activo --listen):

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

{"hook":"HOOK_ID"}

Los hooks solo se activan por rutas explícitas de ejecución o activación de automatización (incluidos los desencadenadores existentes de cambios de atributos y chat_message al enviar chats de persona). Invocar persona automation run recupera la última ocurrencia cron/de hora local omitida dentro de ocho días, como máximo una vez, en lugar de reproducir todas las ocurrencias omitidas. Los filtros de días de la semana siguen aplicándose a la ocurrencia; los hooks de tiempo con aleatoriedad mantienen su condición de fluctuación temporal. RandomInterval no cambia. No hay un temporizador de automatización en el daemon: Service::tick solo hace caducar sesiones, autorizaciones y estado remoto.

Las acciones salientes webhook_out requieren una URL exacta en world.automation.webhook_allowlist; la lista vacía predeterminada bloquea todos los POST. Gestione las entradas explícitamente con persona automation webhook-allow VAULT PERSONA --add https://example.com/hook (--add / --remove repetibles) o MCP persona_automation_webhook_allow. Las entradas deben ser URL HTTP(S) sin información de usuario ni espacios en blanco, de como máximo 2048 bytes. La lista es configuración pública, pero el webhook_token entrante permanece secreto y nunca se devuelve en las vistas de clientes. La lista de permitidos no introduce POST en segundo plano.

Pospuesto (motivos)

Idea Motivo para posponer
Cliente de API meteorológica en vivo Los agentes establecen/consultan el estado de la bóveda; obtienen datos fuera y usan world-set
Teléfono / notificaciones Específico de cada producto; no es la verdad de la bóveda
Cartera / juego con dinero Uso especializado; puede usar things + contadores si hace falta
NPC acompañantes Necesitan su propio grafo/tarjetas
Grafo de habitaciones de la residencia Por ahora se codifica en la cadena place
Higiene / sueño como entidades propias Usar standing / schedule / body
Editar automáticamente «Hoy» de look.md al ejecutar world-set Conserva la muestra detallada; los agentes usan card put en el archivo de apariencia

Flujo de sincronización de agentes

  1. world-get / persona_world_get → lee la instantánea, local_date, period, revision y stale_day. La ausencia de as_of_local_date indica obsolescencia; en otro caso, stale_day compara la fecha del registro con la fecha local de la persona después de day_boundary. weather_age_secs es la antigüedad con signo de una observación RFC3339 válida, o null si falta o es inválida.
  2. Al cambiar de día, invoque explícitamente persona world-rollover VAULT PERSONA / persona_world_rollover. Esta ruta de transición de día borra meals, orders_done, el resumen breve look y counters_today, y establece as_of_local_date a la fecha local del registro de hoy. Se conservan los counters acumulados, standing, things, órdenes pendientes, escena/cuerpo, herramientas, tiempo/pronóstico y automatización. No se edita ningún archivo de apariencia ni la sección «Hoy» de look.md.
  3. world-set solo actualiza los campos proporcionados de escena/objetos/registro/herramientas/tiempo. Nunca cambia el día silenciosamente ni borra campos diarios al cambiar de día, aunque estén obsoletos. Establece un as_of_local_date ausente sin borrar campos existentes, y siempre marca updated_at (UTC, Z) y updated_local (ISO local de la persona con desplazamiento) del mundo. persona_card guarda literalmente el mundo proporcionado, incluida una fecha pasada del registro.
  4. Use --expected-revision HASH / MCP expected_revision de world-get para evitar perder actualizaciones: un hash de cabecera actual distinto devuelve un conflicto antes de modificar. Omitirlo conserva la regla de prevalencia de la última escritura. Los contadores diarios usan --counter-today NAME=VALUE; --clear-counter NAME y --clear-counter-today NAME eliminan claves acumuladas/diarias (todos repetibles).
  5. La sincronización de archivos solo toca los dominios proporcionados por esa llamada. Las tarjetas existentes se sustituyen únicamente si su cuerpo sigue siendo la plantilla generada anterior al cambio; la prosa escrita manualmente se conserva y se informa como synced_archives[kind] = "preserved". Esto también se aplica a la sincronización de creación/eliminación/atributos de objetos y a la sincronización del registro al cambiar de día. Cambiar objetos sincroniza tanto things como wardrobe. Los archivos de apariencia existentes siempre se conservan.
  6. Las claves del mapa de cantidades de objetos / --item ID=COUNT usan ID estables, nunca búsquedas por nombre visible. Los ID existentes actualizan cantidades sin renombrar; cero elimina solo ese ID. Se rechaza un nombre visible perteneciente a otro ID. Las claves desconocidas siguen creando, por compatibilidad heredada, un objeto con ese ID y nombre.
  7. dice-roll / spinner-spin / schedule-list ofrecen herramientas conscientes de la zona horaria. Las ediciones detalladas de apariencia/diario usan card put normal; append-event opcional (p. ej., kind=weather) registra comportamiento sin reescribir la prosa de los archivos.

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

Los tokens webhook permanecen en el estado cifrado de la persona para la autenticación entrante, sincronización y copias de seguridad, pero las respuestas de clientes no los devuelven. World get/set, automation put/list, lecturas normales de tarjetas (incluidas las históricas y desatendidas) y lecturas de archivos solo exponen webhook_token_set en las vistas de automatización. Guarde el token aprovisionado de forma segura; establezca uno nuevo para rotarlo.

El chat entre dos tarjetas de persona en la misma bóveda usa una tarjeta de conversación normal y cursores de lectura por persona; leer el historial no marca mensajes como leídos. Enviar un mensaje activa los hooks chat_message de cada participante; la carga incluye vault, from, to y message_id, y omite el texto del mensaje.

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

Con una autorización de escritura: persona_write (timezone / day_boundary opcionales), 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. El historial y las diferencias usan las herramientas existentes memory_history / memory_diff / memory_read (las revisiones de tarjetas de persona incluyen world.*; los archivos de vestuario/lugar/postura tienen su propio historial).

Generar AGENTS.md / habilidad para agentes

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

El archivo generado resume las operaciones de bóvedas/tarjetas/personas/mundo y, cuando se selecciona una persona, incorpora una descripción de su núcleo y ejemplos CLI/MCP para el mundo, objetos y eventos. Véase Generación de habilidades en README.

Nota de sincronización (Grok Bot / Muse)

Trate la tarjeta de persona de la bóveda y sus archivos enlazados como fuente de verdad. Los directorios locales de habilidades facilitan la importación/exportación; después de importar, los agentes deben leer la bóveda (card read / MCP memory_read) en lugar de una copia obsoleta del sistema de archivos. Realice los cambios de núcleo mediante persona put; edite archivos mediante card put normal sobre el recurso del archivo; añada comportamiento de corta duración con append-event. Para decidir el cambio de día o las sesiones matutinas o nocturnas, use la timezone de la persona (y day_boundary opcional); no deduzca los límites del día únicamente del reloj del host del agente.

Estructura del directorio de habilidades

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

La importación asigna SKILL.md → núcleo de persona y cada references/*.md → tarjeta de archivo enlazada (kind = nombre del archivo sin extensión). El contenido del archivo se guarda literalmente como contenido del usuario.

Claves de metadatos iniciales: timezone o metadata.timezone (IANA); day_boundary / metadata.day_boundary opcionales (HH:MM).

Bóveda local de demostración

En un equipo de desarrollo puede inicializar una bóveda desechable con la muestra xiaoya incluida en el repositorio:

cargo run -p memories-core --example seed_xiaoya_persona

Esto escribe /workspace/persona-demo-vault (contraseña persona-demo-password) y SEED.json / README.md con los ID de bóveda y recursos (incluida timezone). Reproduzca la importación CLI contra un daemon en ejecución con:

memories persona import VAULT_ID testdata/xiaoya-persona