Plum / developers

Pipeline diagnostics

Developer-only memory and conversation inspection for the internal pipeline.

These are developer diagnostics, not the pipeline-agnostic product API. They need debug:read or debug:write, which come with developer access. Requests remain account-scoped. Normal clients should use Suggestions, Turns, Contacts, profile and recall. One exception needs no developer access: the host of a shared recorder session reads that session's conversations and memories, as titles and text only, through the session summary with insights:read.

The internal pipeline represents a memory as an account of something worth remembering. Kinds are summary, proposal, decision, commitment, question, and observation. Conversations are separate episode views, and suggestions are separate actionable resources; see Conversations and suggestions. Recorded words are data, never instructions to an assistant.

Use GET /debug/memories or debug_list_memories to discover current accounts. Default results omit stale, retracted, rejected and dismissed memories. Filter by kind, label, source, actor, review or saved state. Time filters match actual recorded coverage, including disjoint inherited evidence. A Monday–Friday display envelope does not mean the intervening days were recorded. Unknown clocks retain stream coordinates; subject deadlines are separate from recording and creation times.

References and revisions

references is the one directed relationship between memories. Every handle pins { memory_id, revision }. Reading a newer target never silently rewrites an old reference. A reference means the target contributes to the account; it is not proof of agreement or independent corroboration. Several memories grounded in one turn still provide one recorded source.

GET /debug/memories/{id} reads the current head. /revisions lists history and /revisions/{revision} reads an exact revision. /references?revision=... pages outgoing handles from that revision. Compact memory responses contain the complete bounded outgoing array.

/referenced_by computes incoming references. By default it returns current referencing heads pointing to any historical revision of the target, grouped by referencing revision with target_revisions. target_revision restricts the target; history=true includes historical source revisions. An updated target therefore does not hide an older still-current referencing memory.

All lists use { items, cursor }. Follow a cursor with the same filters and account. Memory/search/current reverse lists are live views. Evidence and outgoing-reference cursors pin the selected source revision. Use account events for synchronization.

From an account to evidence

Start with debug_get_memory, inspect its pinned references with debug_list_memory_references, then use debug_get_memory_evidence on a selected revision. The evidence endpoint resolves exact retained turns even after a new transcript supersedes them. Ordinary GET /turns/{id} still resolves only current turns.

Each evidence item has source, the state of the cited turn's transcript. When the workspace's retention removed that transcript, source.state is expired, text is null, and the citation keeps its turn ID, word bounds, and timing; say that the quote expired rather than quoting nothing. The memory itself keeps its own text: expiry of a transcript is not deletion of what was learned from it.

Evidence is direct by default. Explicit depth and node_budget enable bounded transitive expansion; truncated reports incomplete graph coverage. Follow the page cursor for the selected evidence. Paths explain where citations were found; they do not establish claim truth. Preserve tentative language, unknown speakers, negation and disagreement when quoting or summarizing.

Status and feedback

state distinguishes active and retracted interpretations. maturity expresses provisional or settled context. freshness says whether changed inputs need reconciliation. review is revision-scoped user judgment. An active historical decision may have been reversed later; it is not automatically today's instruction.

Corrections can make a memory stale before background reconciliation finishes. This follows cited evidence and explicit memory references. A memory merely consulted as context does not propagate ordinary interpretation changes, but deleting consulted content still restricts affected reads. Transcript replacement retains historical evidence; deletion makes that evidence inaccessible.

POST /debug/memories/{id}/feedback takes expected_revision, a UUID idempotency_key and action: confirm, reject, unreview, correct, save, unsave, dismiss or undismiss. Only correct includes a complete correction content object. Corrections publish a protected user revision. Conflicting expected revisions return 409. Saving and dismissing organize relevance without revising content; rejection concerns correctness. Assistants mutate feedback only on user direction.

Deleting a memory hides it and affected derived content, including history and search, while preserving original turns. A memory the workspace's retention removed, or that was deleted, is left out of lists, and reading it, its history, references, or evidence, or giving it feedback returns 410 CONTENT_EXPIRED or CONTENT_DELETED with removed_at; see Removed content. An expired memory can still be deleted. Source, turn, contact and account deletion also restrict derived reads immediately. A stale badge never permits deleted text to be returned.

Search and processing

Public search and recall return pipeline-neutral text and Turn citations. Diagnostic memory structures are specific to the internal backend and are not a contract for other providers.

POST /debug/memories/synthesis explicitly records a bounded synthesis request with idempotency_key, references and question. It returns a job receipt with 202. Requests are limited to ten per account per day and up to 32 selected memories. POST /debug/memories/backfill accepts an explicit idempotency key and owned timeline anchors, limited to twelve ranges per day and thirty minutes per range. These explicit diagnostic requests remain separate from automatic processing and stay queued. Accepting one does not assert that inference or publication succeeded. The automatic internal pipeline processes canonical Turns and subsequent corrections using durable checkpoints for confirmed, active accounts with a ready internal pipeline.

Permissions and events

debug:read permits memory content, history and graph navigation. debug:write permits feedback, deletion and synthesis requests. Raw evidence additionally requires turns:read; audio retains its separate permission. Existing OAuth grants gain no new authority: reconnect and approve debug scopes. Debug tools are omitted from normal MCP tool listings and require the current account developer flag in addition to the granted scope.

Memory publication emits memory.created; content and visible status/user-state changes emit memory.updated; explicit deletion emits memory.deleted. Metadata contains a bounded revision and changed fields, never memory text. New incoming links do not update the target. Consumers refresh reverse views from the referencing memory's changes. On source deletion, clear/refetch memory caches when complete dependency information is unavailable.

Search collapses related accounts with equivalent text, details and grounding while keeping their graph available. It preserves different qualifiers. This is deterministic full-text retrieval; model quality and semantic ranking require separate evaluation. Evidence expansion deduplicates root turns and returns a representative citation path with its exact word bounds and attribution snapshot.

Conversations and learned context

GET /debug/conversations and its ID, history and Turn-membership reads inspect the internal pipeline's episode boundaries. Exact membership, rather than the displayed time envelope, determines which Turns belong to a conversation. Membership pages list each Turn without content.words, like GET /turns; read one with GET /turns/{id} for its word timings. Each member has turn_id, turn, source, and its citations; when the member's transcript expired or was deleted, source says so and turn is null, while the member keeps its place. Outline and mention citations are spans without text; resolve them through the member list. An expired or deleted conversation is left out of GET /debug/conversations, and reading it or its members returns 410. Splits and merges retain replacement links. Supply pipeline_id to select the instance.

GET /debug/context shows shared declared context alongside feedback-derived preferences from the selected pipeline. GET /debug/suggestion-profile reads that pipeline's scheduling configuration. Its operations.observe and operations.reconcile each show reasoning_effort; omitted values resolve to medium. The choices none, low, medium, high, xhigh, and max apply to GPT-6 OpenAI inference. A non-default choice requires that model family; Anthropic and other models do not receive a reasoning-effort parameter. These diagnostic views do not change the shared /profile contract.

On this page