wenchang/index.md View as Markdown (for AI agents; also llms.txt)
A memory store your agent writes to itself
wenchang is a Python library that lets an AI agent keep what it learns. During a conversation the agent decides what is worth remembering and saves it as markdown files. In later conversations it reads them back. The files live in Google Cloud Storage.
pip install "wenchang[mcp] @ git+https://github.com/msiebert/wenchang@v0.1.1"
Not on PyPI. The install is one line, but the library does nothing until you configure storage, identity, and prompts. Quickstart covers that.
What it is
Memory the agent decides to keep#
Most agents forget everything when a conversation ends. wenchang gives the agent a small set of tools for writing and reading memory. Nothing outside the agent decides what gets saved. The agent notices a character detail, a plot decision, or a style preference, and writes it down.
Say an author is writing a novel with an assistant built on wenchang. The author mentions that the protagonist, Lin Qiao, has grey eyes and grew up in a river town. The agent saves it in a file called project/p-ninth-examination/characters/lin-qiao.md:
description: Lin Qiao, the protagonist
aliases: Qiao
---
- [stated] Has grey eyes.
- [stated] Grew up in Yunmen, a river town.
Weeks later, in a new conversation, the author asks for a scene with Lin Qiao. The agent reads its index, opens that file, and gives her grey eyes. If the author changes their mind, the agent edits that one line.
wenchang does not decide what is worth keeping. A prompt that ships with the library tells the agent how to decide, and you can change that prompt. See Customizing the prompts.
How it works
How it works#
The agent starts from an index#
At the start of each session the agent calls get_memory_index(). It gets one entry for every file it has written: scope, area, name, version, a one-line description, and aliases. It does not get file contents. It reads the descriptions, decides which files matter for the current conversation, and opens only those.
// get_memory_index()
{
"entries": [
{
"scope": "project", "area": "characters", "name": "lin-qiao",
"version": "3",
"description": "Lin Qiao, the protagonist",
"aliases": ["Qiao"]
},
{
"scope": "project", "area": "timeline", "name": "main-timeline",
"version": "1",
"description": "Order of events in the novel",
"aliases": ["chronology", "timeline"]
}
],
"capped": []
}
Real entries also carry sources, and last_updated. If the index gets too big, it is cut at a size limit and the agent lists the rest with list_prefix. There is no search over file contents. Descriptions and aliases are how the agent finds things, so the agent keeps them up to date as it writes.
The agent organizes its own files#
The agent has seven tools: get_memory_index, read_file, list_prefix, write_file, append_line, replace_fact, and delete_file. Each fact is one line. The agent can add a line, change a line, or drop one. It can rewrite a file, create one, or delete one. It can change a file's description and aliases whenever it writes.
The library sets no schema. The agent decides how to split memory into files, which file a fact belongs in, and what to delete when a fact stops being true. The shipped prompt pushes it toward one file per subject, toward appending to an existing file instead of creating a duplicate, and toward removing a fact completely when the user asks it to forget.
Scopes and areas#
Every file path has this shape:
{scope}/{entity_id}/{area}/{name}.md
project/p-ninth-examination/characters/lin-qiao.md
A scope says who can see a file. You define the scopes. A common set is user (private to one person), project (shared by a team), and organization (shared by everyone, writable only by admins). For a novel, user is the author's own preferences, project is the manuscript, and organization is the publisher. The entity ID says whose copy of that scope it is: u-tianlong is one author, p-ninth-examination is one manuscript.
An area is a kind of information inside a scope, such as characters, plot, timeline, or style in a manuscript. You can seed the areas you care about in the prompt, for example "project: characters, plot, timeline, style". Or you can tell the agent to choose its own. Either way it can add areas by writing a file in a new one.
Every scope also has a system/ area. You fill it with curated content. The agent can read it and can never change it.
Versioned writes. Every write names the file version the agent read. If someone else changed the file in the meantime, the write fails and returns the current content, and the agent merges and retries.
Plain files. Each memory is a markdown file in one GCS bucket. The description and aliases are stored as object metadata beside it. You can browse the bucket with ordinary tools.
Sensitive data. The prompt tells the agent never to store financial account numbers, health diagnoses, or anything that suggests the user is a minor. This is prompt guidance. No tool filters content.
How you use it
How you use it#
wenchang is a library. You put its tools in front of your agent in one of three ways, all sharing the same store, identity rules, and prompt. Choose an integration path compares them.
A new MCP server. A short script builds a server with build_server and runs it over stdio or HTTP, for Claude Code or any MCP client. New MCP server
An existing MCP server. register_memory_tools adds the tools and prompt resource to an mcp 2.x MCPServer you already run. Existing MCP server
Without MCP. bind_tools returns the tools as Python methods for your own framework, with JSON Schemas from tool_schemas. Without MCP
The quickest start is a stdio server in Claude Code:
- Install it and create a GCS bucket for memory files. Quickstart
-
Write the server script. It picks the storage, says who the caller is, and builds the MCP server:
Quickstart
server = build_server( slots=slots, # your prompt text client=InProcessClient(MemoryStore(GcsStorage(bucket))), resolver=resolver, # who is calling, and with which scopes policy=policy, # which roles may write which scopes credentials_from_context=credentials_from_context, source="inkwell-web", ) server.run("stdio") -
Register it with your MCP client. For Claude Code,
claude mcp add memory -- python server.py. Quickstart - Tune the prompts. Four text slots tell the agent what your product is, which scopes exist, and which areas to start with. Customizing the prompts
- Plug in your own auth when more than one person uses the server. Identity and multi-tenant auth
Scope of the library
What wenchang is and is not#
wenchang provides the primitives for agent memory. It is not a hosted service and not a complete product.
wenchang provides#
- The seven tools the agent calls.
- The memory prompt that teaches the agent how to use them.
- The layer that writes to long-term storage (GCS), with versioned writes and size limits.
- Enforcement of your scope rules: the
system/area is read-only, and restricted scopes accept only the roles you name. - An MCP adapter, so the tools work in any MCP client, and JSON Schemas for other tool frameworks.
You provide#
- Authentication. Verifying who is calling.
- Authorization. Mapping each caller to the scopes, entity IDs, and roles they get. wenchang calls your resolver on every tool call over MCP, or once per
bind_toolscall without MCP, and trusts its answer. - A GCS bucket and credentials.
- The server process: where it runs and how clients reach it.
- Any content filtering beyond what the prompt asks for.
Not included#
- Search over file contents.
- A command line tool or ready-made server.
- A remote transport. The tools talk to storage in the same process.
- A production storage backend other than GCS.
FilesystemStorageandInMemoryStorageare for tests and local development.
Version 0.1.1, MIT license, Python 3.11 or newer. See Status and compatibility for known limits.