Korely

A research agent that builds on every session

You're three weeks into researching "EU AI Act compliance for our SaaS" with an agent. A stateless agent opens session 5 by asking what you're researching, re-derives the obligations you already pinned down in session 2, and has no idea you overturned one of them after the legal review. You spend the first ten minutes re-grounding it.

With Korely in the loop, session 5 opens already knowing the four obligations you flagged, which two are still open, and which earlier conclusion was overturned and why. Each session's findings accumulate into typed facts; contradictions supersede the old answer instead of piling up; and as_of can replay exactly what you believed on any date. This cookbook walks the pattern at the call level.

The snippets use the Python SDK (pip install korely-memory). The same calls work over the REST API and the Node SDK.

The scoping: one project, many sessions

A research thread is one user_id (the project), and each session is a run_id. Findings written under any session accumulate under the project, so get_context and get_facts see all of them; run_id is there when you want to narrow back down to a single session.

from korely_memory import Korely
korely = Korely(api_key="kor_live_...", region="eu")
PROJECT = "proj-eu-ai-act"
SESSION = "session-2026-06-12" # one run_id per working session

1. Session start: load everything known so far

Before the first turn of a new session, assemble the project's state into a prompt-ready block. get_context returns the active facts plus the most relevant memories, already fitted to a token budget, one call, no model on the read path.

ctx = korely.get_context(
query="EU AI Act obligations, open questions, decisions so far",
user_id=PROJECT,
token_budget=1200,
)
# ctx.context -> a Markdown block to drop into your system prompt
# ctx.tokens -> how many tokens it used
# ctx.sources -> the memory ids it drew from
{
"context": "Active facts:\n- proj-eu-ai-act has_obligation \"register high-risk system (Art. 6)\"\n- proj-eu-ai-act has_obligation \"human oversight (Art. 14)\"\n- proj-eu-ai-act open_question \"does the hiring module count as high-risk?\"\n\nRelevant findings:\n- Session 3: legal review concluded the hiring module qualifies for the Annex III research exemption...",
"tokens": 412,
"sources": ["mem_7c1a", "mem_2b40", "mem_9f08"]
}

The agent now opens the session already grounded. No "remind me what we're working on."

Session 5

You re-open the research thread

  • Three weeks in
  • Resolves to user_id "proj-eu-ai-act"

Korely

get_context(query=...)

  • Active facts + relevant findings, every session
  • Assembled, not re-generated

Turn 1

Agent is already grounded

  • Knows the 4 obligations + 2 open questions
  • Knows the overturned conclusion

2. During the session: search the back-catalogue

When the agent needs a specific past finding, search the project's memories. Scoped to the project, ranked by relevance, no model in the path beyond the query embedding.

hits = korely.search(
"annex III exemption hiring module",
user_id=PROJECT,
limit=5,
)
# each hit: {id, score, snippet, user_id, agent_id, metadata}

3. On a finding: write it down (any session)

When the agent reaches a conclusion, store it. Tag the session with run_id; it still accumulates under the project.

korely.add(
"Legal review: the hiring module qualifies for the Annex III research "
"exemption, so Article 6 high-risk registration does not apply.",
user_id=PROJECT,
run_id=SESSION,
)

Fact extraction runs server-side: this finding becomes typed (subject, predicate, object) triples a few seconds after the write returns, ready at the next get_facts / get_context.

4. When a finding overturns an earlier one

Session 2 concluded "Article 6 high-risk registration applies." Session 3's exemption finding contradicts it. You don't write supersede logic: the two-stage contradiction detector finds the earlier fact (same predicate, conflicting object) and invalidates it. The old conclusion isn't deleted, it gets an invalid_at timestamp and stops being served.

facts = korely.get_facts(user_id=PROJECT, predicate_family="other")
# returns only what's TRUE NOW — the Art. 6 "applies" fact is gone from this list,
# replaced by the "does not apply" conclusion. No stale answer lingers.

5. Point in time: what did we believe back then?

This is the part a vector store can't do. Replay the project's knowledge as it stood on any date, before the legal review, say, for an audit trail or to understand how a conclusion changed.

# what we believed before the June 5 legal review
before = korely.get_facts(user_id=PROJECT, as_of="2026-06-04")
# the full point-in-time profile, grouped by family
snapshot = korely.get_profile(user_id=PROJECT, as_of="2026-06-04")

as_of="2026-06-04" returns the facts that were valid on that date: the "Article 6 applies" conclusion is back, because on June 4 it was still live. The history is intact; you're just choosing which moment to read from.

Why not dump the transcripts into a vector DB?

  • Staleness. A transcript store holds both "Article 6 applies" (session 2) and "Article 6 does not apply" (session 3), and you're trusting the LLM to pick the right one every turn. get_facts returns only what's valid now, the contradiction is resolved before the model sees it.
  • Token cost. Re-feeding five sessions of transcript is thousands of tokens every turn, growing forever. A get_context block is a few hundred tokens and grows with what's worth remembering, not with how long you've been researching.
  • No point in time. A vector store has no concept of "what was true on June 4". Bi-temporal facts do.

One honest caveat: korely.add runs fact extraction asynchronously, so a finding's typed facts land a few seconds after the write returns, ready by the next session's get_context, not inside the same call. Write findings fire-and-forget during the session; read the assembled state at the start of the next one.

Where to go next

Temporal facts explains supersession and as_of under the hood; get context is the call in step 1; the memory-as-a-tool cookbook hands these same operations to the model as callable tools.