User-Owned Memory Protocol (UOMP)
Version: Draft-00
Status: Draft
Published: 2026-07-12
Goal: Public RFC draft for community review
1. Abstract
The User-Owned Memory Protocol (UOMP) defines a user-sovereign authorization protocol that allows users to temporarily grant AI Agents access to their personal memory data (preferences, settings, identity attributes, etc.). Authorization takes effect on a per-session basis, scoped by Tag or Key, and is revoked immediately when the session ends or is revoked. UOMP runs locally by default and defines an extension mechanism for remote Agents.
2. Status of This Memo
This document is the UOMP protocol draft (Draft-00). It describes the protocol design intent, data formats, HTTP API, and security requirements. It is intended to evolve into a formal standard through public discussion. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
3. Introduction
3.1 Motivation
When AI Agents provide services to users, they typically require access to personal data. Existing solutions often require users to upload data to the Agent provider’s server, leading to:
- Users losing direct control over their data.
- Agents potentially retaining user data indefinitely.
- Users having difficulty auditing what Agents have accessed.
UOMP’s design goals are:
- Users always own their memory data.
- Every access requires temporary authorization.
- Authorization scope is minimized.
- Authorization expires immediately after the session ends.
- All access is auditable.
3.2 Design Principles
- Local-first: In the default deployment model, Memory Guard runs on the local machine and only listens on
127.0.0.1. - Capability-based authorization: Uses short-lived Capability Tokens to express authorization scope.
- Tag/Key scoping: Authorization can be granted by tag or exact key.
- Session-bound: Tokens are bound to a specific Session and expire when the Session ends.
- Transport-agnostic core: The core protocol is based on HTTP but can be extended to other transports.
4. Terminology
| Term | Definition |
|---|---|
| Memory | User personal memory data, including preferences, settings, identity attributes, etc. |
| Memory Item | A single memory record containing key, value, tags, sensitivity, and other metadata. |
| Memory Store | User-side persistent storage for Memory Items. |
| Memory Guard | Access proxy layer that validates authorization, filters data, and records audit logs. |
| Auth Service | Session management component responsible for creating/closing Sessions and issuing/validating Capability Tokens. |
| Session | A single Agent task cycle with a unique session_id. |
| Capability Token | Session-level authorization credential specifying the Agent’s accessible tag/key scope. |
| Agent | A program that accesses user memory through UOMP, running locally or remotely. |
| uom.json | Agent manifest file describing the Agent’s identity and default requested memory scope. |
| Local Profile | Local deployment model where Memory Guard listens on 127.0.0.1. |
| Remote Profile | Remote deployment model where Memory Guard is exposed via TLS + mTLS. |
5. Protocol Overview
5.1 Architecture
5.2 Flow
- The Agent runs as an independent process and provides a
uom.jsondeclaring its identity and default requested memory scope. - The user discovers or connects to the Agent through the local UI/CLI, and the Auth Service creates a Session in the
createdstate. The Auth Service may run on the same machine as the Memory Guard / Store or may be provided by a trusted service chosen by the user. - After the user confirms or adjusts the authorization scope, the Auth Service issues a Capability Token.
- The Session enters the
activestate, and the Token is delivered to the Agent. - The Agent accesses Memory Guard via the HTTP API with the Token.
- Memory Guard validates the Token, filters data by scope, returns results, and records audit logs.
- When the Agent task completes, times out, or the user revokes, the Session closes and the Token becomes invalid.
The Agent and UI/CLI are separate processes. The UI/CLI runs on the user’s machine where the Memory Store / Guard lives, and is responsible for identity verification, authorization decisions, and Token delivery. The Agent only uses the Token to access data and never touches the user’s private keys.
5.3 Profiles
UOMP defines two deployment profiles:
| Profile | Default Port | Transport | Authentication |
|---|---|---|---|
| Local Profile | 127.0.0.1:9374 | HTTP | Capability Token |
| Remote Profile | User-configured | HTTPS | Capability Token + mTLS |
Local Profile is the default and RECOMMENDED configuration. Remote Profile MUST be explicitly enabled.
6. Agent Manifest: uom.json
6.1 Location
The Agent MUST provide a uom.json in the same directory as the executable or in the package root.
6.2 Format
{
"uomp_version": "1.0",
"agent": {
"id": "calendar_agent",
"name": "Calendar Assistant",
"version": "1.2.0",
"description": "Helps manage your schedule",
"publisher": "example-org"
},
"requested_scopes": {
"read": {
"tags": ["preference", "identity:public"],
"keys": [],
"description": "Read user preferences and public identity info"
},
"write": {
"tags": ["preference"],
"keys": [],
"description": "Write schedule-related preferences"
}
},
"required_capabilities": ["memory.read"],
"optional_capabilities": ["memory.query"],
"requires_remote": false,
"data_retention_policy": {
"max_retention_seconds": 300,
"deletion_method": "process_termination",
"proof_required": false,
"description": "Agent clears all user data within 5 minutes after task completion"
},
"identity": {
"did": "did:ethr:0xabc123...",
"verification_methods": ["did", "gpg", "x509"],
"proof": {
"type": "Ed25519Signature2020",
"created": "2026-07-12T10:00:00Z",
"proofValue": "..."
}
}
}
6.3 Fields
| Field | Type | Required | Description |
|---|---|---|---|
uomp_version | string | MUST | Protocol version, currently "1.0". |
agent.id | string | MUST | Unique Agent identifier. |
agent.name | string | MUST | Human-readable name. |
agent.version | string | MUST | Semantic version. |
agent.description | string | OPTIONAL | Function description. |
agent.publisher | string | OPTIONAL | Publisher name. |
requested_scopes | object | MUST | Default requested memory scope. |
required_capabilities | string[] | OPTIONAL | List of required capabilities. |
optional_capabilities | string[] | OPTIONAL | List of optional capabilities. |
requires_remote | boolean | OPTIONAL | Whether remote connection is required, default false. |
data_retention_policy | object | RECOMMENDED | Agent declares its data retention policy, see §6.5. |
identity | object | OPTIONAL | Publisher identity verification information. |
6.4 Scope Object
The Scope Object is used in requested_scopes.read and requested_scopes.write:
{
"tags": ["preference"],
"keys": ["user.display_name"],
"deny_tags": ["financial"],
"deny_keys": ["user.password"],
"allowed_fields": ["key", "value", "tags", "sensitivity"],
"description": "Why this scope is needed"
}
| Field | Type | Required | Description |
|---|---|---|---|
tags | string[] | MUST | List of tags requested for authorization. |
keys | string[] | MUST | List of specific keys requested for authorization. |
deny_tags | string[] | OPTIONAL | Explicitly denied tags. |
deny_keys | string[] | OPTIONAL | Explicitly denied keys. |
allowed_fields | string[] | OPTIONAL | Fields allowed to return per Memory Item. If absent, return the full item. |
description | string | RECOMMENDED | Purpose description for the authorization panel. |
6.5 Data Retention Policy
The Agent SHOULD declare a data retention policy in uom.json to be transparent to users about its data handling practices. UOMP does not technologically enforce this policy, but surfaces it to users for informed authorization decisions.
{
"data_retention_policy": {
"max_retention_seconds": 300,
"deletion_method": "process_termination",
"proof_required": false,
"description": "Agent clears all user data within 5 minutes after task completion",
"third_party_sharing": false,
"encryption_at_rest": true
}
}
| Field | Type | Required | Description |
|---|---|---|---|
max_retention_seconds | number | MUST | Maximum seconds the Agent promises to retain data after task completion. 0 means no persistence — discarded immediately. |
deletion_method | string | MUST | How data is deleted: process_termination (OS reclaims after process exit), secure_wipe (active overwrite), ephemeral_storage (no persistent disk). |
proof_required | boolean | OPTIONAL | Default false. If true, the Agent MUST submit a deletion proof before the Session closes (see §19). |
description | string | RECOMMENDED | Human-readable retention policy description. |
third_party_sharing | boolean | OPTIONAL | Default false. Whether the Agent shares user data with third parties (e.g., external APIs). |
encryption_at_rest | boolean | OPTIONAL | Default false. Whether the Agent encrypts temporarily stored user data at rest. |
Retention levels:
| Level | max_retention_seconds | deletion_method | Use case |
|---|---|---|---|
| Zero retention | 0 | process_termination | Stateless function/container; data never touches disk |
| Short retention | 300–600 | process_termination | Discard after each task |
| Session retention | matches Token expiry | secure_wipe | Cached until Session ends |
| No guarantee | large value | any | User sees red warning in authorization panel |
7. Capability Token
7.1 Format
The Capability Token uses JWT format and is signed by the Auth Service’s private key.
{
"version": "1.0",
"session_id": "sess_abc123",
"agent_id": "calendar_agent",
"issued_at": "2026-07-12T10:00:00Z",
"expires_at": "2026-07-12T10:30:00Z",
"scopes": {
"read": {
"tags": ["preference"],
"keys": ["user.display_name"],
"deny_tags": ["financial"],
"deny_keys": []
},
"write": {
"tags": [],
"keys": [],
"deny_tags": ["identity"],
"deny_keys": []
}
},
"limits": {
"max_read_queries": 50,
"max_write_queries": 10
},
"profile": "local",
"audience": "http://127.0.0.1:9374",
"allowed_endpoints": ["127.0.0.1"],
"allowed_fields": ["key", "value", "tags", "sensitivity"],
"aggregation_only": false,
"task_bound": false
}
7.2 Claims
The UOMP Capability Token JWT payload uses the following custom claims (snake_case). The Auth Service MUST also set the standard JWT claims iat (issued at) and exp (expiration time); the Memory Guard MUST accept and validate both exp and expires_at.
| Claim | Type | Required | Description |
|---|---|---|---|
version | string | MUST | Token format version. |
session_id | string | MUST | Bound Session. |
agent_id | string | MUST | Agent identifier. |
issued_at | ISO8601 | MUST | Issue time, consistent with standard iat. |
expires_at | ISO8601 | MUST | Expiration time, consistent with standard exp. |
scopes | object | MUST | Read/write authorization scope. |
limits | object | OPTIONAL | Query count limits. Written but not enforced in MVP. |
profile | string | OPTIONAL | local or remote, default local. |
audience | string | OPTIONAL | Memory Guard endpoint bound to the Token. REQUIRED for Remote Profile. |
allowed_endpoints | string[] | OPTIONAL | Network location whitelist for Token use. |
allowed_fields | string[] | OPTIONAL | Fields allowed to return per Memory Item. Memory Guard MUST filter results to include only these fields. |
aggregation_only | boolean | OPTIONAL | Default false. If true, only aggregation queries are permitted; returning individual Memory Item raw data is forbidden. |
task_bound | boolean | OPTIONAL | Default false. If true, the Token is bound to a single task; the Agent MUST submit a deletion proof after completion and destroy the Token. |
The JWT Header SHOULD include alg and kid to support key rotation and verification.
7.3 Validity
Upon receiving a Token, the Auth Service and Memory Guard MUST perform the following validations:
- Token signature is valid.
- Current time is before
expires_at/ standardexpclaim. - The Session bound to the Token has not been closed or revoked (in the MVP this is implemented via a blacklist table; production implementations SHOULD explicitly query Session status).
- Token is not in the blacklist.
profilematches the current deployment profile.audiencematches the current Memory Guard endpoint (REQUIRED for Remote Profile).
If any validation fails, Memory Guard MUST reject the request and return an error.
8. HTTP API
8.1 Base URL
- Local Profile:
http://127.0.0.1:9374 - Remote Profile: User-configured HTTPS URL
8.2 Versioning
API paths include the major version:
/v1/sessions
/v1/memory/:key
8.3 Authentication
All Agent requests MUST include the Token in the HTTP header:
Authorization: Bearer <capability-token>
8.4 Error Format
All error responses MUST use a unified format:
{
"error": {
"code": "ACCESS_DENIED",
"message": "Key is not within granted scope",
"session_id": "sess_abc123"
}
}
Common error codes:
| Error Code | Description |
|---|---|
INVALID_TOKEN | Invalid Token signature or format. |
TOKEN_EXPIRED | Token has expired. |
SESSION_REVOKED | Session has been revoked. |
ACCESS_DENIED | Request exceeds authorized scope. |
QUOTA_EXCEEDED | Query quota exhausted. |
WRITE_NOT_AVAILABLE | Write interface not enabled in MVP. |
STORE_UNAVAILABLE | Memory Store unavailable. |
SESSION_NOT_FOUND | Session does not exist or has been deleted. |
INVALID_REQUEST | Request format or parameters are invalid. |
9. Auth Service API
9.1 Create Session
POST /v1/sessions
Content-Type: application/json
Request:
{
"agent_id": "calendar_agent",
"agent_name": "Calendar Assistant",
"requested_scopes": {
"read": {
"tags": ["preference", "identity:public"],
"keys": []
}
},
"duration_minutes": 30
}
Response:
{
"session_id": "sess_abc123",
"status": "created",
"agent_id": "calendar_agent",
"requested_scopes": { ... },
"expires_at": "2026-07-12T10:30:00Z"
}
9.2 Grant Session
POST /v1/sessions/:id/grant
Content-Type: application/json
Request:
{
"granted_scopes": {
"read": {
"tags": ["preference"],
"keys": ["user.display_name"]
}
}
}
Response:
{
"token": "<jwt-capability-token>",
"token_type": "Bearer",
"expires_at": "2026-07-12T10:30:00Z"
}
9.3 Close Session
POST /v1/sessions/:id/close
Response:
{
"session_id": "sess_abc123",
"status": "closed"
}
9.4 Revoke Session
POST /v1/sessions/:id/revoke
Revoke MUST immediately invalidate the corresponding Token and add it to the persistent blacklist.
9.5 Validate Token
POST /v1/tokens/validate
Content-Type: application/json
Request:
{
"token": "<jwt-capability-token>"
}
Response:
{
"valid": true,
"session_id": "sess_abc123",
"expires_at": "2026-07-12T10:30:00Z"
}
9.6 Deletion Proof
If the Agent declares proof_required: true in its uom.json, it MUST submit a deletion proof before the Session is closed. See §19 for the full structure and flow.
POST /v1/sessions/{session_id}/deletion-proof
Authorization: Bearer <token>
Content-Type: application/json
{
"deletion_proof_id": "del_xxx",
"session_id": "sess_abc123",
"agent_id": "calendar_agent",
"deleted_at": "2026-07-12T10:35:00Z",
"memory_hash": "sha256:abc123...",
"fields_accessed": ["key", "value"],
"method": "process_termination",
"proof_value": "base64-encoded-agent-signature..."
}
Response (accepted):
{ "status": "accepted", "deletion_proof_id": "del_xxx" }
The Auth Service MUST verify session_id matches the path. If the Token has task_bound: true, the Session is automatically closed after the proof is accepted.
10. Memory Guard API
10.1 Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /v1/memory/:key | Read by key |
| GET | /v1/memory?tag=:tag | Read by tag |
| GET | /v1/memory/aggregate?tag=:tag&op=:op&field=:field | Aggregation query (sum/avg/count/min/max), no raw data, see §10.5 |
| GET | /v1/audit | Query audit logs, see §18 |
| POST | /v1/memory/query | Semantic query (not in MVP) |
| PUT | /v1/memory/:key | Write or update (MVP returns WRITE_NOT_AVAILABLE) |
| DELETE | /v1/memory/:key | Delete (MVP returns WRITE_NOT_AVAILABLE) |
10.2 Read by Key
GET /v1/memory/preference.theme
Authorization: Bearer <token>
Response:
{
"key": "preference.theme",
"value": "dark",
"tags": ["preference", "ui"],
"sensitivity": "low",
"source": "user",
"updated_at": "2026-07-12T10:00:00Z"
}
10.3 Read by Tag
GET /v1/memory?tag=preference
Authorization: Bearer <token>
Response:
{
"items": [
{
"key": "preference.theme",
"value": "dark",
"tags": ["preference", "ui"],
"sensitivity": "low"
}
]
}
10.4 Access Control
Memory Guard MUST determine access permissions in the following order:
- Token signature is valid.
- Token has not expired (validate both the standard
expclaim andexpires_at). - The Session bound to the Token has not been closed or revoked (MVP uses a blacklist table).
- Token is not in the blacklist.
- Query quota has not been exhausted (reserved in MVP, not enforced).
5b. If Token
aggregation_onlyistrue, non-aggregation paths (/v1/memory/:keyor/v1/memory?tag=) MUST be rejected. - Target Key or Tag is within the authorized scope for the action.
- Target Key or Tag is not explicitly denied (
deny_keys/deny_tagstake precedence over allow lists). sensitivity=highMemory Items cannot be accessed via tag authorization and MUST matchkeys.
For GET /v1/memory?tag=:tag, Guard MUST first validate that the tag itself is allowed; each returned Memory Item MUST then be filtered again using key-level rules (applying deny, keys, and sensitivity rules).
If any check fails, MUST return ACCESS_DENIED and record an audit log.
10.5 Aggregation Query
When the Token has aggregation_only: true, the Agent can only call aggregation endpoints — no individual Memory Item raw data is returned.
GET /v1/memory/aggregate?tag=portfolio:holdings&op=sum&field=value.market_value
Authorization: Bearer <token>
Query parameters:
| Parameter | Required | Description |
|---|---|---|
tag | MUST | Tag to aggregate. |
op | MUST | Operation: sum, avg, count, min, max. |
field | REQUIRED for numeric ops | Field path to aggregate (e.g. value.market_value). Not needed for count. |
Response (op=sum):
{ "op": "sum", "field": "value.market_value", "result": 39000 }
Response (op=count):
{ "op": "count", "tag": "portfolio:holdings", "result": 10 }
The Guard MUST first validate tag access authorization (same as regular tag queries), then compute the aggregation over authorized items. Aggregation results MUST NOT leak any individual key or value.
11. Memory Item
11.1 Format
{
"key": "preference.theme",
"value": "dark",
"tags": ["preference", "ui"],
"sensitivity": "low",
"source": "user",
"created_at": "2026-07-01T10:00:00Z",
"updated_at": "2026-07-12T10:00:00Z",
"description": "User interface theme preference"
}
11.2 Fields
| Field | Type | Required | Description |
|---|---|---|---|
key | string | MUST | Unique identifier, dot-separated namespace recommended. |
value | any | MUST | Memory value. |
tags | string[] | MUST | Tag list. |
sensitivity | enum | MUST | low, medium, or high. |
source | string | MUST | user or agent. |
created_at | ISO8601 | MUST | Creation time. |
updated_at | ISO8601 | MUST | Update time. |
description | string | OPTIONAL | Human-readable description. |
11.3 Sensitivity Rules
sensitivity=highMemory Items cannot be accessed via tag authorization.- Agents MUST NOT write any Memory Items during the MVP phase.
- After Milestone 2 introduces Staging writes, Agent writes to high-sensitivity items MUST still be rejected.
12. Memory Import Format
12.1 Overview
UOMP defines not only how Agents access Memory, but also how users populate the Memory Store from external data sources. A standard import format allows data from CSV, JSON, database exports, and other sources to be mapped unambiguously to Memory Items.
12.2 Design Goals
- Generality: Not tied to any specific application domain.
- Simplicity: Ordinary users can import using CSV or JSON directly.
- Extensibility: Implementations may define field aliases and mapping rules.
- Security: The tag and sensitivity of imported data must be explicit.
12.3 Supported Input Formats
- CSV: UTF-8 encoded, first row is a header, comma-separated.
- JSON: A single object or an array of objects.
12.4 CSV Format Requirements
- The file MUST be UTF-8 encoded.
- The first row MUST be a header row.
- The delimiter SHOULD be a comma; implementations MAY support other delimiters.
- Field values containing the delimiter MUST be wrapped in double quotes.
- Empty lines SHOULD be ignored.
- Numeric fields SHOULD NOT contain currency symbols or thousand separators; implementations MAY clean them automatically.
- Date fields SHOULD be ISO8601; implementations MAY recognize common formats and convert them.
12.5 JSON Format Requirements
- The root node MAY be a single object or an array of objects.
- Each object MAY contain:
key(string)value(object)tags(string or string array)sensitivity(low|medium|high)source(string)description(string)created_at/updated_at(ISO8601)
If value is omitted, all non-reserved top-level fields are treated as value.*.
12.6 Reserved Fields
The following top-level fields have protocol meaning and are NOT part of value:
keytagssensitivitysourcedescriptioncreated_atupdated_at
All other top-level fields belong to value.
12.7 Field Mapping
Implementations SHOULD support canonical field aliases:
| Memory Item Field | Canonical Aliases |
|---|---|
key | key, id, item_id, record_id |
tags | tags, tag |
sensitivity | sensitivity, level |
source | source, origin |
description | description, desc |
created_at | created_at, created |
updated_at | updated_at, updated |
Implementations MAY support locale-specific aliases (e.g., Chinese names) and user-defined mappings via --map or equivalent configuration.
12.8 Sensitivity
Imported data MUST have an explicit sensitivity. If the input does not specify sensitivity, the import tool MUST either:
- Require the user to specify it via CLI/GUI, or
- Refuse the import.
Implementations MAY provide application-specific default sensitivity based on tag, but such defaults MUST be clearly communicated to the user.
12.9 Validation
Before writing to the Memory Store, the import tool MUST validate:
keyis present and non-empty for every record.keyis unique within the target tag (unless--replaceis specified).sensitivityis one oflow,medium,high.tagsis non-empty.created_atandupdated_at, if present, are valid ISO8601 timestamps.
12.10 Examples
CSV Example
key,tags,sensitivity,value.title,value.content
note-1,notes,low,Shopping list,Buy milk
contact-1,contacts,medium,Alice,alice@example.com
JSON Example
[
{
"key": "note-1",
"tags": ["notes"],
"sensitivity": "low",
"value": {
"title": "Shopping list",
"content": "Buy milk"
}
},
{
"key": "contact-1",
"tags": ["contacts"],
"sensitivity": "medium",
"value": {
"name": "Alice",
"email": "alice@example.com"
}
}
]
13. Session
13.1 States
[created] --grant--> [active] --close/timeout/revoke/deletion-proof--> [closed/expired/revoked]
13.2 Fields
{
"session_id": "sess_abc123",
"agent_id": "calendar_agent",
"status": "active",
"created_at": "2026-07-12T10:00:00Z",
"expires_at": "2026-07-12T10:30:00Z",
"closed_at": null,
"granted_scopes": { ... },
"token_hash": "sha256:..."
}
13.3 Multi-Session Support
UOMP MUST support multiple independent Sessions existing simultaneously. Each Session has its own Token and lifecycle. Access from different Sessions MUST be audited independently.
13.4 Real-Time Revocation
After a Session is revoked, the corresponding Token MUST become invalid immediately. The Auth Service MUST add the Token to the persistent blacklist, and Memory Guard MUST check the blacklist on every request.
14. Local Profile
14.1 Requirements
- Memory Guard MUST listen on
127.0.0.1:9374by default. - Memory Guard MUST NOT bind to
0.0.0.0or public interfaces by default. - The Token’s
profileclaim MUST be"local"under Local Profile.
14.2 Token Delivery
In the Local Profile, the Token is issued by the Auth Service / CLI on the user’s machine and injected into the Agent process via environment variables:
export UOM_TOKEN="<capability-token>"
export UOMP_BASE_URL="http://127.0.0.1:9374"
uom-calendar-agent
UOM_TOKEN: The Capability Token the Agent uses to access Guard.UOMP_BASE_URL: The Guard endpoint address, defaulting tohttp://127.0.0.1:9374in Local Profile.
The user UI (e.g. CLI) runs on the same host as the Memory Store / Guard, performs identity verification and authorization, issues the Token, and only then hands the Token to the Agent. The Agent itself does not participate in authorization decisions.
15. Remote Profile
15.1 Overview
Remote Profile allows Agents not running on the user’s machine to access user memory. To protect the local Memory Guard, UOMP introduces the UOMP Gateway as the controlled entry point: the Memory Guard MUST NOT be directly exposed to the public internet, and all remote access MUST go through a user-deployed or user-trusted Gateway.
15.2 Security Requirements
Remote Profile implementations MUST satisfy:
- Gateway and remote Agent MUST use TLS 1.3.
- Gateway SHOULD use mTLS, with the remote Agent holding a client certificate issued by the user or Registry.
- Capability Tokens issued by the local Auth Service:
profileclaim MUST be"remote";audienceclaim MUST be bound to the Gateway endpoint, not to local127.0.0.1;allowed_endpointsclaim SHOULD restrict allowed Gateway network locations.
- Gateway MUST validate Token signature, lifetime,
audience, Session revocation status, and request path. - Token lifetime SHOULD not exceed 10 minutes; Agents that need long-running access SHOULD use refresh tokens (see 15.5).
- The user MUST explicitly enable Remote Profile and confirm the Gateway configuration.
- Communication between Gateway and local Memory Guard SHOULD use mTLS or a local Unix socket.
15.3 Deployment Models
Remote Profile defaults to user self-hosted Gateway:
- Users run Gateway on their own VPS, NAS, cloud server, or home server;
- Recommended:
uomp gateway startlaunches with Cloudflare Tunnel, automatically obtaining ahttps://xxx.trycloudflare.compublic URL — no public IP or port forwarding needed; - A reverse tunnel (Cloudflare Tunnel, ngrok) may also be used manually to expose the Gateway;
- A third-party MAY offer managed Gateway services, but open-source core implementations MUST retain self-hosting as the default and trust root.
15.4 UOMP Gateway
Gateway acts as a proxy for Memory Guard with the following responsibilities:
| Responsibility | Description |
|---|---|
| TLS/mTLS termination | Verify the transport-layer identity of the remote Agent |
| Token validation | Validate Capability Token signature, scope, lifetime, revocation status |
| Request forwarding | Forward validated requests to the local Memory Guard |
| Quota enforcement | Enforce request limits according to Token limits |
| Audit logging | Record gateway_access events |
| Payload caching | Temporarily store encrypted Agent output (optional) |
Gateway HTTP API SHOULD at least include:
GET /v1/health
POST /v1/sessions/{session_id}/refresh
GET /v1/memory/{key}
GET /v1/memory?tag={tag}
GET /v1/memory/aggregate?tag={tag}&op={op}
GET /v1/audit?session_id={session_id}
POST /v1/payload/upload
GET /v1/payload/{payload_id}
POST /v1/sessions/{session_id}/deletion-proof
All requests MUST carry:
Authorization: Bearer <gateway-token>
X-UOMP-Agent-Id: <agent_id>
Implementation reference:
uomp-mvpprovides a default mTLS Gateway reference implementation inapps/gateway, plusscripts/generate-gateway-certs.shandscripts/test-gateway-remote.shfor local validation.
15.5 Token Refresh
Remote Agents may need to refresh Tokens due to long-running tasks or SaaS restarts:
- During initial authorization, the Auth Service issues both a short-lived
access_tokenand arefresh_token:- The refresh_token can only be used to obtain a new access_token, not to read Memory;
- The refresh_token’s
scopesclaim MUST be empty or contain onlyrefresh; - Lifetime is configurable, default 7 days.
- Before the access_token expires, the Agent calls the Gateway:
POST /v1/sessions/{session_id}/refresh Authorization: Bearer <refresh_token> - Gateway validates the refresh_token and Session status, then requests a new access_token from the local Auth Service and returns it.
- When the user revokes the Session, the refresh_token MUST become invalid simultaneously.
15.6 Payload Delivery
Agent-generated reports and analysis results MUST NOT remain as plaintext on remote servers. Remote Profile requires:
- End-to-end encryption: The Agent encrypts the Payload using the public key provided in the Remote Profile (RECOMMENDED: ECDH-X25519 + AES-256-GCM).
- Payload Envelope: Uploaded Payloads MUST use the following format:
{ "payload_id": "pay_xxx", "session_id": "sess_xxx", "agent_id": "stock-analyst", "timestamp": "2026-07-14T10:15:00Z", "encryption": { "algorithm": "ECDH-X25519-AES256GCM", "sender_public_key": "...", "nonce": "..." }, "ciphertext": "base64...", "format": "text/markdown", "size": 2048, "hash": "sha256:..." } - Relay modes for encrypted Payload:
gateway-cache: Agent POSTs to Gateway; user pulls from Gateway;presigned-url: Gateway gives Agent a one-time upload URL; Agent uploads and returns the reference;ipfs-cid: Ciphertext on IPFS; CID + hash anchored on-chain.
The user’s local private key SHOULD be protected by a keystore or system keychain.
15.7 Migration to DIDComm
UOMP plans to migrate from mTLS HTTPS to DIDComm v2 for authorization negotiation and Token delivery in the long term. In MVP, mTLS HTTPS is the default channel, and DIDComm is an optional extension.
Migration strategy:
- Phase 1: Agents declare an mTLS endpoint; DIDComm is optional.
- Phase 2: Agents declare both mTLS and DIDComm service endpoints; user clients prefer DIDComm.
- Phase 3: New Agents MAY support only DIDComm; legacy Agents continue to work through an mTLS adapter.
Reserved DIDComm message types:
uomp/authorize-requestuomp/authorize-responseuomp/payload-readyuomp/session-revoked
16. Agent Identity Verification
16.1 Overview
UOMP supports multiple Agent publisher identity verification mechanisms. Identity verification is performed by the UI/CLI on the user’s machine; the Agent process itself does not perform identity verification and must not have access to user private keys or authorization decisions.
16.2 Supported Methods
| Method | Description |
|---|---|
| DID | Decentralized identifier, e.g., did:ethr, did:web. |
| GPG | Publisher signs uom.json with a GPG key. |
| X.509 | Publisher signs with a CA-issued certificate. |
| Registry | Verification status provided by registries such as ERC8004. |
16.3 Verification Process
- The UI/CLI on the user’s machine reads the
identityfield inuom.json. - Select the verification method according to
verification_methods. - Verify the signature or proof of
uom.json. - Present the result to the user; only after user confirmation may a Session be created and a Token issued.
16.4 Trust Policy
- Users MAY configure a trust list: trusted DIDs, GPG Key IDs, CAs, Registries.
- Agents that fail identity verification MAY be allowed to run, but the authorization panel on the user’s machine MUST prompt “unverified publisher”.
- Enterprise deployments MAY mandate specific verification methods; Agents that fail verification MUST NOT receive a Token.
17. Agent Registry
17.1 Overview
UOMP core protocol does not define an Agent Registry. Protocol reference implementations MAY support existing registry standards such as ERC8004.
17.2 Registry Client
The MVP reference implementation SHOULD provide the following CLI commands:
uomp registry search <keyword>
uomp registry install <agent_id>
Registry clients MUST return Agent metadata and uom.json location but MUST NOT participate in authorization decisions.
17.3 Registry Independence
- Users MUST be able to install and run Agents without using a Registry.
- Authorization decisions MUST always be made locally by the user.
18. Audit and Logging
18.1 Audit Log Entry
{
"id": "log_xxx",
"timestamp": "2026-07-12T10:05:00Z",
"session_id": "sess_abc123",
"agent_id": "calendar_agent",
"action": "read",
"key": "preference.theme",
"tags": ["preference", "ui"],
"allowed": true,
"reason": "scope matched",
"request_size": 0,
"response_size": 12,
"query_count_remaining": 49
}
18.2 Required Fields
Each audit log MUST contain:
timestampsession_idagent_idactionkeyortagallowedreason
18.3 Storage
- Audit logs MUST be stored separately from the Memory Store.
- Audit log retention MUST be configurable, default 90 days.
- Audit logs SHOULD be encrypted to prevent Agent tampering.
18.4 Blockchain Extension
UOMP MAY anchor summaries of key audit events to a blockchain for immutable audit proof. The protocol itself does not mandate a specific chain, but Starknet is RECOMMENDED as the default (low cost, high-frequency events), with EVM-compatible chains as an option.
18.4.1 Event Types
event SessionGranted(
bytes32 indexed sessionHash,
bytes32 indexed agentHash,
uint256 expiresAt
);
event SessionRevoked(
bytes32 indexed sessionHash,
bytes32 indexed agentHash
);
event GatewayAccess(
bytes32 indexed sessionHash,
bytes32 indexed agentHash,
bytes32 endpointHash,
bool allowed
);
event PayloadAnchored(
bytes32 indexed payloadHash,
bytes32 indexed sessionHash,
bytes32 agentHash
);
event DataDeletionProofSubmitted(
bytes32 indexed sessionHash,
bytes32 indexed agentHash,
bytes32 deletionProofHash
);
Hash computation:
sessionHash=keccak256(session_id || agent_id || granted_tags_json)agentHash=keccak256(agent_id)endpointHash=keccak256(request_path)payloadHash=sha256(ciphertext)deletionProofHash=keccak256(deletion_proof_id || session_id || memory_hash)
On-chain events MUST NOT contain specific Memory keys/values or Payload plaintext.
18.4.2 Batching Strategy
- Authorization events (
SessionGranted,SessionRevoked): low volume and high criticality, SHOULD be anchored near real-time. - Access events (
GatewayAccess): high volume, SHOULD be batched. Gateway aggregates events into a Merkle tree every N minutes or every M events, anchors themerkleRooton-chain, and keeps the full log locally for later verification. - Payload anchoring: each Payload SHOULD have its hash anchored individually after generation.
- Deletion proofs (
DataDeletionProofSubmitted): deletion proofs for each Session SHOULD be anchored near real-time after submission.
Local events ──► Batch aggregation ──► Merkle root ──► On-chain event
│
└── Full log retained at Gateway for audit verification
19. Data Retention & Deletion Proof
19.1 Overview
UOMP can control what data an Agent reads at the point of access via the Memory Guard, but cannot technologically guarantee the Agent deletes the data afterwards. This section defines:
- How Agents declare retention policies in
uom.json(§6.5). - How users constrain data exposure via the Capability Token (
allowed_fields,aggregation_only,task_bound). - How Agents can voluntarily submit verifiable deletion proofs.
- How deletion proofs integrate with the audit trail and optional blockchain anchoring.
19.2 Data Exposure Controls
allowed_fields
By specifying allowed_fields in the Capability Token, the user (or CLI rules) constrains which fields of each Memory Item are returned. The Memory Guard MUST filter every returned item to include only the specified fields:
{
"allowed_fields": ["key", "value"]
}
If allowed_fields is absent, all fields are returned. For high-sensitivity data (sensitivity=high), allowed_fields SHOULD default to exclude metadata such as sensitivity and source.
aggregation_only
When aggregation_only: true, the Agent is only permitted to call aggregation endpoints that return computed results (sum, average, count, etc.), not individual Memory Items:
GET /v1/memory/aggregate?tag=portfolio:holdings&op=sum&field=value.market_value
Aggregation queries MUST NOT return any individual key or value. The Guard MUST reject non-aggregation requests (/v1/memory/:key, /v1/memory?tag=) from aggregation_only Tokens.
task_bound
When task_bound: true, the Token is valid for a single task. After the task completes, the Agent MUST call the deletion proof endpoint and the Session is automatically closed. The Token cannot be used for subsequent reads.
19.3 Deletion Proof
If the Agent declares proof_required: true in its retention policy, it MUST submit a deletion proof before the Session is closed. The proof is a structured statement signed by the Agent’s identity key:
{
"deletion_proof_id": "del_xxx",
"session_id": "sess_abc123",
"agent_id": "calendar_agent",
"deleted_at": "2026-07-12T10:35:00Z",
"memory_hash": "sha256:abc123...",
"fields_accessed": ["key", "value"],
"method": "process_termination",
"proof_value": "base64-encoded-agent-signature..."
}
| Field | Type | Required | Description |
|---|---|---|---|
deletion_proof_id | string | MUST | Unique identifier for this proof. |
session_id | string | MUST | The Session under which data was accessed. |
agent_id | string | MUST | Agent identifier. |
deleted_at | ISO8601 | MUST | Timestamp when deletion was completed. |
memory_hash | string | MUST | SHA-256 hash of all accessed memory item keys concatenated with their values (used for post-hoc verification of which data the Agent held). |
fields_accessed | string[] | RECOMMENDED | Fields the Agent actually read. |
method | string | MUST | Deletion method; must match data_retention_policy.deletion_method. |
proof_value | string | MUST | Agent’s cryptographic signature over the proof structure using its identity key. |
19.4 Submission & Audit Integration
The Agent submits the deletion proof via:
POST /v1/sessions/{session_id}/deletion-proof
Authorization: Bearer <token>
Content-Type: application/json
Upon receipt, the Auth Service or Gateway:
- Verifies the
proof_valuesignature against the Agent’s registered identity public key. - Validates that
deleted_at≤ Tokenexpires_at. - Records the proof in the audit log with
action: deletion_proof. - If
task_bound: true, automatically closes the Session. - Optionally anchors the proof hash on-chain (§19.6).
If the Agent fails to submit a deletion proof before Session expiration (and proof_required was true), the audit log records a deletion_proof_missing event. This may trigger reputation penalties or bond forfeiture in any reputation system.
19.5 Atomic Guarantee
When both task_bound: true and proof_required: true are set, deletion proof submission is a prerequisite for normal Session closure. Sessions lacking a proof are marked as abnormal, and the Agent’s Registry reputation score degrades. This provides an economic/reputation-level atomicity guarantee as compensation for the technological infeasibility.
Future extension: TEE (Trusted Execution Environment) enables hardware-level atomicity — the Agent code runs inside an enclave, memory is automatically zeroed on exit, and hardware attestation is provided.
19.6 Deletion Proof Anchoring
In addition to the blockchain events in §18.4.1:
event DataDeletionProofSubmitted(
bytes32 indexed sessionHash,
bytes32 indexed agentHash,
bytes32 deletionProofHash
);
deletionProofHash=keccak256(deletion_proof_id || session_id || memory_hash)
This event SHOULD be anchored near real-time after the Agent submits the deletion proof.
20. Security Considerations
20.1 Token Security
- Capability Tokens MUST be signed by the Auth Service’s private key.
- Tokens SHOULD use short lifetimes (default 30 minutes, 10 minutes for Remote Profile).
- Tokens MUST NOT be persisted to locations freely accessible by the Agent.
20.2 Memory Store Security
- Memory Store SHOULD be encrypted.
- High-sensitivity data SHOULD be additionally encrypted.
20.3 Communication Security
- Local Profile uses HTTP over localhost.
- Remote Profile MUST use TLS 1.3 + mTLS.
- SDKs MUST NOT log Tokens.
20.4 Agent Write Restrictions
- Agents MUST NOT write Memory during the MVP phase.
- After Milestone 2 introduces Staging writes, Agent writes MUST be confirmed by the user before taking effect.
- Agents MUST NOT write
sensitivity=highMemory Items.
21. Privacy Considerations
- UOMP aims to minimize the scope of data accessed by Agents.
- Users SHOULD be able to view and revoke any active Session.
- Audit logs SHOULD help users understand what data Agents accessed.
- Memory Guard SHOULD avoid returning any data outside the authorized scope, including existence information.
22. Future Work
- Agent write staging.
- Semantic retrieval (
queryendpoint). - Write version history and rollback.
- Policy templates.
- DIDComm v2 authorization channel.
- Decentralized Payload Relay (IPFS, etc.).
- TEE (Trusted Execution Environment) Agent execution for hardware-level data retention guarantees.
- Stateless Agent execution model with per-task isolation.
- Agent reputation system integrated with Registry.
23. References
- [RFC 2119] Key words for use in RFCs to Indicate Requirement Levels
- [RFC 7519] JSON Web Token (JWT)
- [RFC 8446] The Transport Layer Security (TLS) Protocol Version 1.3
- [ERC8004] Agent Registry on Blockchain
Appendix A: Minimal Interaction Example
# 1. Discover an Agent (via ERC8004 Registry or locally)
uomp registry search calendar
# 2. Install Agent
uomp registry install calendar_agent
# 3. Create Session on the user side
curl -X POST http://127.0.0.1:9374/v1/sessions \
-H "Content-Type: application/json" \
-d '{
"agent_id": "calendar_agent",
"agent_name": "Calendar Assistant",
"requested_scopes": {
"read": { "tags": ["preference"], "keys": [] }
},
"duration_minutes": 30
}'
# 4. User grants authorization
curl -X POST http://127.0.0.1:9374/v1/sessions/sess_abc123/grant \
-H "Content-Type: application/json" \
-d '{
"granted_scopes": {
"read": { "tags": ["preference"], "keys": [] }
}
}'
# 5. Run Agent with Token
export UOM_TOKEN="<token>"
uom-calendar-agent
# 6. Agent reads memory internally
# const memory = new UserMemory({ token: process.env.UOM_TOKEN });
# const theme = await memory.get<string>('preference.theme');
# 7. Close Session
curl -X POST http://127.0.0.1:9374/v1/sessions/sess_abc123/close
Appendix B: Complete uom.json Example
{
"uomp_version": "1.0",
"agent": {
"id": "calendar_agent",
"name": "Calendar Assistant",
"version": "1.2.0",
"description": "Helps manage your schedule and todos",
"publisher": "example-org"
},
"requested_scopes": {
"read": {
"tags": ["preference", "identity:public"],
"keys": [],
"description": "Read user preferences and public identity info for personalized schedule suggestions"
},
"write": {
"tags": ["preference"],
"keys": [],
"description": "Write schedule-related preferences"
}
},
"required_capabilities": ["memory.read"],
"optional_capabilities": ["memory.query"],
"requires_remote": false,
"data_retention_policy": {
"max_retention_seconds": 300,
"deletion_method": "process_termination",
"proof_required": false,
"description": "Agent clears all user data within 5 minutes after task completion"
},
"identity": {
"did": "did:ethr:0xabc123...",
"verification_methods": ["did", "gpg"],
"proof": {
"type": "Ed25519Signature2020",
"created": "2026-07-12T10:00:00Z",
"proofValue": "..."
}
}
}