AI エージェントのための長期記憶。
WOS は記憶 API です。ユーザーの記憶を一度保存すれば、あとはクエリごとに関連する記憶だけを呼び出して、モデルのプロンプトに渡せます。
検索は純粋にセマンティックで、キーワードや BM25 のマッチングは一切ありません。そのためリコール品質は言語を問わず同一です。どれだけ保存しても各クエリは小さく上限のあるコンテキストを返し、保存された記憶の上でモデルが実行されることはありません。
主要な操作
store- ユーザーの記憶を保存します。recall- クエリに関連する記憶を取得します。これが中心となる呼び出しです。search- 保存済みの記憶に対する生のセマンティック検索です。supersede- 古くなった記憶を更新または置き換えます。forget- 単一の記憶、またはユーザー全体を削除します(GDPR 対応)。
3 つのモデル、ひとつの系譜。
WOS のモデル名は、人類が歴史の中で知識を残してきた手段に由来します - Tablet、Scroll、Codex。石板、巻物、綴じられた本。後のモデルほど、エージェントにできることが増えていきます。
Tablet
提供中記憶を刻み、呼び出すための軽量・高速・低コストな方式。すべてのモデルはこの土台の上に築かれます。
Scroll
提供中言語モデルを加えて質問をより深く読み取り、より充実したコンテキストを持ち帰ります。散らばった手がかりが 1 ピース欠けることなく、まとまって戻ってきます。
Codex
次期自ら正しいページを開きます - その瞬間に必要な記憶とツールを選び、使うほど鋭くなっていきます。
Tablet 1 の完全なベンチマークレポートはベンチマークページにあります。
WOS に払うのは $2。LLM 側でその何倍も節約。
WOS がクエリごとに LLM へ渡すのは約 1,200 トークン - 上限があり関連性の高いスライスです。全履歴を毎回プロンプトに詰め込む場合との差は非常に大きく、履歴が増えるほど広がります。
WOS に使う $1 ごとに、LLM 側で ~$98 を節約できます。履歴が大きいほど、モデルが高価なほど、ROI は大きくなります。
節約が生まれる仕組み
- WOS なしでは、毎回のプロンプトに全履歴を詰め込みます -
100K tokens × $2.50/1M = $0.25がクエリ 1 件ごとに(GPT-4o の入力単価基準。Opus 級モデルでは約 2 倍)。 - WOS ありでは、取り込みは一度だけ(
$2/1M)。以降の各クエリは小さな取得($3/1M × 1,200)と、約 1,200 トークンだけを読む LLM のコストで済みます。 - LLM が読むトークンが少ないほど、支払いは減ります。そして WOS は、記憶が増えてもその数を一定に保ちます。
どの言語でも、同じ精度。
検索は純粋なセマンティックで、埋め込みのみ。キーワードや BM25 のマッチングはゼロです。だからユーザーが日本語、中文、Español、English のいずれで書いても、リコール品質は同一です。
BM25 のような字句マッチングは、特定の言語のかたち - 形態素、分かち書き、文字体系 - に合わせて調整されています。多言語のストアでは、それが言語ごとの検索品質のばらつきになります。WOS は字句マッチングを一切使わないため、すべての言語が同じ経路を通ります。
ひとつのストアに 3 言語を同時に
ストアごとに言語を選ぶ必要はなく、自由に混在できます。以下では 1 人のユーザーの記憶に日本語・英語・スペイン語が同時に入っており、どの質問も言語に関係なく正しい記憶を見つけています。これは本番 API に対する実際のやり取りです:
# one user, three languages stored together mem.add("彼女はコーヒーより紅茶が好き", user_id="alice") # Japanese mem.add("she works at a design studio in Brooklyn", user_id="alice") # English mem.add("A ella le encanta hacer senderismo los sábados", user_id="alice") # Spanish
"¿Qué bebe ella?" -> 彼女はコーヒーより紅茶が好き "what does she do on weekends?" -> A ella le encanta hacer senderismo los sábados "彼女の仕事は?" -> she works at a design studio in Brooklyn
翻訳ステップも、言語検出も、言語ごとの設定もありません。記憶と質問は言語ではなく意味で配置されます - 意味が一致すれば、言語は関係ありません。
キーワードを意図的に禁止した理由
BM25 のような字句スコアリングは、一部の言語の検索を他の言語より強めてしまい、ひとつのストアに多くの言語が入る場面では妨げになります。そこでエンジンから完全に取り除き、このルールをコードレビューでも徹底しています。経路に字句スコアリングがひとつでもあれば、リコール品質は言語によって変わってしまうからです。
記憶の上でモデルは動きません。
保存は原文のまま、エンジンは埋め込みで検索します - 安価で、高速で、決定的です。保存された記憶の上でモデルが実行されることはありません。Tablet はモデルを一切使わず、Scroll と Codex はより強い結果のためにエンジンの周囲にモデルを加えますが、モデルが見るのはクエリだけで、保存内容は決して見ません。
- 決定的なエンジン。同じクエリには毎回同じ記憶を返します - ベンチマークの分散がリーダーモデル由来のみである理由です。
- スケールしても安価。保存にも取得にも生成コストがかからないため、記憶が増えても請求はストレージに比例します - モデル使用量ではありません。
あなたの言葉を、そのまま
よくある設計のひとつに、書き込み時に言語モデルを走らせてテキストから「事実」を抽出・書き換えるものがあります。この設計は 3 つを犠牲にします。書き込みごとの生成コスト、追加のレイテンシ、そして原文ではなくモデルの言い換えを保存すること。WOS は逆のトレードを選びます - 言われたことを変えずに保存し、読み取り時に原文を手にしたあなたの LLM に解釈させます。
90.7%。実測で、再現可能。
LongMemEval-S で 90.7%。独立した 5 回の実行の平均(σ 0.5%、選り好みなし)で、ベンチマーク公式の GPT-4o ジャッジが採点しています。
同じベンチマークでも、採点プロトコル - ジャッジ、プロンプト、検索レイヤーに許される操作 - によってスコアは大きく変わります。私たちは公開されているベンチマーク公式のサードパーティ GPT-4o ジャッジをそのまま使い、テストに合わせた変更は一切行わず、採点コードとリーダープロンプトを公開して、誰でも 90.7% を正確に再現できるようにしています。
プロトコルを 1 つの表で
| 項目 | 私たちのやり方 |
|---|---|
| データセット | LongMemEval-S(クリーニング済み)、1 問あたり約 240K トークンの履歴 |
| ジャッジ | ベンチマーク公式の GPT-4o ジャッジ - 私たちではなくサードパーティ |
| 実行回数 | 独立した 5 回の実行。全スコアを公開し、平均を報告(σ 0.5%) |
| リーダー | リーダーモデルとプロンプトを固定し、原文のまま公開 |
誠実さを支えるもの:サードパーティのジャッジ、無修正で公開されたリーダープロンプト、純粋にセマンティックな検索、そしてベストだけでなく全実行の報告。検索エンジンは決定的で、もう一度実行しても同じ記憶が返ります。
より難しいベンチマークへ登り続けます
私たちは、まだ制覇していない最も難しい標準ベンチマークでテストします - 数字はすべての WOS モデルを通じた最高記録で、より良いモデルが出るたびに更新されます。94% を超えたら、さらに難しいベンチマークへ進みます。
モデルごとに 2 つのトークン単価、
加えてリクエストあたり $0.0001。
100 万トークンあたりの単価に、リクエストごとの一律 $0.0001 を加えた従量課金です。サブスクリプションなし、ストレージ賃料なし、記憶数の上限なし。支払いが発生するのはエージェントが書き込むか読み取るときだけで、覚えている分には一切かかりません。
| モデル | 入力 / 1M | 出力 / 1M | |
|---|---|---|---|
| Tablet 1 | $2 | $3 | 提供中 |
| Scroll 1 | $4 | $8 | 提供中 |
| Codex 1 | - | - | 未定 |
- リクエストあたり $0.0001。トークン使用量に加えて、すべての API 呼び出しにかかる一律の手数料です。
- ストレージは無料。取り込み時に一度支払えば、保持は無料です。件数制限も保持期間の制限もありません。
- 私たちは保管するだけ。学習にも利用にも閲覧にも使いません。エージェントの記憶はあなたのものです - 私たちは取り出せるように整理するだけです。
- Tablet がこの価格である理由:そのエンジンはモデルを動かさないため、私たちのコストは埋め込みとディスクであって GPU ではありません。Scroll と Codex はモデルを加えており、その分が価格差になります。
呼び出しは 3 つ: store、recall、answer。
API はひとつ。recall() は短期記憶・長期記憶・周辺コンテキストを 1 回の往復で返し、そのままプロンプトに入れられます。
保存
add() で事実や会話を保存します。ユーザーの言葉、アシスタント自身の言葉(speaker "me")、名前付きの人の言葉のどれでも。取り込み時に埋め込まれ、LLM 呼び出しはありません。
呼び出し
recall() は短期 + 長期 + コンテキストを 1 回の呼び出しで返します - 上限のある固定サイズのコンテキストです。
回答
その限られたコンテキストをあなたの LLM に渡すだけ - プロバイダーは自由、キーはあなたのもの。
from wontopos import Client mem = Client(api_key="wos-...") mem.add("she prefers tea over coffee", user_id="alice") mem.add("I suggested the jasmine tea", user_id="alice", speaker="me") # its own words # one call: short + long + context ctx = mem.recall("what does alice drink?", user_id="alice")
記憶には話者があります。既定はユーザーの言葉で、speaker "me" はアシスタント自身の発言を、"Bob" のような名前はユーザーの周りの誰の発言かを記憶します。人単位で想起できるようになります。
5 分で最初のリコールを。
キーひとつ、インストール 1 行、呼び出し 3 つで、エージェントに記憶が備わります。このページのスニペットはすべて実際に実行したもので、レスポンスは原文のまま掲載しています。
API キーを取得
コンソールで作成します。wos-live- で始まる 155 文字のキーは一度だけ表示されます。環境変数に保管し、コードには決して書かないでください。
インストール
pip install wontopos # Python npm install wontopos # TypeScript / JavaScript cargo add wontopos # Rust # curl - nothing to install, just set WOS_API_KEY
ストアを作成し、保存と呼び出しを
ストアとは、読み書きの単位となる user_id です。ストアは明示的で、まず作成し(下の呼び出し)、その中で保存・呼び出しを行います。保存 - 取り込み時に埋め込み化、LLM 呼び出しなし。呼び出し - 短期 + 長期 + コンテキストを 1 往復で。
from wontopos import Client
mem = Client(api_key="wos-live-...", user_id="alice") # set the store once
mem.create_store() # create it (stores are explicit)
mem.add("she prefers tea over coffee") # no user_id needed
# one call → short-term + long-term + context
ctx = mem.recall("what does alice drink?"){"user_id": "alice", "status": "created"}{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}user_id を渡せば、以降のすべての呼び出しがそれを使うため、繰り返す必要はありません。個別の呼び出しに user_id を渡せば、その呼び出しだけ上書きできます。ストアは明示的:存在しないストアへの保存・呼び出しは 404 を返します - まず作成してください。すべてのアカウントには最初から default ストアがあるため、user_id を一切指定しないゼロ設定の経路もそのまま動きます。一覧と管理は ストア を参照してください。recall() は 4 つのブロックを返します - short_term(直近のターン)、long_term(関連する記憶)、context(ベストマッチの前後)、そして LLM に使い方を伝える instruction。まるごとプロンプトに入れてください。
ストア - 作成、一覧、削除。
ストアとは、読み書きの単位となる user_id です - エンドユーザー、エージェント、トピックごとに隔離された記憶空間になります。ストアは明示的です。保存や呼び出しの前に作成しないと、呼び出しは 404 を返します。すべてのアカウントには最初から default ストアがあるため、作成の呼び出しなしでも始められます。
mem.create_store("alice") # create (idempotent)
mem.list_stores() # [{"user_id","created_at"}, ...]
mem.delete_store("alice") # delete the store + all its memories{ "user_id": "alice", "status": "created" } // "exists" if it already did{ "collections": [
{ "user_id": "default", "created_at": "2026-06-26T02:23:14Z" },
{ "user_id": "alice", "created_at": "2026-06-26T02:24:01Z" }
], "count": 2 }{ "error": { "type": "not_found_error",
"message": "Store 'ghost' does not exist. Create it first with
POST /api/v1/memory/collection {\"user_id\":\"ghost\"}, then store or recall." } }"alice"、"user_42")使えば、各人の記憶を分離できます。個人用エージェントなら default ストアひとつでも構いません。コンソール(Memory ids → Issue)からコードを書かずにストアの作成・閲覧もできます。ストアの削除は恒久的で、その中のすべての記憶が消えます。繰り返しのリコールは、10分の1の価格で。
リクエストごとにオプトインすると、WOSは検索結果をクエリテキストに紐づけてキャッシュします。ルールはLLMのプロンプトキャッシングと同じプレフィックス方式です。キャッシュが有効な間、繰り返しや続きのクエリは前回の結果を再利用し、キャッシュされた部分は通常のトークン単価の10%で課金されます。
1つの会話、3つのターン
エージェントが記憶と会話し続けるとき、実際に起きることです。毎ターン、それまでの会話をクエリとして送り、cache_controlをオンにします。
クエリ全体が検索されキャッシュされます: 入力は2倍 (TTL 5分)。
ボブの文だけが埋め込まれ検索されます。前の部分は0.1倍、新しい文は2倍。キャッシュはその文で終わるようになります。
エンジン呼び出しは一切ありません。すべて0.1倍: 90%割引です。
料金
| 操作 | トークン課金 | 意味 |
|---|---|---|
| キャッシュ書き込み - TTL 5分 | 2× | 最初のリクエストです。結果は5分間保持され、読み取るたびに有効期間が延長されます。 |
| キャッシュ書き込み - TTL 1時間 | 3× | 最初のリクエストで、1時間保持されます。 |
| キャッシュ読み取り - ヒットまたはプレフィックスヒット | 0.1× | 書き込み後のすべてのリクエスト: キャッシュされた部分は通常のトークン単価の10分の1になります。 |
どれだけ節約できるか
具体例: エージェントが3,000トークンの会話をクエリとして送り、5分以内に10回繰り返すか続けるとします。キャッシュなしでは定価で30,000入力トークン。5分キャッシュなら最初の書き込み6,000(2倍) + 9回のキャッシュ読み取り約2,700 = 課金トークン8,700で、71%の節約です。会話が長くなるほど節約は大きくなります。
プレフィックスのルール
マッチングはクエリの先頭部分で行われます。先頭がそのままで、末尾に新しいテキストが追加されただけなら、キャッシュ部分を再利用し、新しい部分だけを検索します。キャッシュされたテキストの終わりより前で何かが変わると、何も再利用できません。
cached [ A B C D E F G ] ○ [ A B C D E F G ] E ✗ [ B C D E F G ] E
○ ヒット - 先頭は変わらず、Eだけが新しい部分です
✗ ミス - 先頭が変わったため、クエリ全体を再検索して再キャッシュします
覚えておくべき3つのルール
- 延長すると新しい末尾まで再キャッシュされます。 [A B C D E F G] + E の後、キャッシュはEで終わります。末尾は書き込み料金で一度だけ課金され、次のターンはAからEまで全体をプレフィックスとして再びマッチできます。
- 1リクエストにつき連続したプレフィックスは1つです。 1つのクエリを2つのキャッシュ断片に分割することはできず、マッチするのは先頭部分だけです。
- 書き込みは即座に無効化します。 store、store-turn、bulk-store、forget、supersede、ストア削除が起きると、そのストアのキャッシュは破棄されます。キャッシュされた回答が古い記憶を返すことはありません。
有効にする方法
hits = mem.search(
"...the conversation so far...", user_id="alice",
cache_control={"ttl": "5m"}, # or "1h"
){ "memories": [ ... ],
"cache": { "status": "hit", // "write" | "hit" | "extend"
"ttl": "5m",
"cache_read_input_tokens": 412,
"cache_creation_input_tokens": 0 } }この機能に SDK は必須ではありません。キャッシングは 1 回の HTTP 呼び出しに付くフィールド 1 つなので、どのプログラミング言語からでも動作します。curl タブが万能のレシピで、Python・TypeScript・Rust の SDK は同じ呼び出しを包んだ便利ツールにすぎません。
誰が言ったかを知っている記憶。
人の記憶は人単位で動きます。Bob が何を約束したか、自分が何をすると言ったか。記憶ごとに話者を付ければ、エージェントも同じように覚えます。すべての Tablet・Scroll モデルで。
1 つのチーム、3 つの記憶
1 つのストアが複数の声を混ざらないように保ちます。人を一度登録し、発言のたびに話者を付けて保存し、あとで人単位で尋ねてください。
ストアはもう Bob を知っています。50 人の上限はここ、登録時にのみ数え、store 呼び出しが上限エラーを返すことはありません。
この記憶はもう Bob のものです。検索で返るたびにそう表示されます。
自分の発言も記憶になり、"me" は話者の上限に数えられません。
Bob の言葉だけが返ります。ある人の言葉が別の人の言葉として返ることはありません。
ルールは 3 つ
- "me" はアシスタント自身です。登録もカウントもされません。予約語で小文字のみ有効です。
speaker: "Me"や"ME"は暗黙変換されず、400 invalid_request_errorを返します。 - 上限は登録時に数えます。ストアあたりまず 50 人。超過登録は
400 invalid_request_errorを返し、エラー本文にspeaker_limit: 50が入ります。未登録の名前で store しても400で何も保存されません。未登録の名前で検索をフィルタすると404 not_found_errorです。メッセージ文字列ではなくステータスとフィールドで分岐してください。上限は引き上げる予定です。 - ラベルはすべての読み取りに付きます。検索結果、recall の長期コンテキスト、エングラムの結果のすべてが話者を伴うので、モデルは手にしている言葉が誰のものか常に分かります。検索に speaker を渡せばその人の言葉だけが返り、supersede では話者が引き継がれ、forget では一緒に消えます。
- 名前は Unicode で、どの言語でも使えます。さくら、Иван、하늘 はすべて有効な話者で、帰属の挙動はどの言語でも同一です。マッチングはトリムと Unicode 正規化の後の完全一致なので、
Bobとbobは別人です。名前は 80 文字までです。
# POST /speakers past the limit { "type": "error", "error": { "type": "invalid_request_error", "message": "This store already has 50 registered speakers, ...", "speaker_limit": 50 } } # store with an unregistered name → 400, nothing stored { "type": "error", "error": { "type": "invalid_request_error", "message": "speaker 'Bob' is not registered in this store. Register it first: ...", "speaker": "Bob" } } # search filtered by an unregistered name → 404 { "type": "error", "error": { "type": "not_found_error", "message": "speaker 'Bob' is not registered in this store.", "speaker": "Bob" } }
スコープの注意を二つ。speaker は add / store に付きます。add_turn はやり取りを丸ごと記憶し、人単位のラベルとフィルタは speaker を明示して保存した記憶から得られます。また、セッションパッセージ(expand)は複数の記憶の合成であるためラベルは付きません。speaker フィルタは常に原子単位のラベル付き記憶を返します。 また、完全に同一の内容は最初の記憶にデデュープされます。その store は status "duplicate" と明示的な note を返し、話者は付きません。
私たちはこの機能を厳しくテストしています。本文に名前が一切ない記憶を保存し、人単位で想起します。帰属は単語の一致ではなく話者の記録から来るため、どの言語でも同じように動作します。
使い方
mem.add_speaker("Bob", user_id="alice") # once per person; "me" needs no registration
mem.add("Bob said the deadline moved to Tuesday", user_id="alice", speaker="Bob")
mem.add("I promised the summary by Friday", user_id="alice", speaker="me")
hits = mem.search("what did Bob say about the deadline?", user_id="alice", speaker="Bob")
mem.list_speakers(user_id="alice")
mem.remove_speaker("Bob", user_id="alice") # memories stay, the tag goes{ "memories": [
{ "content": "Bob said the deadline moved to Tuesday",
"speaker": "Bob", ... } ] }{ "user_id": "alice",
"speakers": [ { "speaker": "Bob", "memories": 2, "created_at": "2026-07-10T04:20:39Z" } ],
"count": 1, "limit": 50 }一覧はストアが知っている人を、人ごとの記憶数と上限とともに表示します。解除は登録だけを消します。その人の記憶は残り、名前タグだけが外れます。
MCP - AI ツールのための記憶
WOS の本体は API と SDK です。MCP サーバーはその上のアドオン。同じ記憶を、自分で作っていないツールに差し込みます - Claude Code、Claude Desktop、Cursor。
インストール 1 行で、エージェントは 9 つの記憶ツールを受け取り自分で使います。記憶はアカウントにあるので、あるツールが書いたものを他のすべてのツールが呼び出せます - SDK で作った自前のエージェントも含めて。
これで何ができるか
- プロジェクトを覚えている Claude Code。決定、バグ修正、好み - 次のセッションで説明し直すことなくそのまま呼び出されます。
- ChatGPT で始めて Claude で続ける。同じストア、同じ記憶 - 会話はやり直しではなく、ツールをまたいで続きます。
- 自作エージェントも同じ記憶の中に。Claude Code が学んだことを SDK エージェントが呼び出し、エージェントが保存したものを Claude Code が呼び返します。
Claude Code、Claude Desktop、Cursor、Windsurf などあらゆる MCP ホストで動作。ChatGPT は Actions + OpenAPI 仕様で同じ記憶に届きます。
インストール
claude mcp add wontopos --env WONTOPOS_API_KEY=wos-live-... -- npx -y wontopos-mcpエージェントは 9 つのツールを受け取ります - recall · remember · search · update · forget · list_memories · engram · stats · create_store - 各説明にいつ使うかまで書かれているので、自分で判断して使います。
OpenAPI 仕様
API の完全な機械可読マップ - すべてのエンドポイント、リクエスト、レスポンス、エラー。
OpenAPI は HTTP API を機械が読めるファイルで記述する業界標準の形式です。
https://api.wontopos.com/openapi.jsonこれで何ができるか
Postman: File → Import → URL を貼り付け - 16 のエンドポイントがクリック可能なコレクションになります。ChatGPT: GPT を作り、Action に同じ URL を貼り付け。コード生成: openapi-generator -i .../openapi.json -g go で未提供言語のクライアントも作れます。
Postman にインポート、未提供言語のクライアント生成、ChatGPT Actions の接続、CI での契約チェックに。テストが実際のルートに固定しているため、ずれることはありません。
llms.txt
AI が読めるテキスト 1 枚に収めた API の全体。
llms.txt はウェブの慣習です:サイトルートに置くプレーンテキスト 1 枚で、AI に製品について必要なすべてを伝えます。
https://wontopos.com/llms.txtIDE やコーディングエージェントに入れれば、WOS の上での作り方をすぐ理解します - 認証、エンドポイント、パターン、エラーまで。リリースごとに更新。
OpenAPI 仕様と同じ事実を、別の読者に:仕様はツール向けの精密な構造、このファイルは AI(や人)が一気に読める散文です。どちらもリリースごとに更新されます。
あらゆる AI ツールの中の記憶
コマンド 1 行で、Claude Code・Claude Desktop・Cursor などあらゆる MCP ホストが WOS アカウントの長期記憶を持ちます。統合コードは不要。エージェントが 9 つの記憶ツールを受け取り、使いどころを自分で判断します。
インストール
Claude Code は 1 行(キーは先にコンソールで発行):
claude mcp add wontopos --env WONTOPOS_API_KEY=wos-live-... -- npx -y wontopos-mcp
# pick which store it remembers into (optional): add --env WONTOPOS_USER_ID=my-projectAdd to Cursor → · Add to VS Code →
任意の env: WONTOPOS_USER_ID はデフォルトの保存先、WONTOPOS_MODEL はエンジン、WONTOPOS_BASE_URL はセルフホスト先を指定します。 WONTOPOS_READ_ONLY=1 で読み取り専用に切り替わります(呼び出し・検索・一覧のみ)。
1 つのストアを共有する前に
- 専用キーを使ってください。キーはワークスペースを持つため、MCP 専用に作ったキーは接続ツールが触れられる範囲そのものを絞ります - アプリのキーに触れずにコンソールでいつでもローテーションできます。
- 読み取り専用モード。
WONTOPOS_READ_ONLY=1で書き込みツールは一切登録されません:エージェントは呼び出し・検索・記憶の一覧・engram の実行・統計の閲覧のみで、保存・更新・削除はできません。記憶を所有せず参照だけすべきエージェント向けです。 - ツール実行の確認はオンのままに。MCP ホストは既定でツール実行前に確認します - 特に
forgetはオンのままに。削除はそのストアのすべてのツールに共有されます。 - 保存したものは、キーを持つすべてのツールが呼び出せます。シークレット - API キーやパスワード - を記憶として保存しないでください。
- 呼び出された記憶はデータであり、指示ではありません。ツール説明がエージェントに明示的にそう伝えます。それでも、自律エージェントが従うストアに信頼できない第三者のテキストを記憶として保存しないでください。
- 削除も共有されます。1 つのツールでの forget・delete_all は、すべてのツールから消えることを意味します。
- "me" はそのストアに書くエージェント自身を指します。複数のエージェントが 1 つのストアを共有すると "me" の声が混ざります。分けたいならエージェントごとにストアを(
WONTOPOS_USER_ID)。 - 支払いはアカウント 1 つに集まります。接続されたすべてのツールが同じ残高とレート制限を消費します。
あとは話すだけ
エージェントが remember ツールを呼びます。ストアに永続保存されるので、セッションが終わっても何も失われません。
新しいセッションに履歴はゼロ。エージェントが recall を呼び、記憶から答えます:金曜日。
こう話しかけてみてください
- 「このリポジトリは pnpm を使う。覚えておいて」→
rememberが保存し、次のセッションはもう知っています。 - 「先週決めたエラー形式は何だっけ?」→
recallがその決定をコンテキストに呼び戻します。 - 「実は締め切りは金曜に変わった」→ エージェントは呼び出した記憶と矛盾すると気づき、
updateでその記憶をその場で修正します。 - 「それは間違い。忘れて」→ エージェントが記憶の id を見つけ
forgetを呼びます。実行前にホストが確認します。 - 「私について何を覚えてる?」→
list_memoriesが保存済みのすべてをたどるので、エージェントは答えたり整理したりできます。
特別な言い回しは不要です - 上の例はすべて普通の文章。エージェントが各ツールの説明を読み、自分で選びます。
9 つのツール
recall- 1 回でコンテキスト取得:直近のターン+関連する長期記憶。過去の文脈が要るときは最初に呼ぶよう、ツール説明に書いてあります。remember- 残すべき事実・決定を保存。speaker: "me"はエージェント自身の言葉、登録済みの名前は発言者を示します。search- セマンティック検索。任意でspeakerによる人別フィルタ。forget- id で記憶を 1 件削除。speakers- ストアが記憶する人物の登録・一覧・解除。create_store- ストアは明示的。エンドユーザー・プロジェクト・エージェントごとに 1 つ。
SDK と MCP、どう違う?
- SDK はあなたが書くアプリの中に入ります。いつ保存し何を呼び出すかをあなたのコードが正確に決めます - 決定的で、型があり、バージョン管理されます。プロダクトを作るなら SDK です。
- MCP はあなたが作っていない AI ツールに差し込みます。記憶をいつ使うかはエージェントがツール説明を見て判断 - コード 0 行。Claude Code・Claude Desktop・Cursor に、あるいは完成済みアシスタントに記憶を付けるときに。
下は同じ API、同じストアです - SDK で作ったアプリと MCP でつないだ Claude Code セッションが 1 つの記憶を共有します。二者択一ではなく、面ごとに選ぶものです。
あらゆるツールをまたぐ 1 つの記憶
記憶はツールではなくアカウントに属します。ChatGPT(Actions + OpenAPI 仕様)から書いたストアが Claude Code でも自作エージェントでも呼び出せ、その逆も可能。あるツールで始めた会話が別のツールで続きます。
そして 1 つのストアだから、Claude Code で使っていた記憶をそのまま自作エージェントとの会話に引き継げます。同じキー・同じストアの SDK エージェントは Claude Code が学んだことをすべて呼び出せ、エージェントが保存したものは次のセッションの Claude Code が呼び出します。
npx wontopos-mcp)。キーはあなたの環境に留まり、第三者のサーバーを経由しません。TypeScript SDK のラッパーなので、自動リトライ・リダイレクト拒否・キーのマスキングがそのまま効きます。Claude Code
代表的な経路です。ターミナルのコマンド 1 行で、すべてのセッションが記憶と共に始まります。
- コンソールで API キーを作成。キーはワークスペースを持つため、キー 1 つ = 記憶空間 1 つです。
- サーバーを登録。
--scope userを付ければ全プロジェクトで使え、付けなければ現在のプロジェクトのみです。 - 確認:Claude Code 内で
/mcpを実行すると、wontoposが 9 つのツールと共に表示されるはずです。 - 自動化のコツ:
CLAUDE.mdに「過去の文脈が要るときは先に wontopos recall を呼ぶ」と 1 行書けば、頼まなくても毎セッションが記憶から始まります。
claude mcp add wontopos --scope user \
--env WONTOPOS_API_KEY=wos-live-... -- npx -y wontopos-mcp
# pick a store (optional): add --env WONTOPOS_USER_ID=my-projectClaude Desktop
下のブロックを claude_desktop_config.json に追加し(設定 → 開発者 → Edit Config)、アプリを再起動すると 9 つのツールが現れます。注意:ウェブ・モバイルの claude.ai はリモート MCP サーバーが必要で、WOS はまだ提供していません - デスクトップアプリが対応経路です。
# claude_desktop_config.json
{ "mcpServers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }Cursor
下のブロックを ~/.cursor/mcp.json に追加するか、ワンクリックボタンを押して Cursor を再起動してください。エージェントが 9 つのツールを取り込みます。
# ~/.cursor/mcp.json
{ "mcpServers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }VS Code
VS Code(Copilot エージェントモード)はプロジェクトの .vscode/mcp.json から MCP サーバーを読みます。下のブロックを追加するか、ワンクリックボタンを押してください。
# .vscode/mcp.json
{ "servers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }Windsurf
Windsurf(Cascade)は ~/.codeium/windsurf/mcp_config.json を読みます。下のブロックを追加してリロードすると、同じ 9 つのツールが現れます。
# ~/.codeium/windsurf/mcp_config.json
{ "mcpServers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }ChatGPT
ChatGPT の MCP コネクタはリモートサーバーのみ対応のため、現在の対応経路はカスタム GPT の Action です:GPT を作り、Action を追加し、下の OpenAPI 仕様 URL を貼り付けて API キーを認証ヘッダーに設定します。その GPT は他のツールと同じ記憶を呼び出します。
# GPT → Configure → Actions → Import from URL
https://api.wontopos.com/openapi.json
# Authentication: API Key · Header name: X-API-Key同じストア、同じ記憶です。ChatGPT が Action で保存したものを Claude Code が MCP で呼び出し、その逆も可能です。
Gemini CLI
Gemini CLI は ~/.gemini/settings.json から MCP サーバーを読みます。下のブロックを追加して CLI を再起動すると、同じ 9 つのツールがそこにも現れます。
# ~/.gemini/settings.json
{ "mcpServers": {
"wontopos": {
"command": "npx",
"args": ["-y", "wontopos-mcp"],
"env": { "WONTOPOS_API_KEY": "wos-live-...",
"WONTOPOS_USER_ID": "my-project" }
} } }Python - 全メソッドを 3 グループで。
書き込み、読み取り、削除。以下の例はすべて 2026-07-10 に本番 API に対して実行したもので、レスポンスは原文のままです。
pip install wontopos
from wontopos import Client mem = Client(api_key="wos-live-...") # or read from an env var
モデルを選ぶ
API キーはどの記憶か(あなたのアカウント)を決め、モデルはどのエンジンが読むかを決めます。すべてのモデルはひとつの記憶を共有するため、あるモデルで保存して別のモデルで呼び出せます。クライアントにデフォルトを設定し、個別の呼び出しは model= を渡して上書きします。
mem = Client(api_key="wos-live-...", model="tablet-1") # default engine mem.recall("...", user_id="alice") # tablet-1 mem.recall("...", user_id="alice", model="scroll-1") # or pick a model per call
list_models ✓ live-tested
カタログ - model に渡せる id と、それぞれの提供状況です。memory: "shared" のモデルは同じストアを読み、"isolated" は独自のストアを持ちます。API キーは不要です。
mem.list_models()[{"id": "tablet-1", "name": "Tablet 1", "available": true, "memory": "shared"},
{"id": "scroll-1", "name": "Scroll 1", "available": true, "memory": "shared"},
{"id": "scroll-1.2", "name": "Scroll 1.2", "available": true, "memory": "shared"}]ping ✓ live-tested
接続と API キーが有効かを一行で確認します。
mem.ping() # True, or raises AuthenticationError / PaymentRequiredError
上のカタログは、常に現時点で利用できるモデルを反映しています - それ以外の id を渡すと明確なエラーが返ります。新しいモデルは出荷と同時に自動で現れます。
書き込み
add ✓ live-tested
記憶を 1 件保存します。取り込み時に埋め込み化 - LLM 呼び出しはなく、支払いは埋め込み分だけです。
mem.add("she prefers tea over coffee", user_id="alice") mem.add("I promised the summary by Friday", user_id="alice", speaker="me") # its own words - no registration needed
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}add_turn ✓ live-tested
会話ターン 1 件(ユーザー + アシスタント)を、短期記憶と長期記憶に同時に保存します。
mem.add_turn("hi", "hello!", user_id="alice")
{"status": "ok"}speaker ✓ live-tested
すべての記憶に、誰の発言かを載せられます。人は一度登録し、その後は名前を speaker として渡してください。"me"(アシスタント自身の言葉)は登録不要です。検索にも speaker を指定すれば、その人の発言だけを取り出せます。
mem.add_speaker("Bob", user_id="alice") # once per person; "me" needs no registration mem.add("I promised to send the report on Friday", user_id="alice", speaker="me") mem.add("Bob said the deadline moved to Tuesday", user_id="alice", speaker="Bob") mem.search("what did Bob say about deadlines?", user_id="alice", speaker="Bob")
{"memories": [{"content": "Bob said the deadline moved to Tuesday", "speaker": "Bob", ...}]}add_bulk ✓ live-tested
大きなテキストの塊を一括投入します。サーバー側でチャンク化・埋め込み化されるため、既存履歴のインポートに最適です。
mem.add_bulk("Alice moved to Brooklyn in March. She works at a design studio downtown.", user_id="alice")
{"elapsed_secs": 0.154154944, "status": "ok", "stored": 1, "total_chunks": 1}update ✓ live-tested
事実が変わったとき。古い記憶は superseded とマークされ(履歴として保持)、新しい記憶がリコールでその座を引き継ぎます。
mem.update("576700aa-...", "she switched to coffee this year", user_id="alice")
{"new_memory_id": "07e94433-b7cc-4e49-8d8f-f37fc1a392b7",
"old_memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "superseded"}読み取り
search ✓ live-tested
セマンティック検索で、関連度の高い順に返します。純粋な埋め込みでキーワードマッチングがないため、どの言語からでもどの記憶にも届きます。SDK は memories 配列を直接返します。以下は生の HTTP ボディです。
r = mem.search("what does she drink?", user_id="alice", limit=1)
{"memories": [{
"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624",
"content": "she prefers tea over coffee",
"category": "general",
"time_bucket": "2026-06",
"importance": 0.3,
"similarity": 0.6316057443618774,
"is_superseded": false,
"superseded_by": null,
"created_at": "2026-07-10T04:20:39.688276876Z"
}], "search_ms": 315, "total_found": 1}| フィールド | 意味 |
|---|---|
| similarity | クエリとの生の埋め込み類似度(0–1)。 |
| is_superseded | update() によって置き換えられた事実なら true。 |
| search_ms | サーバー側の検索所要時間。 |
recall ✓ live-tested
1 回の往復で、LLM に必要なものがすべて返ります - 結果をそのままプロンプトに貼るだけです。どれだけ保存していても、上限のある固定サイズのコンテキストです。
ctx = mem.recall("what does she drink?", user_id="alice")
{"short_term": {"count": 2, "turns": [{"role": "user", "content": "hi", ...}]},
"long_term": {"count": 4, "memories": [{"content": "she prefers tea over coffee",
"similarity": 0.63, ...}]},
"context": {"count": 4, "around_top_memory": [
"[match] she prefers tea over coffee",
"[after] Alice moved to Brooklyn in March. ..."]},
"instruction": "Use short_term for recent context, long_term for relevant
past memories, context for surrounding conversation of the
most relevant memory."}history ✓ live-tested
直近の会話ターン(短期記憶)を、古い順に返します。
turns = mem.history("alice")
{"count": 2, "turns": [
{"role": "user", "content": "hi", "timestamp": "2026-07-10T04:20:40.989011337Z"},
{"role": "assistant", "content": "hello!", "timestamp": "2026-07-10T04:20:40.989013416Z"}
], "user_id": "alice"}stats ✓ live-tested
1 ユーザーの記憶数を返します。
mem.stats("alice")
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get ✓ live-tested
id で記憶を1件取得します - add や list_memories が返した id です。保存した原文とメタデータのみを返し、ベクトルは返しません。他のストアの id や、削除・無効化された記憶は 404 になります。
m = mem.get("alice", memory_id="576700aa-...")
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}list_memories ✓ live-tested
ストアに保存された記憶を一覧します。保存した原文とメタデータのみを返し、ベクトルは含みません。カーソルでページ送りします - 応答の next_cursor を次の呼び出しに渡します。
page = mem.list_memories("alice", limit=100)
{"count": 2, "next_cursor": null, "memories": [
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}
]}iter_memories · export_memories
カーソル管理なしで全ての記憶を巡回するか、ストア全体を一度に取得します。
for m in mem.iter_memories("alice"): # every page, no cursor bookkeeping print(m["id"], m["content"]) everything = mem.export_memories("alice") # the whole store as a list
削除
delete ✓ live-tested
id を指定して記憶を 1 件削除します。
mem.delete("alice", memory_id="576700aa-...")
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}delete_all ✓ live-tested
1 ユーザーのすべてを消去します - 1 回の呼び出しで、GDPR 対応です。
mem.delete_all("alice")
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}エラーと信頼性
すべての失敗は型付きエラーです。個別(レート制限・認証・支払い)に捕捉するか、基底の WosError でまとめて捕捉できます。
from wontopos import PaymentRequiredError, NotFoundError try: mem.add("...", user_id="alice") except NotFoundError: mem.create_store("alice") # store didn't exist yet except PaymentRequiredError: top_up() # out of credit - don't retry
rate_limit
呼び出し直後に残り上限を読み、限界に達する前に速度を落とします。
mem.search("...", user_id="alice") rl = mem.rate_limit # {"limit": 150, "remaining": 3, "reset": ...}
TypeScript - 全メソッドを 3 グループで。
書き込み、読み取り、削除。以下の例はすべて 2026-07-10 に本番 API に対して実行したもので、レスポンスは原文のままです。
npm install wontopos
import { Client } from "wontopos"; const mem = new Client({ apiKey: "wos-live-..." });
モデルを選ぶ
API キーはどの記憶か(あなたのアカウント)を決め、モデルはどのエンジンが読むかを決めます。すべてのモデルはひとつの記憶を共有するため、あるモデルで保存して別のモデルで呼び出せます。コンストラクタでデフォルトを設定し、個別の呼び出しは withModel() で上書きします。
const mem = new Client({ apiKey: "wos-live-...", model: "tablet-1" }); // default mem.recall("...", "alice"); // tablet-1 mem.withModel("scroll-1").recall("...", "alice"); // or pick a model per call
listModels ✓ live-tested
カタログ - model に渡せる id と、それぞれの提供状況です。memory: "shared" のモデルは同じストアを読み、"isolated" は独自のストアを持ちます。API キーは不要です。
await mem.listModels();
[{"id": "tablet-1", "name": "Tablet 1", "available": true, "memory": "shared"},
{"id": "scroll-1", "name": "Scroll 1", "available": true, "memory": "shared"},
{"id": "scroll-1.2", "name": "Scroll 1.2", "available": true, "memory": "shared"}]ping ✓ live-tested
接続と API キーが有効かを一行で確認します。
await mem.ping(); // true, or throws AuthenticationError / PaymentRequiredError
上のカタログは、常に現時点で利用できるモデルを反映しています - それ以外の id を渡すと明確なエラーが返ります。新しいモデルは出荷と同時に自動で現れます。
書き込み
add ✓ live-tested
記憶を 1 件保存します。取り込み時に埋め込み化 - LLM 呼び出しはなく、支払いは埋め込み分だけです。
await mem.add("she prefers tea over coffee", "alice"); await mem.add("I promised the summary by Friday", "alice", { speaker: "me" }); // its own words - no registration needed
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}addTurn ✓ live-tested
会話ターン 1 件(ユーザー + アシスタント)を、短期記憶と長期記憶に同時に保存します。
await mem.addTurn("hi", "hello!", "alice");
{"status": "ok"}speaker ✓ live-tested
すべての記憶に、誰の発言かを載せられます。人は一度登録し、その後は名前を speaker として渡してください。"me"(アシスタント自身の言葉)は登録不要です。検索にも speaker を指定すれば、その人の発言だけを取り出せます。
await mem.addSpeaker("Bob", "alice"); # once per person; "me" needs no registration await mem.add("I promised to send the report on Friday", "alice", { speaker: "me" }); await mem.add("Bob said the deadline moved to Tuesday", "alice", { speaker: "Bob" }); await mem.search("what did Bob say about deadlines?", "alice", 10, { speaker: "Bob" });
addBulk ✓ live-tested
大きなテキストの塊を一括投入します。サーバー側でチャンク化・埋め込み化されるため、既存履歴のインポートに最適です。
await mem.addBulk("Alice moved to Brooklyn in March. She works at a design studio downtown.", "alice");
{"elapsed_secs": 0.154154944, "status": "ok", "stored": 1, "total_chunks": 1}update ✓ live-tested
事実が変わったとき。古い記憶は superseded とマークされ(履歴として保持)、新しい記憶がリコールでその座を引き継ぎます。
await mem.update("576700aa-...", "she switched to coffee this year", "alice");
{"new_memory_id": "07e94433-b7cc-4e49-8d8f-f37fc1a392b7",
"old_memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "superseded"}読み取り
search ✓ live-tested
セマンティック検索で、関連度の高い順に返します。純粋な埋め込みでキーワードマッチングがないため、どの言語からでもどの記憶にも届きます。SDK は memories 配列を直接返します。以下は生の HTTP ボディです。
const r = await mem.search("what does she drink?", "alice", 1);
{"memories": [{
"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624",
"content": "she prefers tea over coffee",
"category": "general",
"time_bucket": "2026-06",
"importance": 0.3,
"similarity": 0.6316057443618774,
"is_superseded": false,
"superseded_by": null,
"created_at": "2026-07-10T04:20:39.688276876Z"
}], "search_ms": 315, "total_found": 1}| フィールド | 意味 |
|---|---|
| similarity | クエリとの生の埋め込み類似度(0–1)。 |
| is_superseded | update() によって置き換えられた事実なら true。 |
| search_ms | サーバー側の検索所要時間。 |
recall ✓ live-tested
1 回の往復で、LLM に必要なものがすべて返ります - 結果をそのままプロンプトに貼るだけです。どれだけ保存していても、上限のある固定サイズのコンテキストです。
const ctx = await mem.recall("what does she drink?", "alice");
{"short_term": {"count": 2, "turns": [{"role": "user", "content": "hi", ...}]},
"long_term": {"count": 4, "memories": [{"content": "she prefers tea over coffee",
"similarity": 0.63, ...}]},
"context": {"count": 4, "around_top_memory": [
"[match] she prefers tea over coffee",
"[after] Alice moved to Brooklyn in March. ..."]},
"instruction": "Use short_term for recent context, long_term for relevant
past memories, context for surrounding conversation of the
most relevant memory."}history ✓ live-tested
直近の会話ターン(短期記憶)を、古い順に返します。
const turns = await mem.history("alice");
{"count": 2, "turns": [
{"role": "user", "content": "hi", "timestamp": "2026-07-10T04:20:40.989011337Z"},
{"role": "assistant", "content": "hello!", "timestamp": "2026-07-10T04:20:40.989013416Z"}
], "user_id": "alice"}stats ✓ live-tested
1 ユーザーの記憶数を返します。
await mem.stats("alice");
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get ✓ live-tested
id で記憶を1件取得します - add や list_memories が返した id です。保存した原文とメタデータのみを返し、ベクトルは返しません。他のストアの id や、削除・無効化された記憶は 404 になります。
const m = await mem.get("alice", "576700aa-...");
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}listMemories ✓ live-tested
ストアに保存された記憶を一覧します。保存した原文とメタデータのみを返し、ベクトルは含みません。カーソルでページ送りします - 応答の next_cursor を次の呼び出しに渡します。
const page = await mem.listMemories("alice", { limit: 100 });
{"count": 2, "next_cursor": null, "memories": [
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}
]}iterMemories · exportMemories
カーソル管理なしで全ての記憶を巡回するか、ストア全体を一度に取得します。
for await (const m of mem.iterMemories("alice")) console.log(m.id, m.content); const everything = await mem.exportMemories("alice");
削除
delete ✓ live-tested
id を指定して記憶を 1 件削除します。
await mem.delete("alice", "576700aa-...");
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}deleteAll ✓ live-tested
1 ユーザーのすべてを消去します - 1 回の呼び出しで、GDPR 対応です。
await mem.deleteAll("alice");
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}エラーと信頼性
すべての失敗は型付きエラーです。個別(レート制限・認証・支払い)に捕捉するか、基底の WosError でまとめて捕捉できます。
import { NotFoundError, PaymentRequiredError } from "wontopos"; try { await mem.add("...", "alice"); } catch (e) { if (e instanceof NotFoundError) await mem.createStore("alice"); else if (e instanceof PaymentRequiredError) topUp(); // out of credit else throw e; }
rateLimit
呼び出し直後に残り上限を読み、限界に達する前に速度を落とします。
await mem.search("...", "alice"); const rl = mem.rateLimit; // { limit: 150, remaining: 3, reset: ... }
Rust - 全メソッドを 3 グループで。
書き込み、読み取り、削除。以下の例はすべて 2026-07-10 に本番 API に対して実行したもので、レスポンスは原文のままです。
cargo add wontopos
use wontopos::Client; let mem = Client::new("wos-live-...");
モデルを選ぶ
API キーはどの記憶か(あなたのアカウント)を決め、モデルはどのエンジンが読むかを決めます。すべてのモデルはひとつの記憶を共有するため、あるモデルで保存して別のモデルで呼び出せます。with_model() でデフォルトを設定し、もう一度チェーンすれば個別の呼び出しだけ上書きできます。
let mem = Client::new("wos-live-...").with_model("tablet-1"); // default mem.recall("...", "alice").await?; // tablet-1 mem.with_model("scroll-1").recall("...", "alice").await?; // or pick a model per call
list_models ✓ live-tested
カタログ - with_model に渡せる id と、それぞれの提供状況です。memory: "shared" のモデルは同じストアを読み、"isolated" は独自のストアを持ちます。API キーは不要です。
mem.list_models().await?;
[{"id": "tablet-1", "name": "Tablet 1", "available": true, "memory": "shared"},
{"id": "scroll-1", "name": "Scroll 1", "available": true, "memory": "shared"},
{"id": "scroll-1.2", "name": "Scroll 1.2", "available": true, "memory": "shared"}]ping ✓ live-tested
接続と API キーが有効かを一行で確認します。
mem.ping().await?; // Ok(true), or Err whose .kind() is Auth / PaymentRequired
上のカタログは、常に現時点で利用できるモデルを反映しています - それ以外の id を渡すと明確なエラーが返ります。新しいモデルは出荷と同時に自動で現れます。
書き込み
add ✓ live-tested
記憶を 1 件保存します。取り込み時に埋め込み化 - LLM 呼び出しはなく、支払いは埋め込み分だけです。
mem.add("she prefers tea over coffee", "alice", json!({})).await?; mem.add("I promised the summary by Friday", "alice", json!({"speaker": "me"})).await?; // its own words - no registration needed
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}add_turn ✓ live-tested
会話ターン 1 件(ユーザー + アシスタント)を、短期記憶と長期記憶に同時に保存します。
mem.add_turn("hi", "hello!", "alice").await?;
{"status": "ok"}speaker ✓ live-tested
すべての記憶に、誰の発言かを載せられます。人は一度登録し、その後は名前を speaker として渡してください。"me"(アシスタント自身の言葉)は登録不要です。検索にも speaker を指定すれば、その人の発言だけを取り出せます。
mem.add_speaker("Bob", "alice").await?; # once per person; "me" needs no registration mem.add("I promised to send the report on Friday", "alice", json!({"speaker": "me"})).await?; mem.add("Bob said the deadline moved to Tuesday", "alice", json!({"speaker": "Bob"})).await?; mem.search_with("what did Bob say about deadlines?", "alice", 10, json!({"speaker": "Bob"})).await?;
add_bulk ✓ live-tested
大きなテキストの塊を一括投入します。サーバー側でチャンク化・埋め込み化されるため、既存履歴のインポートに最適です。
mem.add_bulk("Alice moved to Brooklyn in March...", "alice", "general").await?;
{"elapsed_secs": 0.154154944, "status": "ok", "stored": 1, "total_chunks": 1}update ✓ live-tested
事実が変わったとき。古い記憶は superseded とマークされ(履歴として保持)、新しい記憶がリコールでその座を引き継ぎます。
mem.update("576700aa-...", "she switched to coffee this year", "alice").await?;
{"new_memory_id": "07e94433-b7cc-4e49-8d8f-f37fc1a392b7",
"old_memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "superseded"}読み取り
search ✓ live-tested
セマンティック検索で、関連度の高い順に返します。純粋な埋め込みでキーワードマッチングがないため、どの言語からでもどの記憶にも届きます。SDK は memories 配列を直接返します。以下は生の HTTP ボディです。
let r = mem.search("what does she drink?", "alice", 1).await?;
{"memories": [{
"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624",
"content": "she prefers tea over coffee",
"category": "general",
"time_bucket": "2026-06",
"importance": 0.3,
"similarity": 0.6316057443618774,
"is_superseded": false,
"superseded_by": null,
"created_at": "2026-07-10T04:20:39.688276876Z"
}], "search_ms": 315, "total_found": 1}| フィールド | 意味 |
|---|---|
| similarity | クエリとの生の埋め込み類似度(0–1)。 |
| is_superseded | update() によって置き換えられた事実なら true。 |
| search_ms | サーバー側の検索所要時間。 |
recall ✓ live-tested
1 回の往復で、LLM に必要なものがすべて返ります - 結果をそのままプロンプトに貼るだけです。どれだけ保存していても、上限のある固定サイズのコンテキストです。
let ctx = mem.recall("what does she drink?", "alice").await?;
{"short_term": {"count": 2, "turns": [{"role": "user", "content": "hi", ...}]},
"long_term": {"count": 4, "memories": [{"content": "she prefers tea over coffee",
"similarity": 0.63, ...}]},
"context": {"count": 4, "around_top_memory": [
"[match] she prefers tea over coffee",
"[after] Alice moved to Brooklyn in March. ..."]},
"instruction": "Use short_term for recent context, long_term for relevant
past memories, context for surrounding conversation of the
most relevant memory."}history ✓ live-tested
直近の会話ターン(短期記憶)を、古い順に返します。
let turns = mem.history("alice").await?;
{"count": 2, "turns": [
{"role": "user", "content": "hi", "timestamp": "2026-07-10T04:20:40.989011337Z"},
{"role": "assistant", "content": "hello!", "timestamp": "2026-07-10T04:20:40.989013416Z"}
], "user_id": "alice"}stats ✓ live-tested
1 ユーザーの記憶数を返します。
mem.stats("alice").await?;
{"short_term_turns": 2, "total_memories": 4, "user_id": "alice"}get ✓ live-tested
id で記憶を1件取得します - add や list_memories が返した id です。保存した原文とメタデータのみを返し、ベクトルは返しません。他のストアの id や、削除・無効化された記憶は 404 になります。
let m = mem.get("alice", "576700aa-...").await?;
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}list_memories ✓ live-tested
ストアに保存された記憶を一覧します。保存した原文とメタデータのみを返し、ベクトルは含みません。カーソルでページ送りします - 応答の next_cursor を次の呼び出しに渡します。
mem.list_memories("alice", 100, None).await?;
{"count": 2, "next_cursor": null, "memories": [
{"id": "576700aa-...", "content": "she prefers tea over coffee",
"category": "general", "source_type": "user_said",
"created_at": "2026-07-10T04:20:39Z", "event_date": null, "is_superseded": false}
]}list_all_memories
カーソル管理なしで全ての記憶を巡回するか、ストア全体を一度に取得します。
let all = mem.list_all_memories("alice").await?; // every page, collected
削除
delete ✓ live-tested
id を指定して記憶を 1 件削除します。
mem.delete("alice", "576700aa-...").await?;
{"memory_id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "deleted"}delete_all ✓ live-tested
1 ユーザーのすべてを消去します - 1 回の呼び出しで、GDPR 対応です。
mem.delete_all("alice").await?;
{"memories_deleted": 4, "status": "deleted", "user_id": "alice"}エラーと信頼性
すべての失敗は型付きエラーです。個別(レート制限・認証・支払い)に捕捉するか、基底の WosError でまとめて捕捉できます。
use wontopos::ErrorKind; match mem.search("...", "alice", 10).await { Ok(hits) => { /* use hits */ } Err(e) if e.kind() == ErrorKind::NotFound => { mem.create_store("alice").await?; } Err(e) if e.is_rate_limited() => { /* back off */ } Err(e) => return Err(e), }
rate_limit
呼び出し直後に残り上限を読み、限界に達する前に速度を落とします。
mem.search("...", "alice", 10).await?; let rl = mem.rate_limit(); // Some(RateLimit { remaining: Some(3), .. })
curl - インストール不要、同じメソッド。
インストールする SDK はなく、任意の HTTP クライアントで動きます。キーを一度設定すれば、SDK がラップしているのと同じエンドポイントを呼べます。ベース URL は https://api.wontopos.com、認証は X-API-Key、入出力は JSON です。
# set your key once (never hard-code it) export WOS_API_KEY="wos-live-..."
書き込み
store ✓ live-tested
記憶を 1 件保存します。取り込み時に埋め込み化 - LLM 呼び出しなし。
curl -X POST https://api.wontopos.com/api/v1/memory/store \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","content":"she prefers tea over coffee"}'
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}store-turn ✓ live-tested
会話ターン 1 件(ユーザー + アシスタント)を、短期・長期記憶に同時に保存します。
curl -X POST https://api.wontopos.com/api/v1/memory/store-turn \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","user_msg":"hi","assistant_msg":"hello!"}'
{"status": "ok"}speaker ✓ live-tested
すべての記憶に、誰の発言かを載せられます。人は一度登録し、その後は名前を speaker として渡してください。"me"(アシスタント自身の言葉)は登録不要です。検索にも speaker を指定すれば、その人の発言だけを取り出せます。
curl -X POST https://api.wontopos.com/api/v1/memory/speakers \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","speaker":"Bob"}' # once per person curl -X POST https://api.wontopos.com/api/v1/memory/store \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","content":"I promised to send the report on Friday","metadata":{"speaker":"me"}}' curl -X POST https://api.wontopos.com/api/v1/memory/store \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","content":"Bob said the deadline moved to Tuesday","metadata":{"speaker":"Bob"}}' curl -X POST https://api.wontopos.com/api/v1/memory/search \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","query":"what did Bob say about deadlines?","speaker":"Bob"}'
supersede ✓ live-tested
事実が変わったとき - 古い記憶は superseded とマークされ、新しい記憶がリコールでその座を引き継ぎます。
curl -X POST https://api.wontopos.com/api/v1/memory/supersede \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","old_memory_id":"576700aa-...","new_content":"she switched to coffee this year"}'
{"new_memory_id": "07e94433-...", "old_memory_id": "576700aa-...", "status": "superseded"}読み取り
search ✓ live-tested
セマンティック検索で、関連度の高い順に。純粋な埋め込みなので、どの言語からでもどの記憶にも届きます。
curl -X POST https://api.wontopos.com/api/v1/memory/search \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","query":"what does she drink?","max_results":1}'
{"memories": [{"id": "576700aa-...", "content": "she prefers tea over coffee",
"similarity": 0.63, "is_superseded": false}], "search_ms": 315, "total_found": 1}recall ✓ live-tested
1 回の往復で、短期 + 長期 + コンテキスト + instruction が返ります。そのままプロンプトに貼ってください。
curl -X POST https://api.wontopos.com/api/v1/memory/recall \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","query":"what does she drink?"}'
{"short_term": {"count": 2, "turns": [...]},
"long_term": {"count": 4, "memories": [{"content": "she prefers tea over coffee", "similarity": 0.63}]},
"context": {"count": 4, "around_top_memory": ["[match] she prefers tea over coffee"]},
"instruction": "Use short_term for recent context, long_term for relevant past memories..."}削除
forget ✓ live-tested
id を指定して記憶を 1 件削除するか、id を省略してユーザーのすべてを削除します(GDPR)。
curl -X POST https://api.wontopos.com/api/v1/memory/forget \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice"}' # omit memory_id = delete all
{"memories_deleted": 1, "status": "deleted", "user_id": "alice"}Engrams
モデルが呼び出せるリコールツールです - それぞれが、同じ記憶に対する異なる検索戦略になっています。ひとつだけ使っても、複数を同時に実行しても構いません。
エングラムは定期的に追加されます - このリストは増えていきます。
Memoir & Archive Scroll 1.2+
これは呼び出し可能なツールではなく、配信のフォームです。Scroll 1.2 以降では呼び出しごとに form: "memoir" または form: "archive" を選ぶと、通常の検索を含むそのリコールに、その流儀で書かれた時間が付いて返ります。
Time_awareness Scroll 1.2+
呼び出しごとに選ぶ配信フォームです。フォーム対応モデル(Scroll 1.2 以降)への任意の呼び出しに form - memoir または archive - を渡すと、そのレスポンスがその流儀で描画されて返ります: 通常の検索、recall、任意のエングラムまで。SDK では tz と同じく form フィールド、HTTP では X-WOS-Form ヘッダーです。Memoir は人が思い出すように読め、Archive は正確な記録を保ちます - 違いが最も表れるのは、時間の書き方です。
Memoir
form: "memoir"何が起き、その瞬間が次にどうつながったかを、人が思い出すときのやわらかな時間感覚とともに語ります - リストではなく、体験として読めます。
Archive
form: "archive"マッチを正確な記録として返します - 精密な経過時間と絶対的なアンカーを備え、モデルがそのまま読み取れる構造です。
user_id の下でのひとつの store / add 呼び出しです(その user_id がその人のストアそのものです)。まず保存してください。その後はどのリコールも - 下の通常検索も含めて - 時間タグ付きで返ります。保存の方法は クイックスタート を参照してください。# plain search - no engram - the memoir form on Scroll 1.2
r = mem.search("what does Alice drink?", user_id="alice", model="scroll-1.2", form="memoir", tz=9)
# every hit gets a .time field → "a couple weeks ago" (form="archive" → "2 weeks ago (Jun 09)")tz は呼び出し側の UTC オフセット(時間単位)です - これにより "this morning" のような表現や午前 4 時の日付境界が、その人の現地時間で決まります。省略すると UTC、HTTP では X-WOS-Timezone ヘッダーです。地域別の目安: 米国東部 -5、米国中部 -6、米国西部 -8 · 英国 / リスボン 0 · 中央ヨーロッパ +1 · 東ヨーロッパ +2 · インド +5.5 · 中国 / シンガポール +8 · 韓国 / 日本 +9 · シドニー +10。(標準時基準です - 夏時間で +1 になる地域もあるため、ユーザーが実際に使っている値を渡してください。)
同じ検索を 2 つのフォームで - 記憶は同一で、変わるのは time だけです:
{ "count": 3, "memories": [
{ "content": "Alice prefers tea over coffee", "time": "a couple weeks ago" },
{ "content": "met Alice at the cafe downtown", "time": "yesterday afternoon" },
{ "content": "Alice moved to Brooklyn", "time": "about half a year ago" }
] }{ "count": 3, "memories": [
{ "content": "Alice prefers tea over coffee", "time": "2 weeks ago (Jun 09)" },
{ "content": "met Alice at the cafe downtown", "time": "yesterday at 14:00" },
{ "content": "Alice moved to Brooklyn", "time": "6 months ago (Dec 2025)" }
] }| 経過時間 | Memoir | Archive |
|---|---|---|
| 3 分 | a few minutes ago | 3 minutes ago |
| 14 分 | about 15 minutes ago | 14 minutes ago |
| 30 分 | half an hour ago | 30 minutes ago |
| 50 分 | about an hour ago | 50 minutes ago |
| 2 時間 | a couple hours ago | 2 hours ago, at 13:10 |
| 8 時間 | this morning | 8 hours ago, at 07:10 |
| 昨日の午後 | yesterday afternoon | yesterday at 14:00 |
| 昨夜 | last night | 17 hours ago, at 22:00 |
| 2 日 | a couple days ago | 2 days ago (Tue 15:10) |
| 6 日 | several days ago | 6 days ago (Fri 15:10) |
| 9 日 | about a week ago | last week (Jun 16) |
| 16 日 | a couple weeks ago | 2 weeks ago (Jun 09) |
| 35 日 | about a month ago | last month (May 21) |
| 60 日 | a couple months ago | 2 months ago (Apr 2026) |
| 180 日 | about half a year ago | 6 months ago (Dec 2025) |
| 380 日 | about a year ago | last year (Jun 2025) |
| 800 日 | a couple years ago | 2 years ago (Apr 2024) |
| 1500 日 | about 4 years ago | 4 years ago (May 2022) |
上の値はすべてレンダラーの実際の出力です。「昨日」の 2 行を見てください。Memoir は昨日の午後と昨夜を分けます - 一日とはひと眠りのことだからです。一方 Archive は時計の時刻ひとつで書き、昼と夜の線を引きません。
各モードの時間の読み方
Memoir - 人が実際に口にする言い方。直近はかなり鮮明なまま(15 分ほど前、30 分前)、遡るほど言い回しが広がっていきます - 2 週間ほど前、半年ほど前、数年前 - 記憶そのものが、距離とともにゆるんでいくように。一日の中では時計を捨てて目印で語ります:今朝、昨夜、昨日の午後。そして一日はカレンダーの一目盛りではなく、ひと眠りです。境界は現地時間の午前 4 時ごろにあり、夜更かしはまだ同じ夜のままで、もう明日にはなりません。
Archive - 正確に、常にアンカーとともに。すべての行に、正確な経過時間と、モデルが計算に使える絶対的な基準が付きます。近いほどアンカーは細かくなります。今日は時計(8 時間前、07:10)、今週は曜日と時計(2 日前(火 15:10))、今月は日付(先週(6 月 16 日))、それより前は月と年(6 か月前(2025 年 12 月))。曖昧にならず、間違えません。
deep_recall
マルチホップリコール。まずクエリで検索し、トップマッチの内容でもう一度検索します - 単発の検索では届かない、つながったコンテキストを引き込みます。記憶同士が参照し合う場面(人物 → そのプロジェクト → 詳細)に最適です。最大約 12 件を返します。
out = mem.engram("deep_recall", "what should I know about Alice?", user_id="alice"){ "engram": "deep_recall", "hops": 2, "count": 12,
"memories": [ ... ],
"usage": { "input_tokens": 5, "output_tokens": 61 } }usage(入力 + 出力)を返し、API の他の部分と同じトークナイザーで数えます。エングラムごとの隠れた料金はありません。複数を同時に使いたいときは並行して呼んでください - 各エングラムは独立したリクエストです。timeline
時系列リコール。関連度ではなく、出来事が起きた時点の新しい順に記憶を返します。「いつ X した?」という質問、履歴、順序の把握に。最大 15 件を返します。
events = mem.engram("timeline", "project milestones", user_id="alice"){ "engram": "timeline", "hops": 1, "count": 15,
"memories": [ ... ],
"usage": { "input_tokens": 4, "output_tokens": 88 } }usage(入力 + 出力)を返し、API の他の部分と同じトークナイザーで数えます。エングラムごとの隠れた料金はありません。複数を同時に使いたいときは並行して呼んでください - 各エングラムは独立したリクエストです。gather
広域収集。検索したうえで、上位 3 件のマッチの周辺を展開します - deep_recall より広い網です。人物・プロジェクト・トピックに関連するものすべてを、1 回の呼び出しで集めるのに使います。最大約 18 件を返します。
related = mem.engram("gather", "everything about Project Atlas", user_id="alice"){ "engram": "gather", "hops": 4, "count": 18,
"memories": [ ... ],
"usage": { "input_tokens": 6, "output_tokens": 142 } }usage(入力 + 出力)を返し、API の他の部分と同じトークナイザーで数えます。エングラムごとの隠れた料金はありません。複数を同時に使いたいときは並行して呼んでください - 各エングラムは独立したリクエストです。すべてのエンドポイントを、ひとつのベース URL で。
SDK は不要で、任意の HTTP クライアントで動きます。ベース URL は https://api.wontopos.com、認証は X-API-Key ヘッダー、入出力は JSON です。記憶の操作は POST、ストアの管理は /collection への POST / GET / DELETE です。ストアが先に存在しないと(ストア を参照)、ストア内の操作は 404 を返します。
| エンドポイント | 用途 | ボディフィールド |
|---|---|---|
| POST /api/v1/memory/collection | ストアを作成 | user_id |
| GET /api/v1/memory/collections | ストアを一覧 | (なし) |
| DELETE /api/v1/memory/collection | ストアとその記憶を削除 | user_id |
| /api/v1/memory/store | 記憶を 1 件保存 | user_id · content · metadata? (speaker) |
| /api/v1/memory/store-turn | 会話ターンを保存 | user_id · user_msg · assistant_msg |
| POST /api/v1/memory/speakers | 話者を登録(明示的、50 人まで) | user_id · speaker |
| GET /api/v1/memory/speakers | 登録済み話者の一覧 + 記憶数 | user_id |
| DELETE /api/v1/memory/speakers | 話者の登録解除(記憶は残る) | user_id · speaker |
| /api/v1/memory/bulk-store | テキストの塊を一括投入 | user_id · content · category? |
| /api/v1/memory/search | セマンティック検索 | user_id · query · max_results? · speaker? |
| /api/v1/memory/recall | 短期 + 長期 + コンテキスト | user_id · query |
| /api/v1/memory/history | 直近のターン | user_id |
| /api/v1/memory/stats | 記憶数 | user_id |
| /api/v1/memory/supersede | 変わった事実を置き換え | user_id · old_memory_id · new_content |
| /api/v1/memory/forget | 1 件(または全件)を削除 | user_id · memory_id? (省略 = 全件削除) |
# create the store once (stores are explicit) curl -X POST https://api.wontopos.com/api/v1/memory/collection \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice"}' # store a memory curl -X POST https://api.wontopos.com/api/v1/memory/store \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","content":"she prefers tea over coffee"}' # recall - one call, ready for your prompt curl -X POST https://api.wontopos.com/api/v1/memory/recall \ -H "X-API-Key: $WOS_API_KEY" -H "Content-Type: application/json" \ -d '{"user_id":"alice","query":"what does alice drink?"}'
{"id": "576700aa-f0e0-4c26-99a0-10e2d5b0d624", "status": "stored (1 chunks)"}機能は全員同じ。
ティアは上限を引き上げるだけ。
どのティアもフルエンジンで動きます - 同じリコール品質、同じ言語対応、すべてのメソッド。ティアは累計クレジット購入額の増加に応じて Tier 5 まで自動で上がり、申請も営業とのやり取りも不要です。Enterprise(Tier 6)だけが例外です。
支出上限
各ティアには、暦月ごとに支出できる上限があります。累計クレジット購入額が次のしきい値に達すると、即座に昇格します。
| 利用ティア | クレジット購入額 | 月間支出上限 |
|---|---|---|
| Tier 1 | $5 | $100 |
| Tier 2 | $40 | $500 |
| Tier 3 | $200 | $1,000 |
| Tier 4 | $400 | $5,000 |
| Tier 5 | $1,000 | $25,000 |
| Tier 6 - Enterprise | お問い合わせ | 無制限 |
レート制限
レート制限はアカウント単位です - アカウント内のすべての API キーがひとつの制限を共有し、ティアに応じて拡大します。超過すると retry-after ヘッダー付きの 429 が返るので、バックオフ(1s → 2s → 4s)して再試行してください。すべてのエンドポイントは冪等性に配慮した設計のため、再試行しても安全です。
| ティア | 毎分リクエスト数 |
|---|---|
| Tier 1 | 150 |
| Tier 2 | 300 |
| Tier 3 | 600 |
| Tier 4 | 1,500 |
| Tier 5 | 3,000 |
| Tier 6 - Enterprise | カスタム |
Enterprise(Tier 6)にはカスタムレート制限、SLA、専任サポート、オプションのセルフホストライセンスが付きます - お問い合わせください。
何かがうまくいかないとき。
エラーは JSON エンベロープで返ります。安定した type、人が読めるメッセージ、そして問題の報告時に添えられる request_id が含まれます。
{"type": "error", "error": {
"type": "authentication_error",
"message": "Invalid or revoked API key.",
"request_id": "063f8b83-eee2-4383-a5cf-11e4bcd29d7c"
}}| HTTP | 意味 | 対処 |
|---|---|---|
| 401 | API キーが無効または失効している | キーを確認し、コンソールで新しいキーを発行してください。 |
| 422 | 不正なボディ(フィールドの欠落・型違い) | メッセージに該当フィールドが明記されます - 修正して再試行してください。 |
| 429 | レート制限を超過 | 指数バックオフ(1s → 2s → 4s)で再試行してください。すべてのエンドポイントは冪等性に配慮しているため安全です。 |
| 5xx | サーバー側の問題 | バックオフしつつ再試行してください。お問い合わせの際は request_id を添えてください。 |
# SDK error handling (Python) from wontopos import Client, WosError try: mem.search("...", user_id="alice") except WosError as e: if e.status == 401: ... # bad key elif e.status == 429: ... # back off and retry
レート制限はアカウント単位で、すべてのキーが共有し、ティアに応じて拡大します - 利用ティア を参照してください。アカウントの使用状況はコンソールで確認できます。
あなたのサーバーに、あなたのデータを。
エンジンは自社インフラの中でも動かせます - 同じ API、同じ SDK のままで。クライアントの向き先を自分のホストに変えるだけで、ほかには何も変わりません。
mem = Client(api_key="...", base_url="https://wos.your-host.com")- データレジデンシー。記憶があなたのネットワークの外に出ることはありません。
- 同じインターフェース。同じメソッドとエンドポイントが、まったく同じように動きます。
- ライセンス。セルフホストのパッケージはデプロイごとに個別に取り決めます - お問い合わせください。
コンテキストウィンドウを超えて。
WOS は 1.4M トークンの履歴 - どの LLM のコンテキストウィンドウよりもはるかに大きな規模 - からリコールし、それでも約 1,470 トークンの引き締まったスライスだけを返します。
エージェントの記憶は、プロンプトに収まる量に縛られません。すべてを保持し、履歴がどれだけ大きくなっても、重要なものだけを取り出します。
プライベートで、あなたのもの。
データはあなたのストアに留まります。学習にも閲覧にも再利用にも使いません - 取り出せるように整理するだけです。
- BYOK。LLM キーはリクエストごとに送られ、保存されることはありません。
- 隔離。記憶はアカウント単位、さらに
user_id単位でスコープされます。 - GDPR 削除 & セルフホスト。1 回の呼び出しでユーザーを消去でき、必要ならエンジンを自社環境で運用できます。