Documentation

Rove docs

How Rove works, how to connect your agents, every MCP tool they use, and the HTTP API for your own code.

How Rove works

Rove keeps three things, and your agents read and write all three.

TopicOne problem, feature or investigation, and everything learned about it. Work is handed off by Topic.
SessionOne piece of agent work, written up in Markdown: what was found, what was ruled out, what was decided, what's still open. Not the transcript.
FactOne sentence the team acts on: a decision, a dead end, an observation, an open question.

Order and history

Sessions and Facts are numbered in the order they're added to their Topic, and they're never edited or deleted. Work that changes your mind is recorded on top: a Session can supersede earlier ones, and a Fact can supersede, retract or answer an earlier Fact. Readers see what stands now, and the history stays honest.

Who sees what

Everything lives in a workspace. On each Topic you're a viewer (read), editor (read and add) or owner (also decides who has access). New Topics are open to the whole workspace as editors by default.

Connect your agent

Agents connect to Rove over MCP, at https://rovetech.org/mcp. Create a token in the console under Settings → Agents & tokens, then pick your agent:

Run in a terminal, then /mcp in Claude Code to check. Prompts run as /mcp__rove__check_in:

claude mcp add --transport http rove https://rovetech.org/mcp \
  --header "Authorization: Bearer sac_pat_…"

Add to ~/.codex/config.toml, then run /mcp in Codex to check:

[mcp_servers.rove]
url = "https://rovetech.org/mcp"
http_headers = { "Authorization" = "Bearer sac_pat_…" }

For GitHub Copilot, add to .vscode/mcp.json. Prompts run as /rove.check_in:

{ "servers": { "rove": {
  "type": "http", "url": "https://rovetech.org/mcp",
  "headers": { "Authorization": "Bearer sac_pat_…" }
} } }

Any agent that speaks MCP over Streamable HTTP. Most accept this shape; check your agent's docs for where it goes:

{ "mcpServers": { "rove": {
  "type": "http", "url": "https://rovetech.org/mcp",
  "headers": { "Authorization": "Bearer sac_pat_…" }
} } }

Authentication

Every MCP connection and HTTP request carries a personal access token as Authorization: Bearer sac_pat_… (the X-SAC-Token header works too). Create one under Settings → Agents & tokens after signing in to the console. Tokens belong to a person, start with sac_pat_, and are shown once when created. Give each agent, laptop or CI runner its own, so you can revoke one without breaking the rest. Treat them like passwords.

A token works in every workspace you belong to. Requests act in your home workspace unless you name another in the X-SAC-Workspace header.

MCP tools

Your agent decides when to call these; you rarely name them yourself. Each one shows exactly what your agent is told about it. Read tools never change anything.

READ sac_find_context

Find prior context for a task

What your agent seesGiven what you are about to work on, return the checked-in Sessions most likely to save you rediscovering it — ranked, with why each matched. Call this BEFORE starting unfamiliar work. Prefer it over sac_list_sessions, which returns a Topic's history in order rather than what is relevant to your task.

Arguments

task requiredstringWhat you're about to do, described the way you'd tell a colleague.
topic_idstringOptional. Search one Topic only.
tagsarray of stringOptional. Only Sessions with these tags.
limitintegerHow many Sessions to return, 1 to 25.

Example call

sac_find_context({
  "task": "why checkout p99 climbs after a deploy",
  "limit": 5
})

READ sac_get_facts

Get a Topic's facts

What your agent seesReturn what a Topic currently believes: its standing facts, with retired ones (superseded, retracted, answered) left out. The cheapest read of a Topic — call it before reading Sessions. Pass include_retired=true for the whole log, each fact annotated with what later facts said about it.

Arguments

topic_id requiredstring
include_retiredbooleantrue for the whole history, each Fact annotated with what later Facts said about it.

Example call

sac_get_facts({
  "topic_id": "top_8f2c…"
})

READ sac_list_topics

List Topics

What your agent seesList Topics visible to you, newest first. Use this before checking in work, to find the Topic it belongs to.

Arguments

limitintegerPage size, 1 to 200.
cursorstringFrom the previous call's next_cursor.

Example call

sac_list_topics({
  "limit": 50
})

READ sac_get_topic

Get a Topic

What your agent seesReturn one Topic's metadata, including how many Sessions it holds.

Arguments

topic_id requiredstring

Example call

sac_get_topic({
  "topic_id": "top_8f2c…"
})

READ sac_list_sessions

List a Topic's Sessions

What your agent seesReturn a Topic's history in sequence order, as previews rather than full text — call sac_get_session for one in full. To catch up on only what is new, pass the highest sequence_number you have already seen as after_sequence.

Arguments

topic_id requiredstring
after_sequenceintegerOnly Sessions after this sequence number. 0 for the whole history.
limitintegerPage size, 1 to 200.

Example call

sac_list_sessions({
  "topic_id": "top_8f2c…",
  "after_sequence": 0
})

READ sac_get_session

Get a Session

What your agent seesReturn one checked-in Session in full, including its complete text.

Arguments

session_id requiredstring

Example call

sac_get_session({
  "session_id": "ses_41d0…"
})

WRITE sac_create_topic

Create a Topic

What your agent seesCreate a Topic: a sharing boundary and ordered stream of work context for one problem, feature, incident, or investigation. Check work in against an existing Topic where one fits — list them first.

Arguments

name requiredstringWhat the work is about, e.g. "Checkout latency regression".
descriptionstringOptional. One line of context.
workspace_accesseditor | viewer | noneeditor (default): everyone in the workspace can read and add. viewer: read only. none: only you.

Example call

sac_create_topic({
  "name": "Checkout latency regression"
})

WRITE sac_upload_session

Check in a Session

What your agent seesAppend a compacted Session to a Topic, under a short specific title. The text should be the durable context another developer or agent needs to continue the work — what was established, what was ruled out, what was decided, and what is still open — not a transcript. Immutable once checked in; continued work becomes another Session. Use the `check_in` prompt for guidance on what to write.

Arguments

topic_id requiredstring
title requiredstringA short handle, like a commit subject. Under about ten words.
text requiredstringThe work, in Markdown: what was found, ruled out, decided, and what's still open.
tagsarray of stringLowercase labels, up to 32.
supersedesarray of integerSequence numbers of earlier Sessions this work overturns. Nothing is deleted; readers are told.
idempotency_keystringOptional. Retrying with the same key returns the original Session, never a duplicate.

Example call

sac_upload_session({
  "topic_id": "top_8f2c…",
  "title": "Checkout p99: pool starvation, not the CDN",
  "text": "## Found\n…\n## Ruled out\n…\n## Next step\n…",
  "tags": [
    "latency",
    "checkout"
  ]
})

WRITE sac_add_fact

Add a fact to a Topic

What your agent seesAppend one small claim (at most 280 characters) to a Topic's fact log. Facts are the Topic's standing beliefs — what was decided, ruled out, observed, or is still open — in a form the next agent can read in one call. Never edited: to correct a fact, add another that supersedes or retracts it. Verbs that make a claim of their own (no target): asserts — a claim you believe true; observed — something measured or seen directly; decided — a choice that was made; ruled_out — a hypothesis eliminated, and how; open_question — something still unresolved, phrased as the question. Verbs that act on an earlier fact (target = its number): supersedes — replaces it; the statement is the new claim; retracts — withdraws it with no replacement; the statement is why; answers — resolves an open_question; the statement is the answer; confirms — adds evidence for it without changing it.

Arguments

topic_id requiredstring
verb requiredasserts | observed | decided | ruled_out | open_question | supersedes | retracts | answers | confirmsdecided, observed, asserts, ruled_out, open_question; or, acting on an earlier Fact, supersedes, retracts, answers, confirms.
statement requiredstringOne sentence, up to 280 characters.
targetintegerThe earlier Fact's number, for verbs that act on one.
source_sessionintegerOptional. The Session it came from.
idempotency_keystringOptional. Retrying with the same key returns the original Fact.

Example call

sac_add_fact({
  "topic_id": "top_8f2c…",
  "verb": "ruled_out",
  "statement": "The CDN. Cache hit ratio was flat all window.",
  "source_session": 1
})

MCP prompts

Prompts are ready-made instructions you run yourself, as slash commands. Your agent receives the full text and follows it, calling the tools above as it goes.

Check in this session's work

Compact the current session into a portable Session artifact and append it to a Topic.

When: At the end of a piece of work, or before handing it off. Your agent writes up what it found, ruled out and left open, and checks it in to the right Topic.

Run it

Claude Code/mcp__rove__check_in
VS Code/rove.check_in

Optionally name the Topic: /mcp__rove__check_in top_8f2c….

Preview the prompt your agent receives
Compact the work from this session into a Rove Session, then append it with `sac_upload_session`.

You are writing for the next person or agent picking this up cold. They have the codebase; they do not have your reasoning. Optimize for what would take them longest to rediscover.

Include, where each applies:

- What was being investigated, and why — the question behind the work.
- What you established, with the evidence that settled it (a file:line, a command   and its output, a measurement).
- What you ruled out, and how. This is the highest-value part and the part most   often dropped: it is what stops the next person repeating a dead end.
- Decisions taken, and the reason — especially where a plausible alternative was   rejected.
- What is still open: the unresolved questions, the things you suspect but did   not confirm, the next step you would have taken.

Leave out what the repository already records. Do not restate the diff, re-explain code that can be read, or narrate the conversation turn by turn. Write prose and concrete specifics rather than a summary of topics covered — "the pool is capped at 20 in config/db.yml:14, which is why p99 climbs under load" beats "investigated connection pooling".

Be honest about confidence. Mark what you verified and what you are inferring; a confident wrong Session is worse than no Session.

Write it in Markdown: the console renders headings, lists, `code`, fenced code blocks and links. Raw HTML and images are shown as plain text.

If this work overturns something already checked into the Topic — a finding since shown wrong, a decision since reversed, an approach ruled out that you have now taken — pass those sequence numbers as `supersedes`. Nothing is deleted: the earlier Session stays, and readers are told it was overturned and by what. That is how a Topic stays trustworthy without anyone rewriting history. Use it only where you mean it — "related to" is not superseding, and retiring the wrong finding is worse than retiring none.

Give it a short, specific title — a handle someone scanning the Topic can recognise, the way a good commit subject works. "Traced checkout p99 to pool starvation", not "Investigation" or "Debugging session". Under about ten words.

Add a few lowercase tags for retrieval, then call `sac_upload_session` with the title and the compacted text. It is immutable once checked in — continued work becomes another Session, so check in when you have something worth handing over rather than waiting for the work to be finished.

Then record the load-bearing claims as facts with `sac_add_fact`, passing the new Session's sequence number as `source_session`: each decision (`decided`), each dead end (`ruled_out`), each unresolved question (`open_question`), each finding you would stake the next step on (`asserts` or `observed`). One sentence each. Call `sac_get_facts` first: where a standing fact is now wrong, `supersedes` or `retracts` it rather than adding a contradicting one, and where you resolved an open question, `answers` it. The fact sheet is what the next agent reads first.

First call `sac_list_topics` and pick the Topic this work belongs to. If none fits, create one with `sac_create_topic` — a Topic is a problem, feature, incident, or investigation, not a single task.

Pick up prior work on this

Retrieve what is already known about a piece of work before starting it, so the investigation is not replayed.

When: Before starting work, or when picking up someone else's. Your agent reads what stands and what was tried, and tells you what it's carrying forward.

Run it

Claude Code/mcp__rove__resume
VS Code/rove.resume

Say what you're about to do: /mcp__rove__resume why checkout p99 climbs after a deploy.

Preview the prompt your agent receives
Before starting this work, find out what is already known about it.

If you know the Topic, call `sac_get_facts` on it first. It is the cheapest read there is: the decisions, dead ends and open questions that currently stand, one sentence each, with anything since superseded or retracted already left out.

Call `sac_find_context` with a prose description of what you are about to do — the problem, not keywords. Describe it the way you would to a colleague: "why checkout p99 climbed after the 9/14 deploy", not "latency". The ranking reads your description, so a richer one retrieves better.

Then read what comes back, and use it as follows.

- Treat each Session as evidence, not as truth. It records what someone   believed when they wrote it. Each result reports where it sits in its Topic —   `sequence_position` and `later_in_topic` — so a Session with work checked in   after it is a claim about a past moment rather than the current state. Where   that count is high, read what followed with `sac_list_sessions` before relying   on it. Older findings about fast-moving code deserve more suspicion.
- Take the ruled-out list seriously. It is the highest-value part and the   cheapest to waste: repeating a dead end someone already walked is the specific   failure this product exists to prevent.
- Where Sessions in the same Topic disagree, the later one usually wins, but say   so rather than silently picking. A contradiction is itself a finding.
- Verify before you rely on it. If a Session says a value is set in a file, open   the file. Cheap to check, expensive to assume.
- Say what you took from it. Tell the user which Sessions you are building on   and what you are carrying forward, so they can correct you early if the   context is stale or was misread.

If nothing relevant comes back, this is new ground — which is worth knowing, and worth a check-in when you are done.

The work: why checkout p99 climbs after a deploy

Shown with task = "why checkout p99 climbs after a deploy".

MCP resource

Tools are things your agent does; a resource is something it reads. Attaching a Topic's timeline puts its whole history into the conversation at once, without your agent spending tool calls to fetch it. Use it when you want your agent to have everything about a Topic from the start.

RESOURCE sac://topics/{topic_id}

Topic timeline

The full checked-in history of one Topic, in sequence order — the accumulated work context for that problem or investigation — headed by the facts that currently stand.

Attach it

Claude CodeType @ and pick it, or write @rove:sac://topics/top_8f2c…
VS CodeAdd Context, then MCP Resources
Other agentsWherever your agent lists MCP resources, with the Topic's id
Preview what your agent receives (Markdown)
# Checkout latency regression
p99 rose 400ms after Tuesday's deploy

_2 sessions · created by usr_alice…_

## Standing facts

- **f1** ruled_out: The CDN. Cache hit ratio was flat all window. _(from seq 1)_
- **f2** decided: Raise the connection pool to 40. _(from seq 1)_
- **f4** now: The new retry opened a second connection per request. _(answers f3; from seq 2)_

## 1. Checkout p99: pool starvation, not the CDN
_usr_alice… · 2026-10-12T17:30:00+00:00 · latency, checkout_

## Found
A pool of 10 saturates at peak; 40 fixes it in staging.
…

## 2. Traced the doubled connections to the new retry
_usr_bob… · 2026-10-13T11:05:00+00:00 · latency_
…

Workflows

Hand off work

When you stop, run /mcp__rove__check_in. Your agent finds the right Topic (sac_list_topics, or sac_create_topic for new work), checks in a Session (sac_upload_session), and records the conclusions worth acting on as Facts (sac_add_fact). Then tell your teammate the Topic's name, however your team usually does.

Pick up someone's work

Ask your agent to pick it up, for example "Pick up Alice's checkout work." It reads the Topic's Facts (sac_get_facts) and Sessions (sac_list_sessions, then sac_get_session for the full text), and starts from where they stopped.

Start new work

Run /mcp__rove__resume with a sentence about what you're doing. Your agent checks what's already known (sac_find_context), skips what was ruled out, and tells you what it's building on.

Catch up on a Topic

Pass the last sequence number you read as after_sequence to sac_list_sessions, and you get only what came after.

Correct the record

Nothing is edited. Check in a Session that supersedes the one that was wrong, or add a Fact that supersedes or retracts the old one. Readers are told what changed and why.

HTTP API

The same operations over HTTP, for scripts and your own integrations. Base URL https://rovetech.org; send the headers from Authentication with every request. The OpenAPI schema covers exactly these endpoints.

Identity

GET /v1/me

Who am I

The user the token belongs to, the workspace the request acts in, and every workspace you belong to. A quick way to check a token works.

Example

curl -X GET https://rovetech.org/v1/me \
  -H "Authorization: Bearer sac_pat_…"

Response

{
  "user": {
    "user_id": "usr_alice…",
    "email": "alice@yourco.com",
    "display_name": null,
    "created_at": "2026-10-01T09:00:00Z"
  },
  "workspace": {
    "workspace_id": "ws_7d1e…",
    "name": "Acme engineering",
    "created_at": "2026-10-01T09:00:00Z"
  },
  "role": "member",
  "teams": [],
  "workspaces": [
    {
      "workspace": {
        "workspace_id": "ws_7d1e…",
        "name": "Acme engineering",
        "created_at": "2026-10-01T09:00:00Z"
      },
      "role": "member"
    }
  ]
}

Topics

POST /v1/topics

Create a Topic

A Topic is one problem, feature or investigation. Sessions and Facts are added to it. You become its owner.

Request body

name requiredstringWhat the work is about. Up to 200 characters.
descriptionstring | nullOptional. One line of context.
workspace_accessviewer | editor | owner | nullWhat everyone in the workspace can do: editor (the default) or viewer. null keeps it to you.

Example

curl -X POST https://rovetech.org/v1/topics \
  -H "Authorization: Bearer sac_pat_…" \
  -H "Content-Type: application/json" \
  -d '{"name": "Checkout latency regression", "description": "p99 rose 400ms after Tuesday's deploy"}'

Response

{
  "topic_id": "top_8f2c…",
  "name": "Checkout latency regression",
  "description": "p99 rose 400ms after Tuesday's deploy",
  "workspace_access": "editor",
  "created_by": "usr_alice…",
  "created_at": "2026-10-12T15:04:05Z",
  "latest_sequence_number": 2,
  "latest_fact_sequence": 3,
  "your_role": "owner"
}

GET /v1/topics

List Topics

Topics you can see in the workspace, newest first, a page at a time.

Parameters

limitintegerPage size.
cursorstring | nullFrom the previous page's next_cursor. null there means there are no more pages.

Example

curl -X GET https://rovetech.org/v1/topics?limit=50 \
  -H "Authorization: Bearer sac_pat_…"

Response

{
  "items": [
    {
      "topic_id": "top_8f2c…",
      "name": "Checkout latency regression",
      "description": "p99 rose 400ms after Tuesday's deploy",
      "workspace_access": "editor",
      "created_by": "usr_alice…",
      "created_at": "2026-10-12T15:04:05Z",
      "latest_sequence_number": 2,
      "latest_fact_sequence": 3,
      "your_role": "owner"
    }
  ],
  "next_cursor": null
}

GET /v1/topics/{topic_id}

Get a Topic

One Topic, with how many Sessions and Facts it holds and your role on it.

Parameters

topic_id requiredstring

Example

curl -X GET https://rovetech.org/v1/topics/top_8f2c… \
  -H "Authorization: Bearer sac_pat_…"

Response

{
  "topic_id": "top_8f2c…",
  "name": "Checkout latency regression",
  "description": "p99 rose 400ms after Tuesday's deploy",
  "workspace_access": "editor",
  "created_by": "usr_alice…",
  "created_at": "2026-10-12T15:04:05Z",
  "latest_sequence_number": 2,
  "latest_fact_sequence": 3,
  "your_role": "owner"
}

Sessions

POST /v1/topics/{topic_id}/sessions

Check in a Session

Add one unit of work to a Topic: what was found, what was ruled out, what's next. Sessions are immutable and numbered in order. This is how work is handed off: whoever picks it up reads the Topic's Sessions.

Parameters

topic_id requiredstring
Idempotency-Keystring | nullOptional, recommended. A unique value per attempt: a retry with the same key returns the original Session instead of adding a second.

Request body

schema_versionintegerAlways 1.
title requiredstringA short handle, like a commit subject. Up to 200 characters.
text requiredstringThe work itself, in Markdown. Write for whoever continues it.
tagsarray of stringOptional labels, up to 32.
supersedesarray of integerOptional. Sequence numbers of earlier Sessions in this Topic that this one overturns. Nothing is deleted; readers are told.

Example

curl -X POST https://rovetech.org/v1/topics/top_8f2c…/sessions \
  -H "Authorization: Bearer sac_pat_…" \
  -H "Idempotency-Key: 7f3c9a1e-…" \
  -H "Content-Type: application/json" \
  -d '{"title": "Checkout p99: pool starvation, not the CDN", "text": "## Found\n\u2026\n## Ruled out\n\u2026\n## Next step\n\u2026", "tags": ["latency", "checkout"]}'

Response

{
  "session_id": "ses_41d0…",
  "topic_id": "top_8f2c…",
  "sequence_number": 1,
  "title": "Checkout p99: pool starvation, not the CDN",
  "text": "## Found\nA pool of 10 saturates at peak; 40 fixes it in staging.\n\n## Ruled out\nThe CDN…\n\n## Next step\nWhy Tuesday's deploy doubled connection use.",
  "tags": [
    "latency",
    "checkout"
  ],
  "schema_version": 1,
  "created_by": "usr_alice…",
  "checked_in_at": "2026-10-12T17:30:00Z",
  "supersedes": []
}

GET /v1/topics/{topic_id}/sessions

List a Topic's Sessions

The Topic's Sessions in order. To pick up a handoff, read them from the start; to catch up, pass the last sequence number you read and get only what came after.

Parameters

topic_id requiredstring
after_sequenceintegerOnly Sessions after this sequence number. 0 for all.
limitintegerPage size.

Example

curl -X GET https://rovetech.org/v1/topics/top_8f2c…/sessions?after_sequence=0 \
  -H "Authorization: Bearer sac_pat_…"

Response

{
  "items": [
    {
      "session_id": "ses_41d0…",
      "topic_id": "top_8f2c…",
      "sequence_number": 1,
      "title": "Checkout p99: pool starvation, not the CDN",
      "text": "## Found\nA pool of 10 saturates at peak; 40 fixes it in staging.\n\n## Ruled out\nThe CDN…\n\n## Next step\nWhy Tuesday's deploy doubled connection use.",
      "tags": [
        "latency",
        "checkout"
      ],
      "schema_version": 1,
      "created_by": "usr_alice…",
      "checked_in_at": "2026-10-12T17:30:00Z",
      "supersedes": []
    }
  ],
  "next_cursor": null
}

GET /v1/sessions/{session_id}

Get a Session

One Session by its id.

Parameters

session_id requiredstring

Example

curl -X GET https://rovetech.org/v1/sessions/ses_41d0… \
  -H "Authorization: Bearer sac_pat_…"

Response

{
  "session_id": "ses_41d0…",
  "topic_id": "top_8f2c…",
  "sequence_number": 1,
  "title": "Checkout p99: pool starvation, not the CDN",
  "text": "## Found\nA pool of 10 saturates at peak; 40 fixes it in staging.\n\n## Ruled out\nThe CDN…\n\n## Next step\nWhy Tuesday's deploy doubled connection use.",
  "tags": [
    "latency",
    "checkout"
  ],
  "schema_version": 1,
  "created_by": "usr_alice…",
  "checked_in_at": "2026-10-12T17:30:00Z",
  "supersedes": []
}

Facts

GET /v1/topics/{topic_id}/facts

Get a Topic's Facts

What the Topic currently holds to be true: decisions, dead ends and open questions, one sentence each. Facts that were later corrected are left out unless you ask for them.

Parameters

topic_id requiredstring
include_retiredbooleantrue for the whole history, including corrected Facts.
after_sequenceintegerOnly Facts after this sequence number.

Example

curl -X GET https://rovetech.org/v1/topics/top_8f2c…/facts \
  -H "Authorization: Bearer sac_pat_…"

Response

{
  "topic_id": "top_8f2c…",
  "facts": [
    {
      "fact": {
        "fact_id": "fct_c2a9…",
        "topic_id": "top_8f2c…",
        "sequence_number": 1,
        "verb": "ruled_out",
        "statement": "The CDN. Cache hit ratio was flat all window.",
        "target": null,
        "source_session": 1,
        "created_by": "usr_alice…",
        "asserted_at": "2026-10-12T17:31:00Z"
      },
      "standing": true
    }
  ],
  "standing_count": 1,
  "total": 1,
  "include_retired": false
}

POST /v1/topics/{topic_id}/facts

Add a Fact

Record one conclusion from the work. Facts are never edited: to correct one, add a Fact that supersedes or retracts it.

Parameters

topic_id requiredstring
Idempotency-Keystring | nullOptional, recommended. A retry with the same key returns the original Fact.

Request body

verb requiredasserts | observed | decided | ruled_out | open_question | supersedes | retracts | answers | confirmsdecided, observed, asserts, ruled_out or open_question; or, acting on an earlier Fact, supersedes, retracts, answers or confirms.
statement requiredstringOne sentence, up to 280 characters.
targetinteger | nullThe earlier Fact's sequence number, for the verbs that act on one.
source_sessioninteger | nullOptional. The sequence number of the Session it came from.

Example

curl -X POST https://rovetech.org/v1/topics/top_8f2c…/facts \
  -H "Authorization: Bearer sac_pat_…" \
  -H "Idempotency-Key: 7f3c9a1e-…" \
  -H "Content-Type: application/json" \
  -d '{"verb": "ruled_out", "statement": "The CDN. Cache hit ratio was flat all window.", "source_session": 1}'

Response

{
  "fact_id": "fct_c2a9…",
  "topic_id": "top_8f2c…",
  "sequence_number": 1,
  "verb": "ruled_out",
  "statement": "The CDN. Cache hit ratio was flat all window.",
  "target": null,
  "source_session": 1,
  "created_by": "usr_alice…",
  "asserted_at": "2026-10-12T17:31:00Z"
}

POST /v1/context/find

Find prior context

Before starting work, describe it in a sentence and get back the Sessions most worth reading, across every Topic you can see, with why each matched.

Request body

task requiredstringWhat you're about to work on, in plain words.
topic_idstring | nullOptional. Search one Topic only.
tagsarray of stringOptional. Only Sessions with these tags.
limitintegerHow many Sessions to return.
budget_charsinteger

Example

curl -X POST https://rovetech.org/v1/context/find \
  -H "Authorization: Bearer sac_pat_…" \
  -H "Content-Type: application/json" \
  -d '{"task": "why checkout p99 climbs after a deploy", "limit": 5}'

Response

{
  "task": "why checkout p99 climbs after a deploy",
  "topics": [
    {
      "topic_id": "top_8f2c…",
      "name": "Checkout latency regression",
      "description": "p99 rose 400ms after Tuesday's deploy",
      "workspace_access": "editor",
      "created_by": "usr_alice…",
      "created_at": "2026-10-12T15:04:05Z",
      "latest_sequence_number": 2,
      "latest_fact_sequence": 3,
      "your_role": "owner"
    }
  ],
  "sessions": [],
  "considered": 12,
  "budget_exhausted": false,
  "candidates_truncated": false
}

Errors and retries

Errors return a JSON body with a machine-readable error and a human message:

{
  "error": "TopicNotFoundError",
  "message": "topic not found: top_8f2c…"
}
401Missing or invalid token.
403You can see it, but your role doesn't allow this.
404It doesn't exist, or you don't have access to it.
422The request body or parameters are invalid.

Writes accept an idempotency key (the Idempotency-Key header over HTTP, the idempotency_key argument over MCP). Send a new unique value with each write; if it times out, retry with the same key and you get the original result back instead of a duplicate.

Limits

Topic name200 characters
Session title200 characters
Session tags32 per Session
Session textno fixed limit; requests are capped at 256 KB
Fact statement280 characters
Facts per Topic2,000
Page size (lists)1 to 200, default 50
Find context results1 to 25, default 5
Find context task4,000 characters