Skip to Content
FeaturesValue bindings

Typed presentation and lookup values

Agents often need two exact forms of the same value. A confirmed memory may need to preserve Salt Lake City(Utah) in a user-facing answer while a search tool accepts only Salt Lake City. A prose instruction cannot reliably keep those roles separate across tool calls. PRME therefore supports opt-in typed value bindings on direct stores.

from prme import MemoryClient, MemoryValueBinding with MemoryClient("./memory") as memory: memory.store( '{"plan":"Current City: Salt Lake City(Utah)"}', retrieval_content="Confirmed plan\nCurrent City: Salt Lake City(Utah)", value_bindings=[ MemoryValueBinding( reference="current-city-1", kind="city", presentation="Salt Lake City(Utah)", lookup="Salt Lake City", ) ], user_id="alice", ) response = memory.retrieve("Which city?", user_id="alice") print(response.bundle.render_value_bindings()) resolution = response.bundle.resolve_tool_arguments( {"city": "Salt Lake City(Utah)"} ) assert resolution.arguments == {"city": "Salt Lake City"} assert resolution.binding_uses[0].operation == "replaced"

presentation is the exact source-backed form intended for output. lookup is caller-supplied operational data for a tool or database. kind and reference are application-defined stable labels. PRME does not infer the mapping.

Admission requires every presentation value to occur byte-for-byte in both the immutable source and the text indexed for retrieval. The bindings are copied into the event and direct node metadata before storage work begins, so restart recovery retains the same values. The reserved metadata key is prme_value_bindings_v1; pass value_bindings instead of writing that key directly.

Only bindings whose presentation value survived context packing are exposed by bundle.value_bindings(). A reference-only or key/value memory cannot silently influence a tool call. resolve_tool_arguments() copies a finite JSON argument object and replaces only complete string values that exactly equal a visible presentation form. It never performs substring, fuzzy, case-folded, or model- generated rewriting. The result lists JSON-pointer paths, source node IDs and binding references for every substitution. binding_uses also identifies an argument that already equals an unambiguous visible lookup form, using the already_lookup operation without changing it. This lets a tool adapter carry the source-backed presentation form into result rendering without exposing all lookup values in model context. Ambiguous reverse lookup forms are omitted, and conflicting presentation mappings fail instead of choosing one.

The HTTP POST /v1/store body and MCP memory_store accept the same value_bindings array. HTTP retrieval returns visible bindings in the top-level value_bindings field. MCP memory_retrieve(include_context=true) returns them beside the exact packed context. Cross-language clients can apply the same exact complete-value rule. Python callers can use the audited resolver directly.

Bindings do not rewrite generated answers, validate a tool’s schema, prove that the lookup form is correct, or turn caller metadata into a factual claim. They provide an explicit execution boundary with source provenance. Applications should still validate the resolved arguments against the target tool schema and retain the returned replacement and binding-use audit when the action matters. Unmatched strings remain unchanged because PRME cannot infer which fields a particular tool requires to be bound. A fail-closed integration should reject or return a retryable error for any schema field whose application-defined presentation form remains after resolution; it must not send that value to the underlying tool. If an application adds presentation guidance to a tool result, it should use only the binding_uses from that exact call and keep the annotation separate from the tool’s data.


Source: docs/VALUE-BINDINGS.md  in PRME at 58caddb1.