OneSelf Gives Every AI a Single User-Owned Context Profile
Stop Introducing Yourself to Every AI: I Built a "Personal Context" Management System
By 超级东哥CyberFD
One self. One context. Every AI.
Open source: https://github.com/ptonlix/OneSelf
Online instance: https://chenfudong.win/
一、It starts with "Hello, I'm..."
Have you ever felt this? Every time you open a new AI tool, the first thing you do is introduce yourself.
"I'm a backend engineer, mostly TypeScript, working on personal tools these days..." "I live in XX, prefer light flavors, no cilantro..." "I like my writing more conversational, not too many parallel constructions..."
Say it once in ChatGPT, once in Claude, write another set of rules in Cursor, and start from scratch in some new Agent. After enough repetition, you become "AI-friendly": you get used to compressing yourself into a few hundred characters of prompt, saved in a memo, copy-pasted everywhere.
Eventually I realized the problem isn't that any particular AI has a bad memory. Many products are doing "memory," and doing it better and better. The problem is that these memories live on someone else's platform. The "me" that A remembers, B doesn't know; the day I stop using A, that "me" stays there, not exportable, not cleanly deletable.
So I wanted a different approach:
Memory can belong to the Agent, but "who you are" must belong to you.
Your experience, knowledge, works, preferences should be held by you, like an ID card. Any AI that wants to know you asks your permission; you approve, then it can read. How much it reads is up to you; when you don't want to give it access anymore, you can revoke it at any time.
That's the starting point for OneSelf: an open-source, self-hosted "personal context" management system. One file about you, shared by all AIs. A balance between privacy and efficiency.
Below I'll walk through the design thinking completely: how I split the problem, the principles I set, how protocols and authorization are designed, how data is organized, and what it currently cannot do.
二、Three layers of the problem
"Making AI know me" sounds like one thing, but it's actually three layers.
Layer 1: Where does it live? Ownership
Where your context lives decides who has the final say.
If it lives inside an AI platform, it's the platform's data: the format is set by the platform, whether you can export is set by the platform, whether another model can use it is also set by the platform. If it lives in your own notes app, it's yours, but AI can't read it and you have to copy it manually.
What I want: data on my own machine, but AI can read and write it through a standard interface. Ownership stays with me, and usability doesn't suffer.
Layer 2: Who gets what? Authorization
Even if the data is in your hands, it doesn't mean you should dump everything out.
I can let the coding Agent know my tech stack and project history, but it doesn't need my medical report; I can let the travel-planning Agent know my dietary preferences, but it doesn't need my resume.
The harder part is "revoking." Many tools today treat authorization as one-time: you paste a piece of information into a chat box, it's out there, and there's no way to pull it back. I want authorization to be one-by-one, scoped, and revocable at any time.
Layer 3: Who maintains it? Efficiency
Once the first two layers are solved, there's a very practical question: who curates this information?
If every time I change jobs, move, or learn something new, I have to open the admin panel and edit entries one by one, this system probably won't survive three months. I'm exactly that kind of person.
So maintenance should be left to AI as much as possible. While it chats with me and helps me work, when it discovers a new fact, it writes it back; when an old fact becomes stale, it marks it or forgets it. I set the boundaries, the Agent does the work.
But "having AI maintain it" brings a new problem: AI can make mistakes. So changes must be traceable and rollback-able, and facts need confidence scores and validity periods.
Stack these three layers and you've basically outlined what OneSelf does.
三、Design principles
Before writing code, I set a few principles; all the design that follows is derived from them.
1. Private by default; public requires an explicit decision. All pages are private by default. For callers without permission, seeing a private page and seeing a non-existent page returns the same result: it shouldn't even know "there's something here but you can't see it."
2. Every authorization requires human approval. Whether it's an API Key or OAuth device code, the owner (you) must confirm on an approval page.
3. Agents can't issue keys to themselves. This one I thought about the longest. An Agent can read and write data within its authorized scope, but it cannot create or manage keys, cannot approve authorization on your behalf, and cannot push a public homepage live. The root of permissions always stays with a human.
4. Agent-first, but humans have final control. Interface design prioritizes how Agents use it: how to discover, connect, read, and write. The admin side only does the things that must be done by a person: approve, revoke, agree to go live, delete or restore.
5. Changes are traceable and rollback-able. AI makes mistakes, and so do people. Every write should have a history and be reversible.
6. Data stays on your machine. Self-hosted; Agents only use the interface, never touch the database directly.
四、Let the Agent find you: /.well-known/pcp
With principles set, the first concrete question is: when an Agent meets your OneSelf instance for the first time, how does it know what to do?
I don't want users to write a long integration description for every Agent. That goes back to the "introducing yourself everywhere" path, just now it's about a system.
My approach borrows the mature /.well-known/ convention from the Web and provides a discovery document:
GET https://your-site/.well-known/pcp
PCP (protocol: "pcp" in the discovery document) is the name I gave this interface. For now it's just OneSelf's own protocol, not an industry standard. The discovery document spells out everything an Agent needs to know:
- Protocol version and operation list
- How to attach authentication headers
- Which endpoints are public
- Upload limits
- OpenAPI document address, MCP endpoint address
- OAuth-related addresses
- Skill address
In other words, an Agent only needs a site URL; it reads /.well-known/pcp and knows what's here, how to connect, and what credentials it needs.
Besides the machine-readable discovery document, I also wrote a product Skill for Agents to read, called oneself. It tells the Agent the rules of the system: which reference to read before writing a page, which to read before changing a public page. Installation is one line:
npx skills add https://your-site -a <agent> -s oneself -y
Replace https://your-site with your own instance address and <agent> with the name of the Agent you use.
So "teaching an Agent to use my context" goes from writing a document to running one command.
---
五、One operation table, generating OpenAPI and MCP
Next, the interface itself.
There are two mainstream paths for Agents to integrate with external systems: plain HTTP API (with an OpenAPI document) and MCP. Different Agents prefer different ones, and I wanted to support both.
But I was afraid of one thing: two interfaces slowly drifting apart. HTTP gains a parameter, MCP forgets to update; MCP adds a validation, HTTP doesn't. Eventually the two behave differently, and permission checks diverge. That's a security hazard.
So in code I maintain a single operation registry (packages/operations/src/registry.ts). Each operation is defined once here: name, input schema, required permissions. Then:
- HTTP routes are derived from this table, and the OpenAPI document (
/openapi.json) is generated from the same table and the same input schemas shared with MCP; - MCP tools (
POST /mcp, Streamable HTTP transport) also come from this table, using the same authentication headers as HTTP.
One layer down, the HTTP and MCP entry points only handle authentication and returning results; actual use-case logic lives in the application layer, and business rules live in a separate domain package. Rules aren't written in routes, so the two entry points can't diverge from each other.
Currently the operations fall roughly into these groups:
| Group | Examples |
|---|---|
| Pages | put_page, edit_page, get_page, list_pages, delete_page, restore_page, get_versions, revert_version |
| Attachments | file_upload, file_list, file_url |
| Search | search, query, recall |
| Graph write-back | add_tag, add_link, get_backlinks, add_timeline_entry, remember, forget |
| Sources & identity | sources_list, sources_add, whoami, get_skill |
| Sites | put_site, preview_site, activate_site |
| HTTP-only | create_api_key, list_api_keys, revoke_api_key |
Note the last row: key-related operations exist only over HTTP, not exposed as MCP tools, and require owner identity. That's the "Agent cannot issue keys to itself" principle implemented at the interface level: an Agent's tool list simply doesn't include that hammer.
六、Authorization: approve an Agent like logging into a TV app
With the interface in place, the next question is: what credentials does an Agent use to call it?
I provide two options, choose one:
- API Key:
Authorization: ApiKey <key>orX-Api-Keyheader. For scripts and simple scenarios. - OAuth 2.1 device code:
Authorization: Bearer <token>. For Agents.
Both require owner approval. Let me focus on the device code, because I think it fits the Agent scenario especially well.
You've probably logged into a video app on your TV: the TV shows a code, you open a URL on your phone, type the code, confirm, and the TV is logged in. That's the device authorization grant flow. Its benefit: the device that needs authorization never touches your password.
Applied to an Agent, the flow looks like this:
- Agent requests a device code from
/oauth/device/auth; - Agent tells you the approval URL and user code (for example, in a conversation: "please open this link and confirm authorization");
- You log into the OneSelf admin UI (
/admin), see the request, confirm what it wants and what to grant, then approve; - Agent polls
/oauth/token, gets an access token, and can refresh it later.
Throughout the process, the Agent never sees your admin password and cannot complete the "approval" step itself. Only you can enter the approval page.
Revocation is just as simple: in the admin UI, every API Key and every device code grant can be revoked individually. Revoking one doesn't affect the others. If today I don't want a particular Agent to see my data anymore, I click once, no password change, no need to reconfigure other Agents.
Authorization scope is divided by source directory. For example, I split my data into profile, career, health directories, and can control per caller whether it can read, write, or change visibility in each directory. The coding Agent gets only profile and career; it can't see health—and as said, what it sees is identical to "there's nothing here."
One more detail: the public homepage. OneSelf can publish content you mark as public into an external personal homepage (visitors can only read public content). An Agent with site:write permission can help you edit the homepage and generate previews, but going live requires your approval. An Agent can only "request to go live," not "go live directly."
七、Data model: pages, attachments, and facts that expire
Now that authorization is sorted, let's look at how the data is organized. I spent a lot of time here because it determines whether AI maintenance feels smooth.
Pages + attachments
A piece of context consists of two kinds of things:
- Pages: Markdown files, uniquely identified by
(source, slug). Metadata liketype,title,visibility,tagsgoes in frontmatter. - Attachments: raw files like photos, PDFs (currently JPEG, PNG, WebP, GIF, PDF; max 20 MiB each), uploaded via
file_uploadand attached to a page'sfilesfield. Only if the attached page is public can the attachment be accessed anonymously.
I chose Markdown because it's friendly to both humans and AI: humans can read and edit it directly, and AI writes it most naturally, without learning a proprietary format.
Facts with expiration
Most statements about a person have a shelf life. "Currently lives in Shanghai" might be wrong next year; "learning Rust" might become "gave up Rust" in three months.
If you write these as permanent sentences, over time AI reads an outdated you. So there's a dedicated ## Facts section in pages, with each fact carrying confidence and validity period:
---
type: profile
title: engineer
name: Zhang San
visibility: public
tags: [public-profile]
files: []
---
# Zhang San
Building personal tools and developer products.
## Facts
- id: fact_01
entity: Zhang San
statement: Currently lives in Shanghai
confidence: 0.9
valid_until: 2027-01-01
## Timeline
- 2024-06-01 | Joined a company | Doing backend
confidence lets AI know how reliable this information is: did I say it myself, or did it infer from a document? valid_until tells it when to start doubting the fact and ask me. Agents can use the remember and forget operations to record or drop facts.
History: Timeline
The other type of information is history: what happened in which year. These don't "expire," but they have an order. They go in the ## Timeline section, one line each, date | event | note. Agents can append via add_timeline_entry.
Source of truth and projections
In storage, I make a distinction: the page originals and attachments are the source of truth, stored in object storage (RustFS); PostgreSQL stores the parsed body, tags, links, facts, and timeline — a projection derived from the originals, used for search and structured queries.
The benefit is that the real "source data" is always human-readable Markdown and raw files; if the database breaks, you can rebuild the projection without locking your data into a particular table schema.
Versioning and soft delete
As said, AI can make mistakes. So:
- Edits are incremental with version checks, so two Agents editing the same page at the same time don't overwrite each other;
- Each page keeps its last 50 versions; viewing and reverting happen not in the admin panel but through the same-named operations on PCP — OpenAPI and MCP share
get_versions/revert_version(reverting writes a new version, not a silent overwrite); - Deletion is soft delete, recoverable for 30 days (
restore_page). Sources can also be deleted and restored.
In my own usage, having this safety net is what makes me willing to let Agents reorganize my data.
八、Tech stack and deployment
The tech stack is simple:
- TypeScript (strict mode) + Node.js 24
- Hono 4 for the server, React 19 for the admin UI
- PostgreSQL 18 for projections, RustFS (S3-compatible) for originals and attachments
- MCP over Streamable HTTP transport
The whole service is one Node process: PCP, MCP, OAuth, admin UI, and published public sites are all served by the same Hono app. For personal self-hosting, fewer processes means fewer places to break.
Deployment uses Docker Compose, and the README offers a one-line install command (macOS / Linux):
curl -fsSL https://github.com/ptonlix/OneSelf/releases/latest/download/oneself.sh | sh
Windows has a corresponding PowerShell one-liner, see the repo README. The installer walks you through: admin account, external address, and which entry point to use (default local/LAN, or Cloudflare Tunnel, Caddy, or Tailscale). After installation:
- Open the homepage;
- Log in at
/adminand change the initial password; - Install the
oneselfSkill on your Agent, then approve its authorization request in the admin UI.
After that, update, health check, backup, and restore all have corresponding commands (update, doctor, backup, restore).

九、Welcome to try it
If you're tired of introducing yourself from scratch to every AI, feel free to try it:
- Source code: https://github.com/ptonlix/OneSelf (MIT license)
- Online instance: https://chenfudong.win/ — see what a public homepage looks like, and read its
/.well-known/pcp - Demo video: see the repo README
A few ways to get involved:
- Install one for yourself. One command installs it. Write a few pages for the information you get asked most often — tech stack, writing preferences, eating habits — then have your Agent install the Skill and request authorization. The next time you switch to a different AI, see whether it already knows you.
- File an issue. Anything that feels awkward, insecure, or missing, tell me. Security issues should go through the SECURITY.md in the repo; don't paste keys, passwords, or export bundles into an issue.
- Open a PR. Before making changes, read CONTRIBUTING.md and the PRD. When operation names, permissions, or error codes change, update the docs and the operation registry first.
Finally, the sentence that made me build this project:
Memory can belong to the Agent, but "who you are" must belong to you.
One self. One context. Every AI.