ペルソナカード
ペルソナカードは、Grok Bot や Muse などのクライアント間で性格と振る舞いを同期する、製品横断のアイデンティティカードです。保管庫内のコピーを正本とします。
レイヤー
- コア(低速) — 話し方と行動の指針。ペルソナカードの本文として保存し、
persona_card/memories persona putでリビジョン管理します(他のメモリやカードと同じ署名付きリビジョン DAG)。 - アーカイブ / エピソード(中速) — 日誌、装い、契約、見解、台詞、運用など。ペルソナプロフィール(
archives[])からリンクされる個別の通常のナレッジカードとして保存し、グラフ用にpersona_archive:<kind>カードリンクとしても反映します。アーカイブの内容をコアに戻して統合しないでください。 - 行動イベント(高速) —
persona_append_event/memories persona append-eventによる、リンクされたeventsアーカイブ上の追記専用ストリーム。
プロフィールのフィールド
| フィールド | 意味 |
|---|---|
persona_id |
安定した ID(例: スキルのフロントマターの name) |
display_name |
人が読むタイトル(例: 小雅 / 李雅) |
aliases |
別名 |
timezone |
IANA 名(例: Asia/Singapore)。未設定時 / 古いカードでは既定値は Asia/Singapore |
day_boundary |
日付が切り替わる任意のローカル HH:MM(日付の繰り越し)。未設定 = ローカルの午前0時 |
world |
現在の世界のスナップショット: place/pose/look/body、汎用の things(id→{name,description,images,attrs JSON})、台帳(counters + counters_today、as_of_local_date)、天気、ツール |
本文 / core |
Markdown/テキスト形式の行動指示 |
traits |
任意の文字列マップ(バージョン、言語、…) |
bindings |
{ product, agent } 製品との紐付け |
memory_policy / sync_hints |
任意の同期ガイダンス |
archives |
{ kind, card, vault?, title? } リンクされたアセット |
summary.type は persona で、persona_id、display_name、timezone、day_boundary、place、pose、look、things_count、has_weather、alias_count、archive_count、binding_count を含みます。
タイムゾーン、日付の繰り越し、朝の課業 / 夜の課業
ペルソナは、単なる UTC エポックではなくローカルの時刻に基づいて判断します。
- タイムゾーン — すべてのペルソナに IANA の
timezoneがあります。インポート時にはSKILL.mdからtimezone/metadata.timezoneを読み取ります。CLI では--timezone Asia/Singaporeで上書きできます。未設定時のデモの既定値:Asia/Singapore。 - 暦日(日付の繰り越し) —
day_boundaryが設定されていない限り、そのタイムゾーンの午前0時を境にローカルの暦日が変わります(例: 深夜の切り替えには05:00)。台帳 / 日誌の「新しい日」の確認では、UTC の日付ではなく、スタンプヘルパーのlocal_dateを比較してください。 - 時間帯(ローカル時刻、半開区間):
| 時間帯 | ローカル時刻 |
|---|---|
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) |
夜の課業 /「まだ同じ夜」の日付をまたぐ連続性には、[22:00, 05:00)(night ∪ early_morning)を使います。朝の課業は morning(必要に応じて early_morning の後半も)、夜の課業は evening / night に対応します。
4. イベントのスタンプ — persona_append_event は UTC とローカルの ISO-8601(オフセット付き)の両方、および timezone、period、local_date をイベントアーカイブの見出しと JSON 応答(utc、local、timezone、period、local_date、timestamp は Unix UTC)に書き込みます。
コアのヘルパー(Rust): memories_core::persona 内の persona_local_now、classify_period、stamp_persona_now、format_event_heading。
世界ドメインの分類(世界状態の領域)
world はドメイン/タグであり、コアへの詰め込み先ではありません。コア(SKILL.md の本文)は口調/ルールだけを保持します。
| レイヤー | 意味 | 保存先 |
|---|---|---|
| world | 場面 + 台帳 + ツール + 天気のドメイン | profile.world + world タグ付きアーカイブ |
| things | 自由な JSON 属性を持つ汎用アイテム(任意の名前: テーブル/カップ/ランプ/…) | world.things + アーカイブ things/wardrobe |
| scene | 場所(居所)、姿勢、装い(今日の服装の概要)、身体 | world.place/pose/look/body; 詳細な装いはアーカイブ look |
| ledger | カウンター、食事、指示、常設事項 | world.counters/counters_today/meals/orders_*/standing + アーカイブ ledger |
| tools | サイコロ、スピナー/回転盤、スケジュール/予定 | world.dice/spinners/schedule + アーカイブ dice/spinner/schedule |
| weather | 周囲の状況 / 気温 / 湿度 / 風(+ 任意の予報) | world.weather / world.forecast + アーカイブ weather |
| automation | フック(schedule/random/webhook/attr_change/chat_message)+ アクション | world.automation |
タイムゾーン(profile.timezone)は world の外部にありますが、日付の繰り越し、朝/夜の課業、スケジュールのローカル時刻には必須です。
xiaoya フィクスチャの調査 → 実装
| 要件(装い/日誌/運用から) | フィールド / アーカイブ |
|---|---|
| ローカルの日付 / 日付の繰り越し / 朝と夜の課業 | timezone、day_boundary、時間帯ヘルパー |
| 定番 + 今日の服装 | アーカイブ look; 概要 world.look |
| 持ち物(任意の名前のアイテム + 自由な JSON 属性/画像) | world.things ↔ アーカイブ things/wardrobe; CLI persona thing |
| 居所 / 姿勢 | world.place、world.pose |
| 行動カウンター(累計と今日) | world.counters(累計)、world.counters_today(日別) |
| 今日食べたもの | world.meals |
| 指示の未処理 / 処理済み | world.orders_pending、world.orders_done |
| 常設事項 | world.standing |
| 身体についてのメモ | world.body |
| 遊びのツール | world.dice、world.spinners、world.schedule |
| 天気 / 短期予報 | world.weather、world.forecast ↔ アーカイブ weather |
自動化(world.automation)
トリガー + アクションを持つ名前付きのフックを、ペルソナの世界スナップショットに保存します(cron/ローカルスケジュールはペルソナのタイムゾーンを使用)。
トリガーの type |
意味 |
|---|---|
cron |
ペルソナのローカル時刻での M H または M H * * DOW |
local_time |
HH:MM + 任意の days(スケジュールと同じ) |
random_interval |
[min_secs, max_secs] のランダムな遅延後に発火 |
random_and_timed |
ローカル時刻 + 任意の jitter_secs |
webhook |
受信 HTTP / CLI --source webhook |
attr_change |
thing attr set/delete 後、thing_id が一致し、パスフィルターが完全一致または接頭辞一致する場合 |
chat_message |
persona chat send 時に各参加者について1回(同じイベント。任意の peer は相手のペルソナカード ID で、完全な ID または一覧の短縮 ID) |
manual |
CLI/MCP automation trigger --source manual |
アクションの type |
意味 |
|---|---|
set_attr |
アイテムの属性パスを設定(設定時に作成) |
random_attr |
dice / range / choice |
call_function |
組み込み: inc、dec、clamp、roll、set_weather_stub |
append_event |
イベントアーカイブに追記 |
webhook_out |
URL に HTTP POST JSON を送信 |
デーモンの HTTP(--listen が有効な場合):
POST /v1/persona/{vault}/{persona}/automation/trigger
Authorization: Bearer <world.automation.webhook_token>
Content-Type: application/json
{"hook":"HOOK_ID"}
フックは明示的な自動化の実行/トリガーパスを通じてのみ発火します(既存の属性変更トリガー、およびペルソナのチャット送信時の chat_message を含みます)。persona automation run を呼び出すと、8日以内の最新の実行漏れの cron/ローカル時刻枠を補います。すべての実行漏れの枠を再生せず、最大1回実行します。曜日フィルターはその実行機会にも適用され、時刻指定のランダムフックはジッターによる制限を保持します。RandomInterval は変更されません。デーモンには自動化の定期実行機構はありません。Service::tick はセッション、付与権限、リモート状態を期限切れにするだけです。
送信側の webhook_out アクションには、world.automation.webhook_allowlist 内の完全一致する URL が必要です。既定の空リストはすべての POST をブロックします。persona automation webhook-allow VAULT PERSONA
--add https://example.com/hook(繰り返し可能な --add / --remove)または MCP persona_automation_webhook_allow で、エントリを明示的に管理します。エントリはユーザー情報や空白を含まない HTTP(S) URL で、最大2048バイトです。このリストは公開設定ですが、受信用の webhook_token は秘密情報であり、クライアントビューには返されません。許可リストへの登録によってバックグラウンドの POST が発生することはありません。
保留した項目(理由)
| 案 | 保留の理由 |
|---|---|
| リアルタイム天気 API クライアント | エージェントが保管庫の状態を設定/照会する。外部で取得して world-set を使用 |
| 電話 / 通知 | 製品固有であり、保管庫の正本ではない |
| 財布 / 金銭の遊び | 用途が限定的。必要なら things + カウンターで表現可能 |
| 仲間の NPC | 専用のグラフ/カードが必要 |
| 居所内の部屋グラフ | 当面は place 文字列にエンコード |
| 衛生 / 睡眠の専用項目化 | standing / schedule / body を使用 |
| world-set 時に look.md の「今日」を自動編集 | 詳細なフィクスチャを保持する。エージェントが装いのアーカイブに card put を使用 |
エージェントの同期フロー
world-get/persona_world_get→ スナップショット、local_date、period、revision、stale_dayを読み取ります。as_of_local_dateがない場合は古い状態とみなします。それ以外は、stale_dayが台帳の日付とday_boundary適用後のペルソナのローカル日付を比較します。weather_age_secsは有効な RFC3339 観測の符号付き経過秒数で、欠落/無効の場合は null です。- 日付の繰り越し時には、
persona world-rollover VAULT PERSONA/persona_world_rolloverを明示的に呼び出します。この日付遷移パスはmeals、orders_done、短いlookの概要、counters_todayを消去し、as_of_local_dateを今日のローカル台帳日付に設定します。累計counters、standing、things、未処理の指示、場面/身体、ツール、天気/予報、自動化は保持されます。装いのアーカイブや look.md の「今日」は編集されません。 world-setは指定された場面/アイテム/台帳/ツール/天気のフィールドだけを更新します。古い状態でも、日付の繰り越し時に暗黙的に日付を変更したり、日別フィールドを消去したりすることはありません。欠落しているas_of_local_dateを、既存フィールドを消去せずに設定し、常に世界レベルのupdated_at(UTC、Z)とupdated_local(オフセット付きのペルソナのローカル ISO)を記録します。persona_cardは、過去の台帳日付を含め、指定された world をそのまま保存します。- 更新の消失を防ぐには、world-get から取得した
--expected-revision HASH/ MCPexpected_revisionを使います。現在の先頭ハッシュが一致しない場合、変更前に競合を返します。省略した場合は後勝ちになります。日別カウンターには--counter-today NAME=VALUEを使用します。--clear-counter NAMEと--clear-counter-today NAMEは累計/日別のキーを削除します(すべて繰り返し可能)。 - アーカイブの同期は、その呼び出しで指定されたドメインだけを対象にします。既存カードは、本文が変更前の生成テンプレートのままの場合にのみ置換されます。手書きの文章は保持され、
synced_archives[kind] = "preserved"と報告されます。これはアイテムの追加/削除/属性の同期、および日付繰り越し時の台帳同期にも適用されます。アイテムの変更はthingsとwardrobeの両方を同期します。既存の装いのアーカイブは常に保持されます。 - アイテム数マップのキー /
--item ID=COUNTは安定した ID を使い、表示名で検索することはありません。既存の ID は名前を変更せずに数量を更新し、ゼロはその ID だけを削除します。別の ID に属する表示名は拒否されます。未知のキーは引き続き旧方式で、その ID と名前のアイテムを作成します。 dice-roll/spinner-spin/schedule-listはタイムゾーンに対応したツールを提供します。詳細な装い/日誌の編集には通常のcard putを使用します。任意のappend-event(例:kind=weather)はアーカイブの文章を書き換えずに行動を記録します。
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 トークンは、受信認証、同期、バックアップのために暗号化されたペルソナ状態に保持されますが、クライアントへの応答では返されません。World の get/set、自動化の put/list、通常のカード読み取り(履歴と無人での読み取りを含む)、アーカイブの読み取りでは、自動化ビューに webhook_token_set のみを公開します。発行済みのトークンを安全に保管してください。ローテーションするには、代わりのトークンを設定します。
同じ保管庫内の2枚のペルソナカード間のチャットは、通常の会話カードとペルソナごとの既読カーソルを使用します。履歴を読んでもメッセージは既読になりません。メッセージを送信すると、各参加者の chat_message フックが発火します。ペイロードには vault、from、to、message_id が含まれ、メッセージ本文は含まれません。
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
書き込み権限が付与されている場合: persona_write(任意の 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。履歴と差分には、既存の memory_history / memory_diff / memory_read ツールを使用します(ペルソナカードのリビジョンには world.* が含まれ、wardrobe/place/pose のアーカイブはそれぞれ独自の履歴を持ちます)。
エージェント用の AGENTS.md / スキルの生成
memories default set persona VAULT/PERSONA
memories skill generate --out AGENTS.md --persona VAULT/PERSONA
memories agents generate --out ./skills/memories-persona --layout skill
生成ファイルは保管庫/カード/ペルソナ/世界の操作を要約し、ペルソナが選択されている場合は、そのペルソナのコア概要と、世界、アイテム、イベントに関する CLI/MCP の手順を埋め込みます。README のスキルの生成を参照してください。
同期に関する注意(Grok Bot / Muse)
保管庫のペルソナカードとリンクされたアーカイブを正本として扱ってください。ローカルのスキルディレクトリはインポート/エクスポートの利便性のためのものです。インポート後、エージェントは古いファイルシステムのコピーではなく、保管庫(card read / MCP memory_read)を読む必要があります。コアの変更には persona put、アーカイブの編集にはそのアーカイブアセットへの通常の card put、短期間の行動の追記には append-event を使ってください。日付の繰り越し、朝の課業、夜の課業を判断するときは、ペルソナの timezone(および任意の day_boundary)を使ってください。エージェントのホストの時計だけから日付の境界を推定しないでください。
スキルディレクトリの構成
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
インポートは SKILL.md → ペルソナのコア、各 references/*.md → リンクされたアーカイブカード(kind = ファイル名の拡張子を除いた部分)に対応付けます。アーカイブの内容は、ユーザーコンテンツとしてそのまま保存されます。
フロントマターのキー: timezone または metadata.timezone(IANA)、任意の day_boundary / metadata.day_boundary(HH:MM)。
ローカルのデモ保管庫
開発用マシンでは、リポジトリに含まれる xiaoya フィクスチャで使い捨ての保管庫を初期化できます:
cargo run -p memories-core --example seed_xiaoya_persona
これにより /workspace/persona-demo-vault(パスワード persona-demo-password)と、保管庫およびアセットの ID(timezone を含む)を記載した SEED.json / README.md が書き込まれます。稼働中のデーモンに対して CLI インポートを再現するには、次を実行します:
memories persona import VAULT_ID testdata/xiaoya-persona