Pular para o conteúdo

Especificação v1.0

Status: Publicado
Date: 2026-02-17
Authors: Daniel Gines [email protected] (https://github.com/danielgines)
License: CC BY 4.0 (specification), Apache 2.0 (schema and reference implementation)


Este documento define o Portable AI Memory (PAM), um formato de intercâmbio para memórias de usuário geradas por assistentes de IA. O PAM permite a portabilidade do contexto do usuário, preferências, conhecimento e histórico de conversas em qualquer provedor de LLM, sem aprisionamento a fornecedor (vendor lock-in) ou perda semântica de dados.

O PAM está para a memória de IA assim como o vCard está para contatos e o iCalendar está para eventos: um formato de intercâmbio universal que desacopla os dados do usuário de implementações específicas.


Assistentes de IA (ChatGPT, Claude, Gemini, Grok, etc.) acumulam conhecimento sobre os usuários ao longo do tempo — preferências, expertise, projetos, objetivos e padrões comportamentais. Esse conhecimento é armazenado em formatos proprietários e não documentados, sem interoperabilidade entre provedores. Os usuários não conseguem:

  • Migrar o contexto de IA ao trocar de provedor
  • Manter uma identidade unificada em múltiplos assistentes de IA
  • Auditar, corrigir ou gerenciar memórias sistematicamente
  • Possuir e controlar o conhecimento pessoal gerado por IA

O PAM define um formato de intercâmbio JSON padronizado com:

  • Uma taxonomia fechada de tipos de memória
  • Rastreamento completo de proveniência (qual plataforma, conversa e método produziu cada memória)
  • Gerenciamento de ciclo de vida temporal (criação, validade, substituição, arquivamento)
  • Pontuação de confiança com modelos de decaimento
  • Hashing de conteúdo para deduplicação determinística
  • Um grafo de relações semânticas entre memórias
  • Controle de acesso para cenários multi-agente e de federação
  • Embeddings opcionais como arquivo complementar separado
  • Verificação de integridade para detecção de corrupção e adulteração

O PAM é um formato de intercâmbio, não um formato de armazenamento. Implementações SHOULD usar bancos de dados ( SQLite, PostgreSQL, bancos de dados vetoriais, bancos de dados em grafo) para armazenamento interno e MUST suportar exportação e importação usando este formato.

As palavras-chave “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHOULD”, “SHOULD NOT”, “MAY” e “OPTIONAL” neste documento devem ser interpretadas conforme descrito na RFC 2119.


Uma exportação PAM consiste em um arquivo obrigatório e arquivos complementares opcionais:

FileRequiredDescription
memory-store.jsonYesArquivo principal de intercâmbio com memórias, relações, índice de conversas e bloco de integridade
conversations/*.jsonNoArquivos individuais de conversa referenciados por conversations_index[].storage.ref
embeddings.jsonNoArquivo separado contendo embeddings vetoriais para objetos de memória

Cada tipo de arquivo é validado contra seu próprio schema JSON Schema Draft 2020-12:

  • schemas/portable-ai-memory.schema.json — validates memory-store.json
  • schemas/portable-ai-memory-conversation.schema.json — validates conversation files (see §25)
  • schemas/portable-ai-memory-embeddings.schema.json — validates embeddings.json

{
"schema": "portable-ai-memory",
"schema_version": "1.0",
"spec_uri": "https://portable-ai-memory.org/spec/v1.0",
"export_id": "e47ac10b-58cc-4372-a567-0e02b2c3d479",
"exported_by": "system-name/1.0.0",
"export_date": "2026-02-15T22:00:00Z",
"owner": {
...
},
"memories": [
...
],
"relations": [
...
],
"conversations_index": [
...
],
"integrity": {
...
},
"export_type": "full",
"type_registry": "https://portable-ai-memory.org/types/",
"signature": {
...
}
}
FieldTypeDescription
schemastringMUST ser "portable-ai-memory"
schema_versionstringVersão semântica. Atual: "1.0"
ownerobjectIdentificação do proprietário
memoriesarrayArray de objetos de memória
FieldTypeDescription
spec_uristring|nullURI ou URN da versão da especificação. Implementações MUST NOT exigir que spec_uri seja resolvida pela rede
export_idstring|nullIdentificador único para esta exportação (UUID v4). Permite rastreamento e detecção de duplicatas
exported_bystring|nullSistema que gerou a exportação. Formato: "name/semver"
export_datestringTimestamp ISO 8601 da exportação
relationsarrayRelacionamentos semânticos entre memórias
conversations_indexarrayReferências leves de conversas
integrityobjectBloco de verificação de integridade
export_typestring"full" ou "incremental". Padrão: "full" (Section 16)
base_export_idstring|nullPara exportações incrementais: export_id da exportação base (Section 16)
sincestring|nullPara exportações incrementais: timestamp de corte ISO 8601 (Section 16)
type_registrystring|nullURI do registro de tipos oficial (Section 19)
signatureobject|nullAssinatura criptográfica (Section 18)

O objeto de memória é a unidade fundamental do formato. Cada memória representa um fragmento discreto de conhecimento sobre o usuário.

FieldTypeDescription
idstringIdentificador único. SHOULD ser UUID v4
typestringTipo de memória da taxonomia fechada (Section 5)
contentstringConteúdo em linguagem natural. Payload semântico primário
content_hashstringSHA-256 do conteúdo normalizado (Section 6)
temporalobjectMetadados temporais. created_at é obrigatório
provenanceobjectMetadados de origem. platform é obrigatório
FieldConditionDescription
custom_typeREQUIRED when type == "custom"Identificador de tipo personalizado. MUST ser null quando o tipo não é "custom"
FieldTypeDefaultDescription
statusstring"active"Status do ciclo de vida (Section 7)
summarystring|nullnullResumo curto para exibição
tagsarray[]Tags em minúsculas. Pattern: ^[a-z0-9][a-z0-9_-]*$
confidenceobjectPontuação de confiança (Section 8)
accessobjectControle de acesso (Section 9)
embedding_refstring|nullnullReferência ao arquivo de embeddings (Section 12)
metadataobjectMetadados adicionais (Section 10)

O PAM define uma taxonomia fechada de tipos de memória. A taxonomia é extensível via o tipo "custom".

TypeDescription
factInformação objetiva e verificável sobre o usuário
preferencePreferência, gosto ou desejo declarado do usuário
skillCompetência, expertise ou habilidade demonstrada
contextContexto situacional ou temporal
relationshipRelação com outra pessoa, entidade ou organização
goalObjetivo ativo ou aspiração
instructionComo o usuário deseja ser tratado ou endereçado
identityInformação de identidade pessoal
environmentDetalhes do ambiente técnico ou físico
projectProjeto ativo ou iniciativa
customTipo extensível. REQUIRES o campo custom_type
IF type == "custom" THEN custom_type MUST be a non-empty string
IF type != "custom" THEN custom_type MUST be null

Exemplo:

{
"type": "custom",
"custom_type": "security_clearance"
}

O campo content_hash permite deduplicação determinística entre exportações de diferentes plataformas.

normalize(content):
1. Trim leading and trailing whitespace
2. Convert to lowercase
3. Apply Unicode NFC normalization
4. Collapse multiple consecutive spaces to a single space
content_hash = "sha256:" + hex(SHA-256(UTF-8(normalize(content))))

Pattern: ^sha256:[a-f0-9]{64}$

Exemplo: "sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"


Cada memória possui um campo status que rastreia seu estado no ciclo de vida.

StatusDescription
activeAtual e válida. Estado padrão
supersededSubstituída por uma memória mais recente. temporal.superseded_by SHOULD referenciar o substituto
deprecatedAinda válida, mas sem prioridade
retractedExplicitamente invalidada pelo usuário
archivedRetida apenas para fins históricos
active → superseded (new information replaces old)
active → deprecated (relevance diminished)
active → retracted (user explicitly invalidates)
active → archived (user archives for history)
superseded → archived (historical retention)
deprecated → retracted (user explicitly invalidates)
deprecated → archived (historical retention)

O bloco confidence contém pontuações calculadas pelo sistema. Este NÃO é a prioridade definida pelo usuário.

FieldTypeDescription
initialnumber [0.0, 1.0]Confiança no momento da extração
currentnumber [0.0, 1.0]Confiança atual após decaimento e reforço
decay_modelstring|nullModelo de decaimento: "time_linear", "time_exponential", "none", ou null
last_reinforcedstring|nullTimestamp ISO 8601 do último reforço
  • time_linear: A confiança diminui linearmente com o tempo desde o último reforço
  • time_exponential: A confiança diminui exponencialmente com o tempo
  • none: Sem decaimento automático (ex.: fatos de identidade)

A taxa de decaimento específica é definida pela implementação. O PAM registra o modelo, não os parâmetros.


O bloco access habilita cenários multi-agente e de federação.

FieldTypeDefaultDescription
visibilitystring"private""private", "shared", ou "public"
exportablebooleantrueSe esta memória MAY ser incluída em exportações
shared_witharray[]Lista de concessões de acesso

Cada concessão especifica uma entidade e suas permissões:

{
"entity": "agent-work-assistant",
"permissions": [
"read"
]
}

Permissions: "read", "write", "delete".


O bloco metadata contém propriedades adicionais não semânticas. Este bloco permite additionalProperties para extensibilidade.

FieldTypeDescription
languagestring|nullBCP 47 language tag. Pattern: ^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2})?$
domainstring|nullDomínio de conhecimento (ex.: "technical", "personal", "professional")

Implementações MAY adicionar campos personalizados a este bloco.


O bloco provenance habilita auditabilidade e resolução de conflitos entre plataformas.

FieldTypeDescription
platformstringIdentificador da plataforma de origem
FieldTypeDescription
platform_user_idstring|nullID do usuário na plataforma de origem
conversation_refstring|nullReferência à entrada do conversations_index
message_refstring|nullReferência a uma mensagem específica
extraction_methodstring|nullComo a memória foi extraída
extracted_atstring|nullTimestamp ISO 8601 da extração
extractorstring|nullSistema que realizou a extração
MethodDescription
llm_inferenceLLM inferiu a memória a partir da conversa
explicit_user_inputUsuário declarou explicitamente a informação
api_exportExtraída da API/exportação da plataforma
browser_extractionExtraída via automação de navegador ou extensão
manualInserida manualmente pelo usuário ou operador

Identificadores de plataforma MUST ser ASCII minúsculo correspondendo ao padrão:

^[a-z0-9_-]{2,32}$

Identificadores SHOULD ser registrados em um registro público para evitar colisões.

O mesmo namespace de identificadores MUST ser usado em todos os schemas PAM: provenance.platform no memory store, conversations_index[].platform e provider.name no schema de conversas. Use nomes de produtos, não nomes de empresas.

Identificadores recomendados (lista não exaustiva):

chatgpt, claude, gemini, grok, perplexity, copilot, local, manual


Embeddings são OPTIONAL. Eles são armazenados em um arquivo embeddings.json separado.

  1. Embeddings MAY ser totalmente omitidos de uma exportação
  2. Quando omitidos, embedding_ref em objetos de memória MUST ser null
  3. Consumidores MUST NOT falhar se embedding_ref for null ou se embeddings.json estiver ausente
  4. Consumidores MAY regenerar embeddings a partir do campo content a qualquer momento usando qualquer modelo
  5. O campo content no objeto de memória é SEMPRE a fonte autoritativa de conteúdo semântico, nunca o embedding
  6. Cada objeto de memória MUST ter no máximo um embedding correspondente no arquivo de embeddings — o campo memory_id MUST ser único entre todos os objetos de embedding. Implementações que mantêm múltiplos embeddings internamente (ex.: para diferentes modelos) SHOULD exportar apenas o embedding mais recente ou preferido
{
"schema": "portable-ai-memory-embeddings",
"schema_version": "1.0",
"embeddings": [
{
"id": "emb-uuid",
"memory_id": "mem-uuid",
"model": "text-embedding-3-small",
"dimensions": 1536,
"created_at": "2026-02-15T22:00:00Z",
"vector": [
0.1,
0.2,
...
],
"storage": null
}
]
}
FieldRequiredTypeDescription
idYesstringIdentificador único. Referenciado por memory.embedding_ref
memory_idYesstringID do objeto de memória associado
modelYesstringIdentificador do modelo de embedding
dimensionsYesintegerDimensionalidade do vetor
created_atYesstringTimestamp ISO 8601
vectorNoarray|nullVetor inline. Null se armazenado externamente
storageNoobject|nullReferência de armazenamento externo

O array relations define relacionamentos semânticos entre objetos de memória, formando um grafo de conhecimento.

FieldRequiredTypeDescription
idYesstringIdentificador único
fromYesstringID da memória de origem
toYesstringID da memória de destino
typeYesstringTipo de relacionamento
confidenceNonumber|nullConfiança neste relacionamento [0.0, 1.0]
created_atYesstringTimestamp ISO 8601
TypeSemantics
supportsA origem fornece evidência para o destino
contradictsA origem conflita com o destino
extendsA origem adiciona detalhes ao destino
supersedesA origem substitui o destino
related_toRelação semântica geral
derived_fromA origem foi inferida a partir do destino

O índice de conversas fornece referências leves a conversas sem incorporar o histórico completo de mensagens.

Exporters MUST garantir consistência entre memory.provenance.conversation_ref e a entrada correspondente em conversations_index[].derived_memories.

Importers SHOULD tratar derived_memories como informativo e MAY reconstruir a partir da proveniência usando:

for memory in memories:
conv_id = memory.provenance.conversation_ref
if conv_id:
conversations_index[conv_id].derived_memories.append(memory.id)

Os dados completos da conversa são armazenados externamente e referenciados via:

{
"storage": {
"type": "file",
"ref": "conversations/conv-001.json",
"format": "json"
}
}

Storage types: "file", "database", "object_storage", "vector_db", "uri".


O bloco integrity habilita a detecção de corrupção e adulteração.

O PAM usa RFC 8785 (JSON Canonicalization Scheme — JCS) para serialização determinística. O campo canonicalization declara o método utilizado:

ValueStandardDescription
RFC8785RFC 8785JSON Canonicalization Scheme. Método padrão e único suportado atualmente

Isso elimina ambiguidade de implementação entre linguagens e plataformas. O RFC 8785 define regras determinísticas para ordenação de chaves, serialização de números, escape de strings e eliminação de espaços em branco.

O checksum é calculado usando o seguinte pipeline determinístico:

1. Take the memories array
2. Sort memory objects by id ascending
3. Canonicalize per RFC 8785 (JCS):
- Sort all object keys lexicographically (recursive)
- Serialize numbers per ECMAScript/IEEE 754 rules (e.g., 1.0 → 1)
- Apply RFC 8785 string escaping
- No whitespace
- UTF-8 encoding
4. Compute SHA-256 over the canonical UTF-8 bytes
5. Format as "sha256:<hex>"

IMPORTANT: O json.dumps() padrão na maioria das linguagens NÃO é compatível com RFC 8785. Implementações MUST usar uma biblioteca JCS dedicada. Veja o Appendix C para recomendações de bibliotecas por linguagem.

FieldRequiredTypeDescription
canonicalizationNostringMétodo de canonicalização. Padrão: "RFC8785"
checksumYesstringSHA-256 das memórias canonicalizadas. Formato: sha256:<hex>
total_memoriesYesintegerMUST ser igual a len(memories)
integrity.total_memories MUST equal len(memories)
integrity.checksum MUST match the computed checksum of the canonicalized memories array
If integrity.canonicalization is absent, implementations MUST assume RFC8785

O PAM suporta exportações completas e incrementais (delta) para sincronização eficiente.

TypeDescription
fullMemory store completo. Padrão. Autocontido
incrementalDelta desde uma exportação anterior. Contém apenas memórias novas ou atualizadas

Quando export_type for "incremental":

FieldRequiredDescription
base_export_idSHOULDO export_id da exportação base à qual este delta se aplica
sinceSHOULDTimestamp ISO 8601. Apenas memórias criadas ou atualizadas após este momento são incluídas

Importers processando exportações incrementais MUST:

  1. Corresponder base_export_id a uma exportação completa previamente importada
  2. Para cada memória no delta: se id existir na base, atualizá-la; caso contrário, inseri-la
  3. Recalcular integrity.checksum após a mesclagem
  4. Memórias com status: "retracted" no delta MUST ser marcadas como retracted na base
  5. Importers MUST NOT excluir fisicamente memórias marcadas como "retracted". Eles MUST preservar o objeto de memória e atualizar seu status. Isso garante auditabilidade e habilita operações de desfazer

Importers MAY rejeitar exportações incrementais se base_export_id não corresponder a nenhuma exportação conhecida.


O PAM suporta Identificadores Descentralizados W3C para resolução de identidade universal entre plataformas.

O campo owner.did aceita qualquer método DID válido:

did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
did:web:example.com:user:alice
did:ion:EiAnKD8...
did:pkh:eip155:1:0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb
  1. owner.did é OPTIONAL mas RECOMMENDED para exportações compartilhadas entre sistemas
  2. Quando presente, o DID MUST ser resolvível para um DID Document conforme W3C DID Core (https://www.w3.org/TR/did-1.0/)
  3. Se signature estiver presente, signature.public_key SHOULD corresponder a um método de verificação no DID Document
  4. owner.id permanece REQUIRED mesmo quando did está presente, para compatibilidade retroativa
MethodUse CasePropriedades Principais
did:keyAutocontido, sem necessidade de resoluçãoMais simples. A chave é o identificador
did:webIdentidade hospedada por organizaçãoBaseado em DNS, fácil de configurar
did:ionDescentralizado, ancorado no BitcoinMáxima descentralização
did:pkhBaseado em carteira blockchainReutiliza chaves criptográficas existentes

Exportações PAM MAY ser assinadas criptograficamente para verificar autenticidade e detectar adulteração.

{
"signature": {
"algorithm": "Ed25519",
"public_key": "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"value": "eyJhbGciOiJFZERTQSJ9..base64url-signature",
"signed_at": "2026-02-15T22:00:01Z",
"key_id": "did:key:z6Mk...#z6Mk..."
}
}
AlgorithmTypeRecommended
Ed25519EdDSASim — rápido, chaves pequenas, resistente a ataques de canal lateral
ES256ECDSA P-256Sim — amplamente suportado
ES384ECDSA P-384Opcional
RS256RSA 2048+Compatibilidade legada
RS384RSA 3072+Compatibilidade legada
RS512RSA 4096+Compatibilidade legada

A assinatura MUST cobrir não apenas a integridade das memórias, mas também a identidade da exportação e a propriedade, para prevenir ataques de replay e falsificação de exportação.

Quando signature estiver presente (não null), os campos export_id e export_date MUST também estar presentes e não-null. Isso é imposto pelo schema via dependência condicional.

A assinatura MUST ser calculada da seguinte forma:

1. Compute integrity.checksum (Section 15)
2. Construct the signature payload object:
{
"checksum": integrity.checksum,
"export_id": export_id,
"export_date": export_date,
"owner_id": owner.id
}
3. Canonicalize the payload using RFC 8785 (JCS)
4. Sign the canonical UTF-8 bytes with the private key using the specified algorithm
5. Base64url-encode the signature (RFC 4648 §5)
6. Store in signature.value

Isso garante que alterar memories (o que muda o checksum), export_id, export_date ou owner.id invalidará a assinatura. Note que mudanças em relations, conversations_index ou outros campos de owner NÃO são cobertas pelo payload da assinatura.

1. Recompute integrity.checksum from the memories array
2. Verify computed checksum matches integrity.checksum
3. Reconstruct the signature payload object from the export
4. Canonicalize with RFC 8785
5. Decode signature.value from Base64url
6. Verify the signature against the canonical payload using signature.public_key
7. If owner.did is present, optionally resolve the DID Document and verify the key matches
  1. A assinatura é OPTIONAL mas RECOMMENDED para exportações compartilhadas entre sistemas ou usuários
  2. O payload da assinatura MUST incluir checksum, export_id, export_date e owner_id
  3. signature.signed_at MUST ser igual ou posterior a export_date
  4. Se signature.key_id estiver presente e owner.did estiver presente, key_id SHOULD ser uma URL DID referenciando um método de verificação no DID Document do proprietário
  5. Importers SHOULD verificar assinaturas quando presentes, mas MUST NOT rejeitar exportações não assinadas

O PAM fornece um registro centralizado para tipos de memória personalizados, a fim de habilitar interoperabilidade entre implementações.

O campo raiz type_registry especifica o URI do registro:

{
"type_registry": "https://portable-ai-memory.org/types/"
}

O registro é um documento JSON de acesso público que lista os tipos personalizados registrados:

{
"registry_version": "1.0",
"types": {
"security_clearance": {
"description": "Security clearance level held by the user",
"proposed_by": "my-exporter/1.0.0",
"status": "registered",
"registered_at": "2026-03-01T00:00:00Z"
},
"medical_condition": {
"description": "Known medical condition or diagnosis",
"proposed_by": "healthai/1.0.0",
"status": "registered",
"registered_at": "2026-04-15T00:00:00Z"
}
}
}
unregistered → registered → candidate → standard
StatusDescription
unregisteredTipo personalizado usado localmente, não no registro
registeredListado no registro, disponível para uso entre plataformas
candidateIndicado para promoção à taxonomia padrão
standardPromovido à taxonomia principal em uma versão futura da especificação
  1. Tipos personalizados SHOULD ser registrados no registro oficial para interoperabilidade
  2. Implementações MUST aceitar qualquer valor de custom_type independentemente do status de registro
  3. O registro é orientativo, não prescritivo — implementações MUST NOT rejeitar tipos não registrados
  4. Tipos personalizados adotados pela comunidade MAY ser promovidos à taxonomia padrão em versões futuras da especificação

20. Interoperability and Migration Compatibility Matrix

Seção intitulada “20. Interoperability and Migration Compatibility Matrix”

IMPORTANT: Os caminhos de interoperabilidade descritos nesta seção refletem formatos de exportação observados e estratégias de extração vigentes na época da publicação. Provedores de IA não suportam o PAM nativamente no momento desta especificação. Implementações SHOULD tratar esses mapeamentos como orientação de compatibilidade de melhor esforço, não como caminhos de migração garantidos ou oficialmente suportados. Os formatos de exportação dos provedores podem mudar sem aviso prévio. Importers MUST ser versionados e resilientes a variações de formato.

SourceExport MethodPAM Coverage
ChatGPTconversations.json + memory promptCompleto: conversas, memórias, preferências
ClaudeJSON export + memory prompt + memory editsCompleto: conversas, memórias, instruções
GeminiGoogle Takeout + prompt extractionParcial: conversas; memórias via prompt
CopilotPrivacy Dashboard CSVParcial: somente conversas
GrokData export (grok.com settings)Completo: conversas, projetos, publicações de mídia, assets
PerplexityForm request + promptParcial: acesso limitado a conversas
Local LLMsDirect database accessCompleto: controle total
TargetMethod
ChatGPTInstruções personalizadas, preparação de conversa
ClaudeEdições de memória, Projects, prompts de sistema
GeminiGems, preparação de conversa
Any LLMInjeção de prompt de sistema a partir das memórias PAM

Os arquivos PAM contêm informações pessoais. Implementações MUST:

  • Criptografar arquivos PAM em repouso quando armazenados localmente
  • Usar TLS para qualquer transmissão de arquivos PAM pela rede
  • Respeitar a flag access.exportable ao gerar exportações
  • Não incluir memórias marcadas com exportable: false em exportações

O content_hash usa SHA-256 para deduplicação, não para autenticação criptográfica. Para verificação à prova de adulteração, use o bloco signature (Section 18).

O campo provenance.platform_user_id é OPTIONAL especificamente para permitir exportações que preservam a privacidade. Implementações SHOULD permitir que os usuários removam identificadores de plataforma antes de compartilhar.

Quando o bloco signature estiver presente, implementações SHOULD verificá-lo antes de processar a exportação. Uma falha na verificação SHOULD resultar em um aviso ao usuário, não em uma falha silenciosa.


Novos tipos são adicionados via o mecanismo do tipo "custom" e o registro de tipos (Section 19). Se um tipo personalizado atingir ampla adoção, ele MAY ser promovido à taxonomia padrão em uma versão futura.

O bloco metadata permite additionalProperties, habilitando implementações a adicionar campos personalizados sem quebrar a validação do schema.

As versões de schema seguem versionamento semântico:

  • Patch (1.0.x): Esclarecimentos de documentação, sem mudanças no schema
  • Minor (1.x.0): Adições compatíveis com versões anteriores (novos campos opcionais, novos valores de enum)
  • Major (x.0.0): Mudanças que quebram compatibilidade e requerem migração

Uma implementação de referência está disponível para o PAM. Ela fornece:

  1. Platform extractors — Analisam exportações do ChatGPT, Claude, Gemini, Copilot e Grok para o formato PAM
  2. Validator — Ferramenta CLI para validação de schema (pam validate)
  3. Converter — Exporta memórias PAM para formatos de importação específicos de plataforma
  4. Integrity checker — Verifica checksums e regras de consistência
  5. Signature tools — Assina e verifica exportações (pam sign, pam verify)

Esta especificação foi informada por:

  • University of Stavanger PKG research — Krisztian Balog, Martin G. Skjæveland e o grupo de pesquisa de Personal Knowledge Graph
  • Solid Project — A visão de Tim Berners-Lee de armazenamentos de dados pertencentes ao usuário
  • Mem0, Zep, Letta — Implementações comerciais de camada de memória que demonstraram padrões práticos de gerenciamento de memória
  • Samsung Personal Data Engine — Implantação de grafo de conhecimento pessoal em escala de produção
  • EU Digital Markets Act — Framework regulatório que impulsiona os requisitos de portabilidade de dados
  • W3C DID Core — Padrão de identidade descentralizada que habilita a resolução de identidade entre plataformas

O PAM define um schema companheiro para armazenar dados completos de conversa referenciados por conversations_index[].storage.ref. Enquanto o schema principal do memory store contém o conhecimento extraído, o schema de conversas preserva o diálogo bruto do qual as memórias foram derivadas.

O schema de conversas serve como o formato intermediário normalizado entre as exportações específicas do provedor e o PAM memory store. O pipeline de importação é:

Raw Provider Export → Parse → Normalize → Conversation Schema → Extract Memories → PAM Memory Store

portable-ai-memory-conversation.schema.json — JSON Schema Draft 2020-12

DAG support: As conversas OpenAI usam ramificação (mapeamento com parent/children). O schema suporta parent_id e children_ids por mensagem para preservar essa estrutura. Conversas lineares (Claude, Gemini) definem parent_id: null e children_ids: [].

Role normalization: Cada provedor usa nomes de papel diferentes (human, Request, AI, ASSISTANT, nomes de modelos). O schema normaliza para: user, assistant, system, tool. Veja a seção 6 de importer-mappings.md para a tabela de mapeamento completa e verificada.

Multipart content: Mensagens podem conter texto, imagens, código e arquivos. O campo content suporta tanto texto simples (type: "text") quanto multipart (type: "multipart" com parts[]).

Import metadata: Conversas normalizadas SHOULD registrar a versão do importer, o arquivo de origem e o checksum de origem. Isso habilita depuração, re-importação e rastreamento de versão de formato. O bloco import_metadata é OPTIONAL no schema para permitir exportações leves, mas implementações SHOULD populá-lo para auditabilidade.

raw_metadata: Campos específicos do provedor que não mapeiam para o PAM são preservados verbatim em raw_metadata para round-tripping sem perda.

Veja importer-mappings.md para mapeamentos campo a campo de cada formato de provedor para o schema de conversas normalizado:

  • OpenAI (ChatGPT): conversations.json com mapeamento DAG
  • Anthropic (Claude): conversations.json com array chat_messages
  • Google (Gemini): Google Takeout MyActivity.json (array de log de atividade único)
  • Microsoft (Copilot): Privacy Dashboard CSV
  • xAI (Grok): Exportação de dados via configurações do grok.com (conversations, projects, assets)

Os formatos de exportação dos provedores mudam sem aviso prévio. Importers MUST ser versionados:

importer_version: "openai-importer/2025.01"

Quando um formato mudar, crie uma nova versão do importer mantendo a antiga para processar exportações mais antigas.


Este documento de especificação (spec.md) é licenciado sob a Creative Commons Attribution 4.0 International License ( CC BY 4.0). Você pode compartilhar e adaptar este documento para qualquer finalidade, desde que o crédito adequado seja dado.

Texto completo: https://creativecommons.org/licenses/by/4.0/

Os arquivos JSON Schema (portable-ai-memory.schema.json, portable-ai-memory-conversation.schema.json, portable-ai-memory-embeddings.schema.json) e todo o código de implementação de referência são licenciados sob a Apache License, Version 2.0.

Texto completo: https://www.apache.org/licenses/LICENSE-2.0


  • Memory store: examples/example-memory-store.json
  • Conversation: examples/example-conversation.json
  • Embeddings: examples/example-embeddings.json
  • schemas/portable-ai-memory.schema.json — Schema principal do memory store (JSON Schema Draft 2020-12)
  • schemas/portable-ai-memory-embeddings.schema.json — Schema de embeddings (JSON Schema Draft 2020-12)
  • schemas/portable-ai-memory-conversation.schema.json — Schema de conversas normalizadas (JSON Schema Draft 2020-12)
import hashlib
import unicodedata
def normalize_content(content: str) -> str:
"""Normalize content for deterministic hashing."""
text = content.strip()
text = text.lower()
text = unicodedata.normalize("NFC", text)
text = " ".join(text.split())
return text
def compute_content_hash(content: str) -> str:
"""Compute SHA-256 hash of normalized content."""
normalized = normalize_content(content)
hash_hex = hashlib.sha256(normalized.encode("utf-8")).hexdigest()
return f"sha256:{hash_hex}"
def compute_integrity_checksum(memories: list) -> str:
"""Compute deterministic checksum of memories array using RFC 8785.
IMPORTANT: This function MUST use an RFC 8785 (JCS) compliant
serializer. Standard json.dumps() is NOT sufficient because:
- json.dumps serializes 1.0 as "1.0", RFC 8785 requires "1"
- json.dumps does not guarantee RFC 8785 Unicode escaping rules
- json.dumps number formatting differs from IEEE 754/ECMAScript
Python: pip install rfc8785
Node.js: npm install canonicalize
Go: github.com/nicktrav/canonicaljson
Java: org.erdtman:java-json-canonicalization
"""
import rfc8785
sorted_memories = sorted(memories, key=lambda m: m["id"])
canonical_bytes = rfc8785.dumps(sorted_memories)
hash_hex = hashlib.sha256(canonical_bytes).hexdigest()
return f"sha256:{hash_hex}"

WARNING: Não use json.dumps(..., sort_keys=True, separators=(",", ":")) para cálculo de checksum. Ele produz saída diferente do RFC 8785 para números de ponto flutuante, o que resultará em incompatibilidades de checksum entre implementações.

from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives import serialization
import base64
import rfc8785
def build_signature_payload(export: dict) -> bytes:
"""Construct and canonicalize the signature payload per Section 18.3.
The payload MUST include checksum, export_id, export_date, and owner_id
to prevent replay attacks and export spoofing.
"""
payload = {
"checksum": export["integrity"]["checksum"],
"export_id": export["export_id"],
"export_date": export["export_date"],
"owner_id": export["owner"]["id"]
}
return rfc8785.dumps(payload)
def sign_export(export: dict, private_key: Ed25519PrivateKey) -> str:
"""Sign an export with Ed25519 over the canonical payload."""
payload_bytes = build_signature_payload(export)
signature_bytes = private_key.sign(payload_bytes)
return base64.urlsafe_b64encode(signature_bytes).decode("ascii")
def verify_export(export: dict, signature_b64: str, public_key_bytes: bytes) -> bool:
"""Verify an Ed25519 signature over the canonical payload."""
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
public_key = Ed25519PublicKey.from_public_bytes(public_key_bytes)
payload_bytes = build_signature_payload(export)
signature_bytes = base64.urlsafe_b64decode(signature_b64)
try:
public_key.verify(signature_bytes, payload_bytes)
return True
except Exception:
return False
import rfc8785
def merge_incremental(base: dict, delta: dict) -> dict:
"""Merge an incremental export into a base export."""
base_memories = {m["id"]: m for m in base["memories"]}
for mem in delta["memories"]:
base_memories[mem["id"]] = mem # insert or update
merged = list(base_memories.values())
base["memories"] = merged
base["integrity"]["total_memories"] = len(merged)
base["integrity"]["checksum"] = compute_integrity_checksum(merged)
return base

Veja importer-mappings.md para mapeamentos campo a campo completos de cada provedor para o formato PAM normalizado.