@osyra/ome/adapters/langchain
Pre-release — offline verification only: Offline verification from an authorized source checkout is usable. The memory/network RPC surface and any
api.osyra.aiexamples below describe protocol/interface shape only. The public Edge bridge, package publication, and release acceptance are still pending; do not treat this page as proof that customer network read/write is available.
Import: import { … } from "@osyra/ome/adapters/langchain";
Classes
OmeChatMessageHistory
class OmeChatMessageHistoryLangChain.js BaseListChatMessageHistory subclass backed by OME.
The class is constructed lazily — the LangChain.js core base class is
resolved at runtime via loadLangChainCore() so that import of
@osyra/ome/adapters/langchain does not eagerly throw when LangChain
is not installed (it's a peerDep). Customers who do not use the
adapter pay no penalty.
constructor(config: OmeChatMessageHistoryConfig): OmeChatMessageHistory
Properties
| Name | Type | Description |
| --- | --- | --- |
| readonly lcNamespace | string[] | LangChain namespace token (per Serializable convention). |
Methods
addAIChatMessage(message: string): Promise<void>Deprecated: Use addAIMessage instead (LangChain.js v0.3 deprecation).
addAIMessage(message: string): Promise<void>Convenience: add an AI message.
addMessage(message: BaseMessage): Promise<void>Add a single message.
addMessages(messages: BaseMessage[]): Promise<void>Add multiple messages in one batch. Implementations should override
the default loop-of-addMessage per LangChain.js convention to
minimize transport round-trips. Adapter pre-serializes all messages
up-front, then awaits each write sequentially (preserving insertion
order — OME claims carry a per-instance monotonic timestamp).
addUserMessage(message: string): Promise<void>Convenience: add a human message.
clear(): Promise<void>Clear all messages for this session.
Compliance note: OME is append-only — clear() does NOT delete
the underlying claims; it writes a TombstoneClaim per claim that
marks them as logically cleared. Auditors can still see that the
messages existed (and were cleared by whom + when) via the full
claim chain. This is the GDPR Art-17 "right to be forgotten" pattern
per ADR-049.
memory.tombstone has an RPC implementation (ENG-2570 / ENG-2585), so
clear() delegates
to the store's listClaimIdsForSession to acquire the IDs, then
tombstones each via client.memory.tombstone (fail-fast on the first
error, auditing the count actually erased — see below).
getMessages(): Promise<BaseMessage[]>Return all messages currently stored for sessionId in chronological
order. Optionally re-verifies each claim's signature.
toLangChain(): Promise<BaseListChatMessageHistory>Return a real LangChain.js BaseListChatMessageHistory instance
that delegates to this adapter. Useful when downstream code requires
a true instanceof BaseListChatMessageHistory check.
This is the LangChain.js "extends a class loaded at runtime" pattern — adapter constructors cannot extend a peer-dep class at file scope because the peer-dep may not be installed at import time.
OmeMemory
class OmeMemoryLangChain BaseMemory subclass backed by OME.
constructor(config: OmeMemoryConfig): OmeMemory
Properties
| Name | Type | Description |
| --- | --- | --- |
| history (get) | OmeChatMessageHistory | Direct accessor to the underlying chat history (escape hatch). |
| memoryKeys (get) | string[] | Memory key registered with LangChain chains. |
Methods
clear(): Promise<void>Clear the underlying chat history. Delegates to
OmeChatMessageHistory.clear() — see compliance notes there.
loadMemoryVariables(_values: Record<string, unknown>): Promise<Record<string, unknown>>Load the chat-history payload as a LangChain memory variable.
Per the BaseMemory contract, returns { [memoryKey]: <buffer> }
where <buffer> is either a string (default) or BaseMessage[]
(if returnMessages = true).
saveContext(inputValues: Record<string, unknown>, outputValues: Record<string, unknown>): Promise<void>Append the (input, output) pair to the underlying chat history.
Input becomes a HumanMessage; output becomes an AIMessage. If
the chain dictionary lacks the configured input/output keys, the
adapter raises OmeWorkspaceError rather than silently skipping
— silent skip would be a correctness bug.
toLangChain(): Promise<BaseMemory>Return a real LangChain.js BaseMemory instance that delegates to
this adapter. Useful when downstream code requires a true
instanceof BaseMemory check.
Class is constructed lazily at first call (peer-dep loaded at runtime; see chatHistory.ts toLangChain for the same pattern).
OmeVectorStore
class OmeVectorStoreLangChain.js VectorStore subclass backed by OME.
constructor(config: OmeVectorStoreConfig): OmeVectorStore
Properties
| Name | Type | Description |
| --- | --- | --- |
| readonly lcNamespace | string[] | |
| embeddings (get) | EmbeddingsInterface | Direct accessor to the embeddings provider. |
Methods
_vectorstoreType(): stringVector-store type tag — required by LangChain's serialization machinery.
addDocuments(documents: DocumentInterface<Record<string, any>>[]): Promise<string[]>Embed each document via the configured embeddings provider, then
call addVectors. Matches LangChain.js's VectorStore.addDocuments
contract.
addVectors(vectors: number[][], documents: DocumentInterface<Record<string, any>>[]): Promise<string[]>Add precomputed embeddings + documents. Matches LangChain.js's
VectorStore.addVectors contract.
delete(params?: { ids?: string[] }): Promise<void>Delete documents by ID. Per the OME append-only contract this is a tombstone, not physical deletion (ADR-049). Customers who need physical deletion must wait for the workspace-purge surface (V1.5+).
similaritySearch(query: string, k?: number): Promise<DocumentInterface<Record<string, any>>[]>Text-input similarity search — embeds the query and delegates to
similaritySearchVectorWithScore.
similaritySearchVectorWithScore(query: number[], k: number): Promise<[DocumentInterface<Record<string, any>>, number][]>Similarity search via cosine similarity. Returns top-k documents with their cosine-similarity scores.
v0.1 limitation — IN-PROCESS index ONLY (F048): this scans only
the documents THIS adapter instance wrote (_localIndex). When the
adapter is backed by a real client.memory.* store (no injected
fixture), that index is merely a write-side cache — it CANNOT see
documents written by other instances/processes. Returning a
truncated top-k as if it were the global result would be a silent
correctness bug. So against a real client store the adapter REFUSES
to search unless the caller opted in via
allowInProcessIndex: true. Server-side k-NN is a v1.5+ surface.
similaritySearchWithScore(query: string, k?: number): Promise<[DocumentInterface<Record<string, any>>, number][]>Text-input similarity search WITH scores.
toLangChain(): Promise<VectorStore>Return a real LangChain.js VectorStore instance that delegates to
this adapter.
Interfaces
OmeChatMessageHistoryConfig
interface OmeChatMessageHistoryConfigConstructor options for OmeChatMessageHistory.
Properties
| Name | Type | Description |
| --- | --- | --- |
| client | OmeClient | The OME client. Construction is the caller's responsibility — the adapter does NOT own the client lifecycle. Customers must close the client (or use await using) when done. |
| sessionId | string | Stable session ID. Used to scope chat history within a workspace. Strongly recommend a uuidv7 — but the adapter does not enforce format. Cross-session reads are NOT supported (one history per sessionId). |
| store? | OmeStoreLike | Optional escape hatch for tests: an in-memory store that satisfies the OmeStoreLike interface. When provided, the adapter routes all reads/writes through this store instead of client.memory.*. This exists so unit tests can run without a live OME service AND so customers can implement bring-your-own persistence for migration scenarios. client.memory.writeClaim / getClaim have RPC implementations, so this argument is OPTIONAL at the type level. Production use without an injected store still depends on the pending public Edge bridge. Supply an OmeStoreLike only for tests (no live OME service) or bring-your-own persistence / migration scenarios. |
| trustedSignerKey? | Uint8Array<ArrayBufferLike> | Caller-anchored 32-byte Ed25519 public key used as the trust anchor for verifyOnRead. REQUIRED when verifyOnRead is true (the default). Why required? The verify API was re-modeled (ENG-2413): a receipt is never "verified" against its own in-band signerPub (self-signed + self-attested keys are forgeable). The relying party must pin the signer's public key (or resolve it out-of-band) and pass it here. DID-resolver-based trust anchoring is a v0.2 surface; until then a pinned key is the only supported anchor. Supplying this key with verifyOnRead: false is allowed (the key is simply unused). |
| verifyOnRead? | boolean | If true, every getMessages() re-verifies every claim's Ed25519 signature locally via client.verify.receipt(). Defaults to true per PM-BRIEF §3.2 defense-in-depth posture. Set to false ONLY if your application has separately verified the workspace's completeness witness and trusts the transport layer (rare; not recommended). H7 (F033): when verifyOnRead is true, an explicit trustedSignerKey MUST be configured — the in-band SignedClaim.signerPub is NOT a trust anchor (client.verify.receipt throws without a caller-supplied key). If verifyOnRead === true and no trusted key is configured, the constructor THROWS rather than silently emptying every message on read. |
OmeMemoryConfig
interface OmeMemoryConfigConstructor options for OmeMemory.
Properties
| Name | Type | Description |
| --- | --- | --- |
| aiPrefix? | string | AI-side prefix used when formatting the buffer string. Default "AI" — matches LangChain ConversationBufferMemory. |
| client | OmeClient | Underlying chat-history config. See OmeChatMessageHistory. |
| humanPrefix? | string | Human-side prefix used when formatting the buffer string. Default "Human" — matches LangChain ConversationBufferMemory. |
| inputKey? | string | Variable name carrying the new user input on saveContext. Defaults to "input" (matches ConversationChain convention). |
| memoryKey? | string | Variable name surfaced to LangChain chains as the chat-history payload. Defaults to "history" (matches ConversationBufferMemory). |
| outputKey? | string | Variable name carrying the chain's AI output on saveContext. Defaults to "output" (matches ConversationChain convention). |
| returnMessages? | boolean | If true, loadMemoryVariables returns a BaseMessage[]. If false (default), returns a buffer-formatted string. |
| sessionId | string | Session ID — scopes memory within a workspace. |
| store? | OmeStoreLike | Optional escape hatch for tests / migration; see OmeChatMessageHistoryConfig.store. |
| trustedSignerKey? | Uint8Array<ArrayBufferLike> | Caller-pinned 32-byte Ed25519 trust anchor for verifyOnRead. REQUIRED when verifyOnRead is true (the default) — forwarded to the underlying OmeChatMessageHistory (H7). See OmeChatMessageHistoryConfig.trustedSignerKey. |
| verifyOnRead? | boolean | Whether the chat history should re-verify each claim's Ed25519 signature on every read. Default true. See OmeChatMessageHistoryConfig.verifyOnRead. |
OmeStoreLike
interface OmeStoreLikeMinimal store interface for adapter persistence. Decouples the adapter
from client.memory.* transport status — see config store argument.
This is the same shape as OmeClient.memory.writeClaim / getClaim
plus a listClaims(sessionId) enumeration helper. The enumeration
lives here rather than on the full client surface because chat-history
replay is an adapter-specific pattern (workspaces hold MANY chat
histories; we filter by sessionId).
Methods
getClaim(claimId: string): Promise<SignedClaim>Retrieve a signed claim by ID.
getClaimMetadata(claimId: string): Promise<Record<string, string> | undefined>Retrieve the adapter metadata payload associated with a claim.
Current limitation: until the server-side metadata RPC lands in a
later release, the production store cannot return metadata stashed
at write-time. Customers must inject an in-memory store fixture;
that store's writeClaim captures metadata, and this method
returns it.
Returns undefined if no metadata is available for this claim
— production paths will see this until the metadata RPC lands.
listClaimIdsForSession(workspaceId: string, sessionId: string): Promise<string[]>Enumerate all claim IDs for a given session. Adapter-specific because the canonical OME workspace API is uuidv7-keyed, not session-keyed.
writeClaim(claim: Claim, metadata?: Record<string, string>): Promise<string>Write a single claim; returns the assigned claim ID (uuidv7).
F049 metadata-persistence contract (alpha.2): the metadata
map (carrying sessionId / collectionId / payload etc.) MUST be
persisted alongside the claim and round-tripped by
getClaimMetadata. Replay (chat-history / vector-store reads)
is unimplementable without it: the canonical message/document
payload is stashed under metadata.payload, and session/collection
scoping uses metadata.sessionId / metadata.collectionId.
The default client.memory.* store does NOT yet accept a metadata
arg on the wire (the server-side metadata RPC is alpha.2). Until it
lands, the default store's writeClaim DROPS this argument and
getClaimMetadata returns undefined — so replay against the
default store is a documented no-op (see buildClientStore).
Customers needing replay today inject an OmeStoreLike fixture that
captures the metadata.
OmeVectorStoreConfig
interface OmeVectorStoreConfigConstructor options for OmeVectorStore.
Properties
| Name | Type | Description |
| --- | --- | --- |
| allowInProcessIndex? | boolean | F048: opt-in acknowledgement that this store runs an IN-PROCESS similarity index ONLY. When the adapter is backed by a real client.memory.* store (not an injected fixture), similarity search scans only documents this instance wrote — it CANNOT see documents written by other instances/processes, so results would be silently PARTIAL. By default the adapter refuses to run similarity search against a real client store (throws). Set this to true to explicitly accept the in-process-only semantics (e.g. a single long-lived process that owns the whole corpus, or small-corpus dev). Has no effect when an OmeStoreLike fixture is injected (the fixture IS the authoritative index in that mode). |
| client | OmeClient | OME client (caller-owned lifecycle). |
| collectionId? | string | Optional collection ID. Used to scope vector store within a workspace (the same workspace can hold multiple collections, like multiple RAG indices). Defaults to "default". |
| embeddings | EmbeddingsInterface | LangChain.js embeddings provider (any subclass of Embeddings). |
| localIndexSoftCap? | number | F048: soft cap on the in-process index size. When the local index exceeds this many documents, addVectors emits a warning audit event (unbounded local growth is a memory-leak + a sign the corpus has outgrown in-process search). Default 10_000 (matches the documented "fine for small corpora (<10k docs)" guidance). |
| store? | OmeStoreLike | Optional escape hatch (matches OmeChatMessageHistoryConfig.store). client.memory.writeClaim / getClaim implement their RPCs (ENG-2585), so this is optional at the type level. Production use without an injected store still depends on the pending public Edge bridge. |
| trustedSignerKey? | Uint8Array<ArrayBufferLike> | Caller-anchored 32-byte Ed25519 public key — the trust anchor for verifyOnRead. REQUIRED when verifyOnRead is true. See OmeChatMessageHistoryConfig.trustedSignerKey for the rationale (self-signed in-band keys are forgeable; DID resolution is v0.2). |
| verifyOnRead? | boolean | If true, every read re-verifies the stored claim's Ed25519 signature via client.verify.receipt(). Defaults to true per PM-BRIEF §3.2. H7 (F033): requires trustedSignerKey when true (the default). The in-band SignedClaim.signerPub is NOT a trust anchor; without a caller key the constructor THROWS rather than silently dropping every candidate document on search. |
OmeVectorStoreDocument
interface OmeVectorStoreDocumentDocument storage record returned by addDocuments / passed to
addVectors. Exposed publicly so customers can introspect.
Properties
| Name | Type | Description |
| --- | --- | --- |
| id | string | OME-assigned claim ID (uuidv7). |
| metadata | Record<string, unknown> | Stored metadata (arbitrary JSON). |
| pageContent | string | Document text content. |
Variables
ADAPTER_INFO
const ADAPTER_INFO: { adapterVersion: "0.1.0"; auditTag: "langchain"; framework: "langchain"; minFrameworkVersion: "0.3.0" }Adapter version + framework support window. Surface this to consumers so they can sanity-check at runtime that their LangChain.js version lines up with what the adapter was tested against.
Symmetric with the Python sibling's osyra_ome.adapters.langchain.__version_compat__
once AP00013's adapter lands (cross-language parity per ADR-045).