SmartMemory
ExamplesClinical trials

Ask an as-of question

Find out which consent form version a site should have used on a given day.

Set SMARTMEMORY_API_KEY, SMARTMEMORY_WORKSPACE_ID and optionally SMARTMEMORY_BASE_URL (default https://api.smartmemory.ai). See the overview for setup.

What it uses

  • client.search and client.memories.search take the question as written. A day named in the question narrows retrieval to records that were valid on that day.
  • client.ask and client.memories.ask answer from the retrieved records and return the evidence they used. They raise an error when the deployment's language model cannot answer, there is no fallback answer.
  • Both SDKs also take as_of_date (asOfDate) on search. That one is transaction time: it returns what the system believed on that date, which is the audit question. The day in the question text is valid time: it returns what was true on that date.

Python

"""Ask an as-of question: which ICF version should site 03 have used on 2026-03-03?"""

import os

from smartmemory_client import SmartMemoryClient
from smartmemory_client.errors import SmartMemoryServerError

client = SmartMemoryClient(
    base_url=os.environ.get("SMARTMEMORY_BASE_URL", "https://api.smartmemory.ai"),
    api_key=os.environ["SMARTMEMORY_API_KEY"],
    workspace_id=os.environ["SMARTMEMORY_WORKSPACE_ID"],
)

QUESTION = "Which ICF version should site 03 have used on 2026-03-03?"

# A day named in the question narrows retrieval to records that were valid on that day.
print("Records valid on 2026-03-03:")
for hit in client.search(QUESTION, top_k=3):
    print(" ", hit.metadata.get("record_id"), hit.valid_start_time[:10], "|", hit.content[:70])

# ask() answers from those records and returns the evidence it used. It raises when the
# deployment's language model cannot answer, it never invents a fallback.
try:
    result = client.ask(QUESTION, limit=5)
except SmartMemoryServerError as error:
    print("ask() unavailable:", error.status_code)
else:
    print("Answer:", result["answer"])
    for item in result["evidence"]:
        print("  evidence:", item["item_id"])

Output:

Records valid on 2026-03-03:
  CT-DEV-03 2026-03-03 | Protocol deviation DEV-03: consent on superseded ICF 2.0, participant 
ask() unavailable: 502

JavaScript

// Ask an as-of question: which ICF version should site 03 have used on 2026-03-03?
import { SmartMemoryClient } from "@smartmemory/sdk-js";

const client = new SmartMemoryClient({
  apiBaseUrl: process.env.SMARTMEMORY_BASE_URL ?? "https://api.smartmemory.ai",
  apiKey: process.env.SMARTMEMORY_API_KEY,
  storage: "memory", // a script has no browser storage
});
client.setWorkspaceId(process.env.SMARTMEMORY_WORKSPACE_ID);

const QUESTION = "Which ICF version should site 03 have used on 2026-03-03?";

// A day named in the question narrows retrieval to records that were valid on that day.
console.log("Records valid on 2026-03-03:");
const { results } = await client.memories.search(QUESTION, { topK: 3 });
for (const hit of results) {
  console.log(" ", hit.metadata?.record_id, hit.valid_start_time.slice(0, 10), "|", hit.content.slice(0, 70));
}

// ask() answers from those records and returns the evidence it used. It rejects when the
// deployment's language model cannot answer, it never invents a fallback.
try {
  const result = await client.memories.ask(QUESTION, { limit: 5 });
  console.log("Answer:", result.answer);
  for (const item of result.evidence) console.log("  evidence:", item.item_id);
} catch (error) {
  console.log("ask() unavailable:", error.status);
}

Output:

Records valid on 2026-03-03:
  CT-DEV-03 2026-03-03 | Protocol deviation DEV-03: consent on superseded ICF 2.0, participant 
[session] Service unavailable: HTTP 502
ask() unavailable: 502

Notes

The search step ran locally and found the record that answers the question: the deviation record for a participant consented on 2026-03-03 on a superseded form. The ask step was not run locally: the local language model provider is unavailable, so the service answered 502 and the script printed that. Not run locally, expected output shape below. The field names come from the SDK's documented return value, the values depend on the deployment.

{
  "answer": "<written answer>",
  "reasoning": "<how the answer was reached>",
  "evidence": [{"item_id": "<memory id>", "content": "<memory text>"}],
  "relations": [{"source": "...", "type": "...", "target": "...", "source_id": "...", "target_id": "..."}]
}

The output below is from a real run against a local test stack seeded with the demo dataset. It shows record ids and dates only.

On this page