- Who wrote it? — which service or API key submitted the conversation
- Where did it come from? — a source event ID and payload hash linking back to the original ingestion call
- When was it observed? — the timestamp from your system, not when MemoryOS received it
Core objects
Service Writer
A named identity for one of your backend services. Register it once; reuse it across alladd() calls from that service.
| Field | Meaning |
|---|---|
service_key | Stable slug — chat-service, crm-sync, support-bot |
display_name | Human-readable label for the dashboard |
authority_rules | Priority scores (0–100) per category for conflict resolution |
api_key_id | Optional — binds the writer to a specific API key for credential verification |
Memory Source Event
Created automatically when anadd() call includes a source block. Ties the extraction job and all resulting memories to:
- your system’s event ID
- the exact time it happened in your system (
observed_at) - a SHA-256 hash of the conversation payload
- optional evidence references and scope metadata
source_event_id pointing back to this event.
Authority Rules
When two writers produce conflicting memories for the same user,authority_rules resolve it:
observed_at recency → confidence score.
This lets you declare that crm-service always wins on fact memories while chat-service wins on preference.
Payload retention and redaction
Raw message content is retained for a configurable window (extraction_payload_retention_days). After expiry, a daily task (03:20 UTC) redacts the content from the job payload, replacing it with { "messages_redacted": true }. The payload_hash stays permanently for integrity verification.
How to use it
1. Register a Service Writer
2. Pass source on add()
| Field | Required | Notes |
|---|---|---|
service | Yes | Must match a registered service_key |
event_id | Yes | Your system’s stable event identifier |
observed_at | No | Defaults to now() |
scope | No | Arbitrary key-value metadata |
evidence | No | References to source documents |
3. Idempotency protection
Retrying with the sameevent_id returns the original job response — no duplicate extraction.
Retrying with the same event_id but different messages returns PROV_409 source_event_payload_mismatch. This protects against accidental data mutation.
Provenance in responses
Memories with a source event include aprovenance field in list and retrieve responses:
source block have provenance: null.
Managing writers
"is_active": false to deactivate. Existing source events and memories are preserved.
Auditing source events
observed_at, received_at, payload_hash, linked extraction_job_id, evidence_refs, and scope.
Error codes
| Code | HTTP | Meaning |
|---|---|---|
PROV_403 | 403 | api_key_id doesn’t match the writer’s bound key |
PROV_404 | 404 | Service writer not found |
PROV_409 | 409 | service_key already registered, or event_id exists with different payload |
PROV_422 | 422 | service not a registered writer, or invalid api_key_id |
Who needs provenance?
| Scenario | Do you need it? |
|---|---|
| Single service writing memories | No |
| Multiple services writing to the same user | Yes — use authority rules to control which wins |
| Compliance audit trail with verifiable payload hash | Yes |
| Exactly-once ingestion with retry safety | Yes |
| Automatic payload redaction after retention window | Yes |