opentelemetry-instrumentation-memorysync
OpenTelemetry instrumentation for the MemorySync Python SDK — memory, conversation-history and framework-state operations become first-class spans in AgentOps, Respan, and any other OpenTelemetry backend.
The first SDK-level tracing instrumentor shipped by any memory vendor.
pip install opentelemetry-instrumentation-memorysync
With AgentOps
agentops.init() registers AgentOps as the global OpenTelemetry tracer
provider, so MemorySync spans land in your AgentOps traces automatically:
import agentops
from opentelemetry.instrumentation.memorysync import instrument_memorysync
from memorysync import MemorySyncClient
agentops.init() # before or after instrument_memorysync() — both work
instrument_memorysync()
client = MemorySyncClient(api_key="ms_...", base_url="https://api.memorysync.io")
client.add("Prefers window seats", source="chat") # → span: memorysync.add
client.query("seating preferences", k=5) # → span: memorysync.query
With Respan (formerly Keywords AI)
Route your LLM calls through the Respan gateway and instrument MemorySync — every step of the loop is a first-class span:
from openai import OpenAI
from opentelemetry.instrumentation.memorysync import instrument_memorysync
instrument_memorysync()
llm = OpenAI(api_key=RESPAN_API_KEY, base_url="https://api.respan.ai/api/")
context = ms.recall(tenant_id=t, user_id=u, prompt=question, k=6) # span 1
reply = llm.chat.completions.create(...) # gateway-traced
ms.add_turn(tenant_id=t, user_id=u, text=question, role="user") # span 2
add_turn sends the user's turn to fact extraction: only the durable facts
it contains are stored, as memories, so the span reports the extraction
receipt (processing_status, request_id) rather than a memory id.
Assistant replies are not stored as memories, so the reply is not sent.
With plain OpenTelemetry / auto-instrumentation
The package registers the standard opentelemetry_instrumentor entry
point, so the OTel CLI picks it up with zero code changes:
opentelemetry-instrument python app.py
What gets traced
memorysync.{operation} CLIENT spans for both MemorySyncClient and
AsyncMemorySyncClient (full sync/async parity):
- Memories:
add,add_turn,bulk_add,query,retrieve,recall,search_routed,get,update,forget,summarize,history,feedback,list_memories. - Conversation history:
append_history,list_history,delete_history. - Framework state:
put_state,get_state,list_state,search_state,delete_state,list_state_namespaces.
The history and state methods exist in memorysync 1.10.0 and later; with
an older SDK installed, the memory operations are traced as usual.
Attributes always include the operation, sync/async client kind,
server address, project/tenant/user identifiers, result counts, score
min/max/avg, idempotency signals (already_exists on add_turn,
created / created_count on state and history writes), and error
type + HTTP status on failure. A memorysync.client.operation.duration
histogram is recorded per call.
add_turn sends one turn to fact extraction and does not store the turn
itself, so its span describes the extraction:
| Attribute | Value |
|---|---|
memorysync.role |
the role argument, when one is passed |
memorysync.processing_status |
distilling, skipped_non_user_turn, skipped_low_value, skipped_replay, or skipped (over the plan limit) |
memorysync.request_id |
the extraction job; absent when none was started |
memorysync.already_exists |
true when the server recognised a retry of the same turn |
memorysync.memory_id |
set only when a response carries one; add_turn answers null |
History and state spans record tenant_id, user_id and source, plus
(all names prefixed memorysync.):
| Span | Request | Response |
|---|---|---|
append_history |
session_id, turns_count, extract |
status, results_count, created_count, request_ids_count |
list_history |
session_id, limit |
results_count |
delete_history |
selector (session / ids), session_id, ids_count, delete_derived_facts |
deleted_count, deleted_facts_count |
put_state |
namespace, key, index, extract, replace_derived_facts |
status, created, request_id, deleted_facts_count |
get_state |
namespace, key |
results_count (0 or 1) |
list_state |
namespace_prefix, limit, offset |
results_count |
search_state |
namespace_prefix, limit |
results_count, score.min / score.max / score.avg |
delete_state |
namespace, selector (keys / namespace), keys_count, delete_derived_facts |
deleted_count, deleted_facts_count |
list_state_namespaces |
namespace_prefix, max_depth, limit, offset |
results_count |
Namespaces are recorded as string arrays. Flags (extract, index,
replace_derived_facts, delete_derived_facts) are recorded when passed
explicitly. status is skipped when the organization is over its plan
limit and nothing was stored.
Privacy: content capture is OFF by default
Memory content is customer data. By default no memory text, query text, recalled context, transcript turn, or state value is recorded — only counts, identifiers (tenant, user, session, namespace, key), scores, and latencies. Opt in explicitly:
instrument_memorysync(capture_content=True)
# or: MEMORYSYNC_OTEL_CAPTURE_CONTENT=true
Even opted in, input is truncated to 500 characters and at most 5
result texts of 200 characters each are recorded. For history and state
spans the input is the appended turns' text, the put_state text (the
value's JSON when no text is given) or the search_state query; the
results are the listed turns' text and the state items' searchable text.
Engineering guarantees
- Instrumentation can never break the app. Attribute extraction is
fully guarded and never consumes an argument (a generator passed as
ids,keysorturnsreaches the SDK intact); return values and exceptions pass through untouched; spans are always ended. - Zero stdout pollution — the instrumentation never prints (the test suite asserts stdout stays empty during instrumented calls).
- Idempotent —
instrument_memorysync()twice is safe;uninstrument_memorysync()restores the original methods. - Order independent — OTel's proxy tracer late-binds, so instrumenting before your platform initializes still works.
- Zero changes to the
memorysyncpackage — methods are wrapped at runtime; nothing in the SDK itself is modified on disk.
Docs
- AgentOps guide: https://docs.memorysync.io/guides/agentops
- Respan guide: https://docs.memorysync.io/guides/respan
Metadata
Release files for opentelemetry-instrumentation-memorysync 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| opentelemetry_instrumentation_memorysync-1.1.0.tar.gz | 11.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| opentelemetry_instrumentation_memorysync-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.2 kB
Release files / opentelemetry_instrumentation_memorysync-1.1.0.tar.gz
| Download URL | opentelemetry_instrumentation_memorysync-1.1.0.tar.gz |
|---|---|
| Size | 11.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5bf17899824dcb480cdb3cbd6484b5827205b98fbdd9189ab534bc168292cacb
|
|
BLAKE2b-256 checksum How to use checksums |
26b7ebece5bd5597e979dbe98adbb90ec56d605090057b1d3ac4787bbe1adc62
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.5
|
Release files / opentelemetry_instrumentation_memorysync-1.1.0-py3-none-any.whl
| Download URL | opentelemetry_instrumentation_memorysync-1.1.0-py3-none-any.whl |
|---|---|
| Size | 12.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3e38b4944a49d30d7b18e82eb2526267539edde474f6c13a2f304a32f1a89133
|
|
BLAKE2b-256 checksum How to use checksums |
a68187f2022c32f111337a8a5265f049654ffa889ec0e3a38605bd7006964da1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.5
|
Security for opentelemetry-instrumentation-memorysync 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.