Portable Context
An adapter can capture readable conversation records and read shared memory through Link's authenticated storage bridge, whichever carries its connections. Its native sessions, context policy and resume mappings remain its own.
Storage binding
A harness keeping Link's collections receives Settings.storage when
its restricted folder layout supports the bridge. Its native sessions
and the state exchanged over ASP remain the harness's own.
The binding
Link hands configure the resolved storage and this start's binding
secret in endpoint_key. Keep that secret in private configuration,
never Launch.env or a command line. Use the supplied agent ID and
owner to build a Binding.
Read and write collections
Use the existing store::Request/Reply through Bridged. Link selects
the driver for each request's collection, installing the driver when
needed.
The file place
For the file place it runs lnk-file-store rooted at the protected
agent folder, with the agent's ID, outside the sandbox. It gives the
harness no unrestricted mount of Agent/.
What the bridge checks
The bridge checks the proven agent and owner against the request,
validates collection paths and uses the existing no-follow file driver.
File versions are opaque u64 CAS tokens: compare them for equality
only. Conversation sequence conflicts, leases and file CAS keep their
existing meanings.
Grants
Instruction and skill writes follow the agent's grants. A writable
Home, or its memory/ documents, grants no write to the protected
memory index. The existing notes grant also permits portable documents
under memory/portable/. Memory's separate socket retains its index
write scope. Source metadata never expands grants.
Notes
Notes at memory/notes.md retain the agent spec's size limit and
require versioned FileWrite, so an unbounded append cannot bypass
that limit.
Capture exposed records
store::context::Event is an owned view of the common fields, with
seq, typed role, text, at, optional from and optional
source.
Roles and defaults
Roles are user, assistant, tool and summary. Missing legacy
text/time fields default to empty strings, while from and source
default to none. Unsupported native record types can remain in the raw
log without becoming a portable role.
Source correlation
New native captures include stable source correlation, with adapter,
native session and native record. Correlation is scoped to the Link
agent and thread. Neither a transcript role nor a source label
establishes who may act.
The archive
Preserve original JSON and unknown extensions. Read the raw log as the archive, and avoid writing the smaller event view over it. The owner-facing chat copy omits tools, summaries and unfinished turns, so it is unsuitable as an archive. Unexposed reasoning does not become readable context.
context::append
context::append assigns the next existing sequence and detects a
repeated source. After an uncertain append response, retry the same
immutable record with the same source: it finds the original sequence.
Reusing a source with different content is an error. The caller
persists native record IDs before trying a capture and retains
uncertain work for retry.
The capture queue
The optional native-hook client syncs each admitted capture batch into
.lnk/agent-context/captures/ before contacting storage. It replays pending
batches in order before another capture or context preparation, using
the same source correlation after a lost acknowledgement. Completed
batches are removed only after every record is confirmed. A private
lock serializes native-hook clients.
The queue's limits
The queue holds at most 1,024 batches and 64 MiB, with at most 16 MiB per batch. A full queue drains when storage recovers. Corrupt, incomplete, foreign or unsupported queue entries retain their originals and refuse context preparation.
What the queue covers
It covers records admitted by the client, not uncaptured native history or a host switch/export barrier. Native hooks can report a failure and continue.
Keep versioned memory
Portable documents are JSON files at memory/portable/<id>.json, using
existing FileRead/FileWrite.
context::Memory
context::Memory holds id, text, optional source, evidence as
Link thread/sequence references, and modified_at. Unknown metadata is
preserved. The store's opaque version is the revision, separate from
the document. It is neither a timestamp nor an ordered counter.
Deletion
An optional deleted flag defaults to false. A deletion keeps the
document ID, source and evidence at a new CAS version, with empty text
and deleted: true. It stays visible to context consumers as a sourced
deletion. Removing the portable JSON file itself remains a separate
storage operation.
Native exports against a deletion
Old native exports cannot overwrite a deletion when their last successful export is unchanged. A changed native file conflicts with an intervening shared deletion until reconciled.
Each adapter's exports
The optional native-hook client keeps each adapter's exports under its own IDs. It retains native originals, records the last successful export's digest and version in the adapter's state, preserves shared corrections when the native file is unchanged, and refuses divergent edits. It supplies other adapters' documents as sourced data without overwriting a vendor's memory files.
Read a finite context
context::read reads Last = N, then the raw log through N and the
requested memory versions.
Snapshot and Cursor
Its Snapshot retains original events and a Cursor holding the Link
thread, through_seq and referenced memory-file versions. Version zero
means that a referenced file was missing. Cursor::current detects
changed or deleted referenced files and later conversation activity.
A finite boundary
This is a finite boundary, not a transaction across resources or a claim of model consumption.
On return
Keep the native session mapping and last supplied cursor in the adapter's home. On return, reconcile intervening records and memory versions before selecting context. A new native session can be seeded from the same inputs. Never replay tool effects merely because their records appear in historical context.
Keep host session and approval metadata
link_harness_contract::harness::authority supplies host-only session
and approval types. Its Ledger is an explicit local primitive.
Existing adapters, commands and tool proxies do not activate it or
advertise an authority profile.
Sessions
The host associates a validated link:<name> conversation with a
permanent session ID. It reuses store::Agent and the current
bridge::Binding/Keyring, and requires an immutable agent ID. Other
thread formats and pre-ID agents are refused by this primitive; their
existing behavior is unchanged. No history or memory is copied into the
ledger.
Its fields
The adapter's opaque binding reference, host turn-attempt ID and host execution generation are distinct fields. Native graph IDs and callback handles remain adapter data.
authority.json
The host chooses a protected directory outside every runtime mount.
Versioned authority.json holds session mappings, one active attempt
and owner requests. It holds only a fingerprint of the current start
secret. Agent collection storage cannot read or write this directory.
How it's kept
The directory is private, its files are private regular files, and reads refuse links. A directory lock serializes changes. Writes sync the new file, rename it atomically and sync the directory before returning. Metadata is limited to 1 MiB; full, corrupt, foreign or unknown-version metadata is refused.
Requests to the owner
One attempt can propose one tool call. Repeated delivery returns its
original request, retaining its status. The host authenticates the
owner before calling respond; native metadata cannot authenticate a
response. A request starts pending and accepts allow_once or deny.
Its approved tool and arguments are immutable.
consume
consume checks the current binding and attempt, requires a fresh
host-policy check and durably claims the call once before returning it.
Approval creates no grant. A lost claim response leaves an uncertain
outcome and cannot trigger automatic effect replay.
retire and recover
After containing the old execution, the host calls retire or the
explicit restart barrier recover. Unresolved requests remain
inspectable with recovery_required; an unanswered request remains
pending and can be denied. This primitive offers no native callback
rebind. Retrying admission after a lost acknowledgement returns the
committed attempt and generation.
Its schema
These types derive JSON Schema from the same Serde definition with the
existing schema feature. They describe host metadata, not a native
lifecycle protocol.
What it fences
The ledger fences its own operations; it neither stops a native process nor replaces store leases, confinement or the tool proxy's invocation context.
Over ACP
A session's lifecycle, cancels and requests to the owner are ACP's, the Agent Client Protocol's, which every harness speaks (Interface).