Skip to main content
Glama
Cloto-dev

CPersona

Official
by Cloto-dev

reconstruct

Read-only

Assemble coherent memory items from recall candidates by selecting, ordering, and assigning roles, using verbatim excerpts and traceable provenance.

Instructions

Assemble recall ITEMS from the candidate rows a recall produces: units of memory, each traceable to the canonical rows that support it. Reconstruction means select, order and assign roles -- never compose. No model is called and nothing is summarised: content is a verbatim excerpt of the item's head claim, cut the way the recall preview tier cuts, and expandable through head_ref via get_contents. HEAD CLAIM: the most relevant row in the item; if newer versions of that record (same message id in the same stored project) are present, their latest version. When max_evidence cuts an item, the head is kept and the most relevant remaining rows fill the rest. Stored rows are never modified. COUNT IS A CEILING, NOT A FILL TARGET AND NOT A SEARCH DEPTH: base = forced ?? requested ?? server default, effective = min(base, maximum), and 0 <= returned <= effective. Every response states effective_count and returned_count. A RESPONSE SAYS MORE ONLY WHEN THE SERVER DID SOMETHING OTHER THAN WHAT WAS ASKED: requested_count + count_policy {source, clamped, reason} when the count was clamped or operator-forced; requested_budget + budget_policy when the budget was clamped, raised or forced; effective_budget + used_budget when the budget withheld an item or an excerpt; bounds when a bound dropped rows, was reached, or was lowered by the library ceiling; reconstruction.excluded_without_provenance when rows were excluded. A response without them was served as asked. trace=true returns the full audit every time. Fewer items than the window is a NORMAL result and carries shortfall_reason (no_relevant_evidence / below_quality_threshold / exhausted_candidates); a shortfall is never padded with duplicates, fragments, or a cluster split in two. BREADTH IS SEPARATE FROM COUNT: top_k (candidate depth), max_hops (relation hops) and max_evidence are declared independently and none is derived from count -- changing count alone does not move the candidate id set. WHAT THE RESPONSE ADMITS: bounds.omitted names a bound that DROPPED rows the tool held (max_evidence -- each cut item also counts them in claims_omitted -- or max_hops: a declared relation was left unfollowed); bounds.reached names a bound that was only MET (top_k: retrieval returned as many rows as it was allowed; max_evidence: an entity the walk reached is mentioned by more records than were read -- whether more lay beyond is not known). Both are absent when empty. quote_selection: lexical_only appears when no query embedding was available and nodes were ranked by shared trigrams alone; an item whose cut quote is merely the start of its record carries node_unavailable (no_nodes, or not_current when nodes exist but are partial or another model's). ABSENCE IS NOT A VERDICT: a response without these fields does not say its items suffice to answer, that the whole store was searched, or that the rows were checked for contradiction -- conflicts detects one narrow case only. BREADTH BEFORE DEPTH: budget bounds the characters of quoted text -- each item's content and its excerpts -- where count bounds how many items. The quoted text is one fixed sequence: every head in item order, then each item's most relevant remaining excerpt, then the next, and the response is its longest prefix that fits. An excerpt the budget cannot carry is omitted (counted in excerpts_omitted, absent when zero; its claim and ref stay); an item is dropped only when its head does not fit, with shortfall_reason budget_exhausted. Raising the budget alone never removes an item or an excerpt. When budget is omitted the default is the configured default or one quote per item of the window, whichever is more, so a count you name is not cut by a budget you did not set; a budget you do name is taken as given. QUOTES: content quotes the head claim and each excerpts[] entry quotes another retained claim, most relevant first; all are verbatim and cut as the preview tier cuts. A long record with overflow-tree nodes is quoted from the node that best matches the query (rank by embedding similarity and by shared character trigrams, fused), and node gives its index, node count and character span in the stored text; a record without nodes is quoted from its start. READ FURTHER IN STEPS, SMALLEST FIRST: a node quote is the start of a node several times its length, and an item whose quote was cut carries expand -- pass it to get_contents as it is to read the rest of that node. If that is not enough, read its neighbours with {ref, node: [index - 1, index + 1]}. Pass the bare ref, the whole record, only when the parts did not answer: a record can be tens of times a node. Nodes are read after items are chosen, so they never change which items come back or their order. No relevance score is returned. ITEM SHAPE (the same for every item): claims carries one entry per retained row, newest first, each with ref, as_of, why (the key that admitted the row; relation:<predicate> when a declared relation did), hops when the relation walk reached the row, and roles when it has any -- sort by as_of for a chronological view. excerpts and excerpts_omitted are absent when empty. trace=true adds reconstruction (policy, candidate / cluster / selected counts), candidate refs, clusters and, for each record quoted by node, node_order -- its best few node indices, best first, as places to read next (an order, not a confidence). Gate fallback remains visible even when count is filled; zero count states count_zero. Retrieval degradation and update notices are delivered unchanged. If the library ceiling clamps top_k, bounds.effective_top_k reports the applied bound, including when the candidate pool is empty. independence_reason says why this is a separate item; conflicts appears only when two rows cannot be ordered. ROLE DIRECTION: roles[].role names what the REFERENCED row is to this claim (the ref is the subject, the claim is the object): the referenced episode SUPPORTS this claim, the referenced newer row SUPERSEDES it. The vocabulary is fixed at supports / supersedes / corrects / qualifies / contradicts / temporal_predecessor. The server derives supersedes (same message id, time order) and supports (episode span containment); any role word can also be DECLARED as a record -> record relation (declare_associations), whose subject is the ref. Ignore a role you do not know. BUNDLING KEYS are deterministic and never semantic: same message id within the same stored project (unknown project context cannot establish identity), containment in a candidate episode's time span, and adjacent timestamps FROM THE SAME SOURCE within the same project and channel, with the entire burst bounded by the time window (source alone is not a key -- in a single-agent store it is constant and would fold the whole pool into one item), and a declared record -> record relation between two candidates. Sharing a declared entity does not bundle. DECLARED ASSOCIATIONS (declare_associations, or associations on store) are read here and nowhere else, and change nothing when none apply: the names and aliases of entities the query mentions are added to the LEXICAL search only (the query's meaning, and so the vector search, is unchanged; the extra match is a vote, not a pass through the quality gate); and from each item's candidates the relation walk follows declared entity -> entity relations, either direction, up to max_hops, adding records that mention an entity it reached as evidence inside that item -- never as an item, never twice in one response, kept fewest hops first, then most recently declared relation, then lowest record id. This tool is additive: the recall contract is untouched.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
deepNoDeep recall for the candidate stage -- same semantics as in `recall`.
countNoCeiling on recall items returned -- not a fill target, not a search depth. Declare per call; omit to take the server default (1 unless configured). An operator-forced value overrides both. Requesting 5 with only 2 valid items returns 2; neither setting requires filling the window. Clamped to the server maximum, and the clamp is reported in count_policy rather than applied silently.
queryYesSearch query (empty returns recent memories)
top_kNoCandidate depth: how many rows the retrieval hands to bundling. This is the breadth knob; it is independent of `count` and is what to raise when items are missing evidence.
traceNoInclude candidate refs and cluster membership for local diagnosis; no full text is added.
budgetNoPayload budget: characters of quoted text (item `content` plus `excerpts`) the response may carry. Bounds depth, where `count` bounds breadth, and breadth wins: excerpts are omitted before any item is. Omit for the server default, which is never less than one quote per item of the window; an operator-forced value overrides both; clamped to the server maximum and raised to one preview-tier excerpt, and budget_policy says which.
channelNoMemory channel filter
agent_idYesAgent identifier
max_hopsNoRelation hops the walk may follow from an item's candidates through declared entity -> entity relations. 0 adds no walked evidence. A relation left unfollowed at the bound is named in bounds.omitted.
source_idNoPer-user source filter -- same semantics as in `recall`.
project_idNoγ filter -- same semantics as in `recall`, including the '@auto' sentinel, which resolves this agent's default from the server's operating context and echoes the resolution as resolved_project_id. With no configured operating context the sentinel is NOT resolved: it is filtered as the literal project_id '@auto'. Read resolved_project_id before relying on the resolution.
session_keyNoOpaque session identity you declare: a partition hint, not authentication and not a data filter. Forwarded to the candidate recall.
max_evidenceNoMaximum retained rows per item, bounding its claims and role targets. A cut is named in bounds.omitted and counted in the item's claims_omitted.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Addedv2.5.12

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description is consistent with the readOnlyHint=true annotation — "Stored rows are never modified" — so there is no contradiction, and it goes far beyond the annotation. It discloses the non-obvious traits the annotation can't: count is a ceiling not a fill target, ``0 <= returned <= effective`` with explicit effective_count/returned_count reporting, the absence-is-not-a-verdict caveat, bounds.omitted versus bounds.reached semantics, and the guarantee that no relevance score is returned. This is exceptional disclosure of behavioral nuance the annotation alone cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely long — effectively a full API specification covering policy reporting, bounds semantics, quote sequencing, role direction, bundling keys, and declared associations. It is well organized into CAPITALIZED sections and front-loads the core purpose, but it is far beyond what an agent should hold in context; much of the response-contract detail (item shape, role vocabulary, bounds semantics) belongs in an output schema or separate docs. There is also redundancy with the schema (top_k as the knob to raise for missing evidence appears in both). Density means real conciseness cost.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 13 parameters, no output schema, and a genuinely complex response contract (bounds, count/budget policies, shortfall_reason, item shape, role vocabulary, trace additions), the description carries the full burden of documenting returns — and it does so exhaustively. It specifies the item shape, the fixed role vocabulary (supports / supersedes / corrects / qualifies / contradicts / temporal_predecessor), what fields appear only under error or clamp conditions, and what trace=true adds. Nothing an agent needs to correctly call and interpret this tool is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, placing the baseline at 3, and the description adds real meaning beyond the schema: it frames count as "a ceiling, not a fill target, not a search depth," clarifies that budget bounds characters where count bounds items ("breadth wins"), and names top_k as "the breadth knob... what to raise when items are missing evidence" — the same key the schema flags. The description enriches parameter intent beyond the schema's bare minimums, justifying a 4 rather than the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states a specific verb and resource: "Assemble recall ITEMS from the candidate rows a recall produces: units of memory, each traceable to the canonical rows that support it." The core distinction is nailed precisely with "select, order and assign roles -- never compose," separating it cleanly from recall (which produces candidate rows) and from summarization tools. The tool's identity is unambiguous and differentiated from siblings like recall_with_context and get_contents.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is rich internal guidance — "READ FURTHER IN STEPS, SMALLEST FIRST" tells the agent to pass node quotes to get_contents before falling back to the bare ref, and the breadth-vs-depth discussion explains when to raise top_k versus count. However, explicit tool-selection routing among siblings is absent: the description never states when to choose reconstruct over recall or recall_with_context, and the contrast with get_contents is implied via the expand parameter rather than stated as a decision rule. The when-to-use-the-tool guidance is present but implicit in the behavioral detail.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.