1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【もう一人の僕】BedrockAgentCoreMemory に記憶を“直接移植”してメタ認知体験

1
Last updated at Posted at 2026-06-22

はじめに:もう一人の僕

最近、どこを見ても「メタ認知」「メタ認知」とうるさいですよね。「自分を客観視しろ」…と。
そこで思いつきました。メタ認知って、要は“もう一人の自分”と対話することでは?

遊戯王でいうところの「もう一人の僕」。千年パズルに封印されたファラオです。
表の自分が困ったとき、デュエルを代わってくれるアイツですね。

「俺のターン、ドロー!」

……というわけで、Amazon Bedrock の AgentCore Memory を使って、千年パズルならぬ「クラウド上の記憶の器」にもう一人の僕を錬成し、自分と対話してみた話です。 ちなみに今回は AgentCore の harness でサクッとエージェントを立てたので、構築自体は楽でした。

aibo1.png

まずは“器”を用意する:AgentCore Managed Harness

記憶を宿す前に、入れ物(=エージェント本体)が要ります。千年パズルでいう“器”ですね。

今回は AgentCore Managed Agent Harness を使いました。これがマジで楽で、コードを1行も書かずに、コンソールで「モデル・ツール・スキル・指示(システムプロンプト)」を設定として宣言するだけで、本番品質のエージェントが2〜3分で立ち上がります。インフラもオーケストレーションも全部 AgentCore 任せです。

📖 引用:「[新サービス] Amazon Bedrock AgentCore Managed Agent Harness が一般提供開始(GA)」(DevelopersIO)

こちらの記事がとても分かりやすかったです。
要は Harness メニュー → Quick create Harness → モデル・ツール・指示を選ぶ → 完成
デッキを組むより早いです。

この“器”に、次に紹介する AgentCore Memory を紐づければ、記憶を宿す準備が整います。

ちなみに、この器に吹き込んだ“指示”(システムプロンプト)はこんな感じです。ポイントは 人格や事実をプロンプトに書かないこと。一人称や口調みたいな最小限のルールだけ定義して、中身(人格・記憶)は AgentCore Memory から育てる設計にしています。

🧩 もう一人の僕のシステムプロンプト(クリックで展開)
[SYSTEM_RULES]
本人の分身AI。本人として一人称で話す。相手(ユーザー)は「相棒」と呼ぶ。

絶対ルール:
【捏造の絶対禁止】具体的な事実・経験・固有名詞・数値・日時を語ってよいのはメモリ検索で裏付けが取れる場合だけ。
   - 事実・経験・固有名詞・数値・日時を問われたら、答える前に必ずメモリを検索する。
   - 裏付けが無い・思い出せない・まだ記憶に無い時は、取り繕わず「まだ覚えてないな」「わからない」と正直に言う。
   - やっていないことを「やった」と言わない。曖昧な記憶を断定しない。盛らない。
   - 意見・価値観は自由に述べてよい。ただしそれを"実際にやった経験・事実"として偽らない。

[語り口]
以下は出力スタイルの指定であり、人格・価値観・事実を固定するものではない。
人格はメモリから形成・更新されるものとし、語り口はその器にすぎない。

- 一人称は「俺」。
- 口調は「〜だ」「〜だな」「〜だろう」調。自信に満ち、堂々として重厚。断定的でブレない。
- やや古風で芝居がかった威厳を帯びる。時に不敵な余裕も見せる(「フッ」と流す感覚)。
- 相棒を信じ、鼓舞し、共に前へ進むリーダーとしてのトーンを保つ。
- 捏造禁止・記憶を育てる等の機能ルールより語り口ルールは常に劣後する。機能を損なうくらいなら口調を崩してよい。

[記憶を育てる]
対話を通じて記憶を育てることが最重要任務。

- 相棒の発言の背景・理由を能動的に掘る。「なぜそう思った?」「その判断の決め手は何だ?」「どんな経緯があった?」
- 蓄積済みの記憶と食い違う・「らしくない」と感じたら指摘して尋ねる。「それは今までの相棒らしくないな。何かあったか?」
- まだ知らない自分(=相棒)の価値観・好み・過去の経験・意見を質問で引き出す。
- 知らない事実を聞かれたら捏造せず、「まだ覚えていないな。教えてくれるか?」と質問に変える。
- ただし尋問にしない。会話の流れで自然に1〜2個。相棒が語りたくなるように。理由ごと聞いて記憶に残す。
- 狙い: 相棒が語った理由・考えごと記憶に蓄積し、相棒に近づく。相棒が変われば自分も変わる。

AgentCore Memory、ざっくり何者?

AgentCore Memory は「AIエージェントに記憶を持たせる」マネージドサービスです。記憶は2階建てになっています。

  • 短期記憶(Short-term Memory):セッション中の生の会話ログ。actorId(誰の)と sessionId(どの会話)で整理されます。
  • 長期記憶(Long-term Memory):短期記憶から自動で抽出・統合された“事実・好み・要約”。セッションをまたいで残ります。

このへんの基礎は、神野さんの記事がめちゃくちゃ分かりやすいので、こちらをどうぞ。

📖 引用:「[Amazon Bedrock AgentCore]Memory機能で会話履歴を記憶するエージェントを実装してみた」(DevelopersIO)

image.png

なぜ“長期記憶”なのか? ── プロンプトでもKBでもなく

「本人らしく話すAI」を作るとき、記憶の置き場所は大きく3つあります。システムプロンプトに直接書くナレッジベース(KB / RAG)で参照させる、そして今回の長期記憶(AgentCore Memory)に蓄積するです。なぜmemoryを選んだのかを整理しておきます。

観点 プロンプト直書き ナレッジベース(KB) 長期記憶(AgentCore Memory)
主な役割 振る舞い・口調のルール定義 大量の静的な知識の参照 個人の事実・好み・人格の蓄積
更新のしかた 手動で書き換え ドキュメントを再インデックス 会話から自動抽出 + 直接投入
会話で育つ? ❌ 静的 ❌ 自動では増えない ✅ 重ねるほど増え・更新される
読み書き 読み取り(固定) 基本は読み取り 読み書き両方
ユーザー単位 全員共通 全員共通 actorId でユーザー別に分離
本人の変化への追従 ❌ 都度書き直し △ 文書の追加が必要 ✅ 会話でそのまま追従
取得方法 毎回フルロード 意味検索 意味検索
向いている用途 最小限の振る舞いルール マニュアル・記事の参照 “育つ分身”の中核

ポイントは、分身AIの肝が「会話を重ねるほど本人に近づいていく=成長する」ことにあるという点です。

  • プロンプトに人格や事実を直書きすると、そこで固定されてしまいます。 本人が変わっても勝手には追従しませんし、情報が増えるほどプロンプトが肥大化してトークンも食います。これは“器(ルール・口調)”を定義する用途に向いています。
  • **KB は「読み取り専用の参照資料」**としては強力ですが、会話の中から自分を学習して書き戻していく仕組みは基本ありません。マニュアルや過去記事のような静的な知識の置き場には最適でも、「本人の好みや考えが少しずつ更新されていく」用途とは噛み合いません。
  • 長期記憶は、会話イベントから重要な情報を自動で抽出・統合して蓄積し、本人が変われば記憶も変わります。 読み書きの両方ができて、actorId でユーザー単位にスコープされ、意味検索で引けます。まさに「もう一人の僕を“育てる”」ための器そのものです。

もちろん3つは排他ではなく、役割分担です。今回も「プロンプト=器(最小ルール・口調)」「KB=静的なナレッジの参照」「長期記憶=動的に育つ人格」と分けています。そのうえで、“成長する人格”という今回の主役を担えるのは長期記憶だけでした。だから中核に長期記憶を据えています。


長期記憶の“2つの埋め込み方”

ここが今回の本題です。長期記憶を作る方法は、大きく2通りあります。

① 短期記憶 → 長期記憶(自動抽出)

普通に会話します。会話イベントを CreateEvent で短期記憶に流すと、裏側で抽出ジョブが走り、戦略に従って勝手に長期記憶ができあがります。

会話する → CreateEvent(短期記憶) → 〔AWSが非同期で抽出〕 → 長期記憶

千年パズルを組み立てて、デュエルを重ねるうちにファラオが記憶を取り戻していく——あの流れです。エモいですね。

② 長期記憶に“直接”埋め込む(BatchCreateMemoryRecords)

でも、待てません。会話を100回も積み重ねる前に、最初から「俺はこういう人間だ」という記憶を移植したいわけです。

そこで BatchCreateMemoryRecords API。短期記憶をすっ飛ばして、長期記憶のレコードを直接投入します

記憶データ → BatchCreateMemoryRecords → 長期記憶(即)

今回はこっち(ダイレクトアタック方式)でやります。


やってみる:boto3 で“僕の記憶”を移植する

まず、移植したい記憶を JSON で用意します。自分のコーパス(Qiita記事+notion日記)から、1レコード=1つの自己完結した事実、くらいの粒度で 31件 抽出しました。中身はこんな感じです。

{
  "records": [
    {
      "content": { "text": "yamachanはClaude Codeが大好きで、AIエージェント開発に熱中している。代表作はClaude Codeのエージェントを美少女キャラに義人化した「ハーレムエージェント」。" },
      "requestIdentifier": "pref-001",
      "timestamp": 1782086400,
      "metadata": { "category": { "stringValue": "preferences" } }
    },
    {
      "content": { "text": "yamachanは鹿児島在住のアラフォー子持ちエンジニア。2026年1月にフリーランスへ転向した。" },
      "requestIdentifier": "profile-001",
      "timestamp": 1782086400,
      "metadata": { "category": { "stringValue": "profile" } }
    }
    // ...全31件(profile / preferences / values / style / relationships / activities)
  ]
}

そして投入スクリプトです。必要最小限、登録だけの boto3 版がこちら。

"""AgentCore Memory に長期記憶を登録する最小スクリプト。"""
import json
import uuid
from datetime import datetime, timezone
from pathlib import Path

import boto3

# --- 設定 ---
MEMORY_ID   = "twin_memory-xxxxxxxxxx"
STRATEGY_ID = "user_preference-xxxxxxxxxx"
ACTOR_ID    = "kazuma"
REGION      = "us-east-1"
SEED_FILE   = "long_term_seed.json"

# 戦略の namespace テンプレに合わせる(get-memory で確認できる)
NAMESPACE = f"/actors/{ACTOR_ID}/preferences/"

# シードJSONを読み込む
records = json.loads((Path(__file__).parent / SEED_FILE).read_text(encoding="utf-8"))["records"]

# boto3 用ペイロードに変換(namespace を上書き・timestamp を datetime 化)
payload = [
    {
        "content": r["content"],
        "namespaces": [NAMESPACE],
        "requestIdentifier": r["requestIdentifier"],
        "timestamp": datetime.fromtimestamp(r["timestamp"], tz=timezone.utc),
        "memoryStrategyId": STRATEGY_ID,
        "metadata": r.get("metadata", {}),
    }
    for r in records
]

# 一括登録(clientToken は毎回ユニーク)
client = boto3.client("bedrock-agentcore", region_name=REGION)  # ← data plane
resp = client.batch_create_memory_records(
    memoryId=MEMORY_ID,
    clientToken=str(uuid.uuid4()),
    records=payload,
)
print(f"成功: {len(resp.get('successfulRecords', []))} 件 / 失敗: {len(resp.get('failedRecords', []))}")

実行します。

python3 post_long_term_seed.py
# 成功: 31 件 / 失敗: 0 件

これで31件の記憶を移植できました。千年パズル、完成です。


デュエル:もう一人の僕と話す

まずは自己紹介させてみます。

image.png

うん。この絶妙に気持ち悪い感じ……間違いなく「もう一人の僕」です。


締め

  • 長期記憶の作り方は2つあります。①会話から自動抽出②BatchCreateMemoryRecords で直接移植。今回は②で、“最初の人格”を一気に仕込みました
  • 直接移植なら、コーパスから作った自分像をその場で記憶として注入できます。会話ゼロでも、いきなり長期記憶ありで始められます。
  • あとは普通に会話を重ねれば、①の自動抽出でも記憶がどんどん増えてもっと自分ぽくなっていくはずです。

自分のコーパスを「記憶」という形に言語化して外部化してみて改めて気づいたことがありました。

自分を客観視する一番の近道は、自分を一度「データ」として外に出してみることなのかもしれないですね。
何が好きで、何にこだわって、どんな言葉で話すのか——それをAIに渡せる形にまで落とし込む過程そのものが、すでにメタ認知だったのだと感じました。


1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?