Shelvia
RecipeAvailable

Recipe, Agent proposes a memory candidate

This is the pattern under every recipe. Shelvia is the memory layer the agent runtime calls, not the agent runtime itself. Agents propose. Humans approve. Shelvia keeps the trusted memory.

Principle

There is no service-token path that writes directly to trusted Shelvia memory. Every agent run that produces a new claim worth keeping must propose it as a candidate. The candidate enters the review queue with status pending. A workspace member approves before it appears in any future context pack or search response.

Scope required

memory.candidates. This scope cannot write trusted memory and cannot read structured memory. Combine with memory.read or memory.context if the same agent should both read and propose.

Pattern

// 1. Agent run finishes with a finding worth remembering.
// 2. The runtime calls Shelvia with the candidate body.
// 3. Shelvia returns a pending candidate id + review URL.

import { ShelviaClient } from "@shelvia/sdk";
const shelvia = new ShelviaClient({ apiKey: process.env.SHELVIA_API_KEY! });

const candidate = await shelvia.memory.createCandidate(
  projectId,
  {
    type: "decision",             // decision | next_step | open_question | prompt | source | note | ...
    title: "Use Paystack for African card payments",
    content: "Decision body, with quote-level evidence and source links.",
    source_url: "https://example.com/sources/paystack-comparison",
  },
  {
    // Idempotency key shape: agent-<runtime>-<run-id>-<candidate-hash>.
    idempotencyKey: `agent-${runtime}-${runId}-decision-${hash(content)}`,
  },
);

console.log(candidate.status);   // "pending"
console.log(candidate.review_url); // /imports/review/<id>

Propose memory candidates safely

This is the canonical safety pattern under every recipe. Shelvia records it explicitly so reviewers can audit any agent integration against a single checklist. Agents propose. Humans approve. Shelvia keeps the trusted memory.

  • Identity: one narrow-scope Workspace API token per agent / workflow. Label it in Settings > API (e.g., "OpenAI support-agent recipe", "LangGraph research workflow", "Claude Desktop local assistant", "Google ADK production support agent"). Reuse shv_live_<hex> with memory.candidates + memory.context, no separate token shape.
  • Idempotency: every candidate write should pass Idempotency-Key shaped agent-<runtime>-<run-id>-<candidate-hash>. Where <runtime> is openai-agents-sdk, langgraph, google-adk, mcp-client, or custom. Agent reruns are common; idempotency prevents duplicate candidates.
  • Runtime tag: record the runtime via the logContinuation emit (suggested_tool: "langgraph" etc.). The candidate body intentionally has no runtime field, that lives in the observability lane.
  • Never write to trusted memory directly. There is no service-token path that bypasses review. project_decisions, source_links, and saved_prompts can only be written from the Shelvia review approval flow.
  • Never log raw chain-of-thought in the candidate body. Keep candidate content to the final claim; use the optional `reasoning` field for a short justification only.
  • Never include secrets, cookies, authorization headers, or session tokens. The forbidden-key validator rejects these with a structured error code.
  • Agents must not approve their own memory. There is no createCandidate-then-approve combo. Approval is a UI action performed by a workspace member with the right role.

Review lifecycle

  • Insert: candidate row created with status: pending.
  • Notify: workspace receives a Review Queue update.
  • Decide: a workspace member approves, edits-and-approves, or rejects.
  • Promote: on approval the row becomes trusted memory and starts appearing in context packs + search.

Observability (optional)

After the candidate is proposed, the agent can also log a continuation event. This is a separate audit / observability emit using the continuations.log scope, it records what should happen next without writing to trusted memory and without bypassing review-before-save.

// 1. Agent proposes a candidate (pending review).
await shelvia.memory.createCandidate(projectId, { /* ... */ });

// 2. Agent logs an observability event (audit only).
await shelvia.projects.logContinuation(projectId, {
  next_best_action: "Review the proposed decision and ship v2",
  why: "Candidate proposed; awaiting human approval before context pack consumes it.",
  suggested_tool: "openai-agents-sdk",  // or "langgraph", "google-adk", "mcp-client"
  priority: "normal",
});

Safety notes

  • Pass Idempotency-Key on every candidate write. Agent reruns are common; idempotency prevents duplicate candidates.
  • Don't include cookies, session tokens, or other credentials in the candidate body, the validator rejects forbidden keys with a structured error code.
  • Candidate type must be one of: prompt, decision, source, next_step, open_question, research_note, implementation_note, handoff_material, constraint, note.
  • Workspace scope: the candidate is anchored to the token's workspace. There is no body field that can retarget a different workspace.
  • Continuation events are audit-only. They do NOT write to trusted memory tables (project_decisions, source_links, saved_prompts). They are observability, not memory.

Where to go next

  • Review-before-save concept, /docs/concepts/review-before-save
  • REST API candidates endpoint, /docs/developers/api
  • Authentication scopes, /docs/developers/auth

For runnable code samples and the developer reference, see /developers. For the trust model in depth, see /security.