Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
OPENROUTER_API_KEYNoYour OpenRouter API key, used for classification and embeddings as described in the 'What it costs' section.

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": true
}
logging
{}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}

Tools

Functions exposed to the LLM to take actions

NameDescription
searchA

Route to the most relevant ATOMS in the trusted knowledge base (David's saved opinions + tracked artifacts). This is a ROUTER, not an answer: each hit is a thin card — matched-chunk snippet + a pointer (source_url / raw_ref / atom_id) + ranks — NOT a statement of what the source says. To assert what a source actually claims, call open(atom_id) and read its raw text. That split is the whole trust model.

RETURNS {hits, notices, insights, trace, frontier_atoms} — and the non-hit keys are read DIFFERENT ways: • notices — finished sentences about what your QUERY did (a filter that matched nothing, a handle that resolved to nobody or to two people, results truncated). Surface these to the user when the list is non-empty; they are written to be repeated as-is. [] on a healthy query, which is the normal case. • insights — VALUES about the evidence: authors/sources/topics counts, date_span, body_state, saved_vs_crawled, corpus_newest, filter_cost (what each filter cost you), and resolved_who when you passed who=. These describe hits ONLY. On a default call saved_vs_crawled therefore lists no crawled atoms — they are in frontier_atoms, not missing. • trace — VALUES about what the ENGINE did: ran (which arms actually ran), score_scale (the units score is in), candidates/ranked/showing, cutoff, fts_query, filters as applied. • frontier_atoms — a SECOND, separately ranked list: atoms found by the user's standing keyword queries rather than saved or written by anyone they follow. Present only on a default call (see entry_mode). Same card shape as hits, capped at 8 and floored at a fraction of its own top score, with floor.dropped saying how many the floor removed. Offer it as "and from the frontier crawl…", never merged into hits: its scores are ranked against other frontier atoms and mean nothing next to theirs.

frontier_atoms is NOT the frontier key you may also see here. That one is the Frontier QUEUE's push notice — staged candidates not yet in the KB — and it appears at most once a session. These are atoms already in the KB that matched THIS query.

insights and trace are for your reasoning — do not recite them to the user. They are bare values on purpose. Use them to decide what to do next (open something, re-query, drop a filter, warn about a lopsided result); say the CONCLUSION in your own words, never the fields. Only notices is written to be read out.

score is not comparable across calls unless trace.score_scale matches. It is a raw cosine under semantic (and under a hybrid run that dropped its keyword arm), a reciprocal rank under bm25, and a fused rank sum under a true hybrid run. 0.03 in one scale can outrank 0.7 in another. A known bias rides the cosine: a longer document max-pools higher for having more chunks to draw from, so weigh a long hit's lead over a short one as smaller than it looks.

Retrieval: an optional tag/kind/source/author pre-filter, then a BM25 arm and a semantic arm, fused by rank. Ranking is pure relevance — there is no trust re-rank. mode="hybrid" often runs only the semantic arm: a conceptual query with no literal token (most natural-language questions over three words) gives BM25 a weight of 0 and the keyword arm is skipped. trace.ran says which arms really ran; do not assume both.

Read body_state before quoting a snippet. It says how much of the source we actually stored: "complete" (the whole body), "partial" (knowingly short of it — a paywall teaser, a truncated feed entry), "absent" (no body, the card is all there is), or "pending" (not yet determined). On "partial" or "absent", do not present the text as the full thing — say what you have, and follow source_url for the rest. body_basis says how that was decided: "observed" (we saw the boundary), "stated" (the source declared it), "assumed".

Read when_precision before reporting a date, especially under date_from/date_to. when_ts always LOOKS like a day, and for two values it is not one: • "year" — only the YEAR is known (common for papers); when_ts is that Jan 1 as a FLOOR, not a real day. Such a hit is included whenever its year OVERLAPS your window, deliberately — a wrongly-included atom you can see and discard, a wrongly excluded one you cannot. Caveat it to the user ("published sometime in 2025"), never as a confirmed date match. • "push" — GitHub's LAST-PUSH date, NOT a publication date. A repo matching "after May" was ACTIVE then and may have been created years earlier. A different KIND of date, not a coarser one, and the easiest thing here to misreport. Atoms with NO recorded date are excluded by either bound, and a notice says how many.

Each hit also carries payload — whatever extras that atom's SOURCE had, returned verbatim. It is NOT a fixed schema and it is NOT filterable: GitHub atoms carry stars/code_language, X atoms like_count/is_thread, papers citationCount/venue. Read the keys that are there; never assume a key exists because another hit had it.

openA

Follow an atom's pointer and return its REAL raw snapshot text + live source_url. Call this before citing or asserting anything an atom "says" — search only routes you to the atom; THIS gives you the ground truth to reason from. Returns {atom_id, source_url, raw, description, body_state, body_basis, payload, …}; an unknown id returns {error: "not found"}.

The pre-citation check: raw is only as complete as body_state says. "complete" means you have the whole body. "partial" means you have a knowing fragment — a paywall teaser or a truncated entry — so quoting it as the full article invents a citation; attribute what you have, and send the reader to source_url. "absent" means there is no body at all. body_basis says how that was determined (observed / stated / assumed). payload holds that source's own extras verbatim, and its keys differ per source.

kb must be whatever the hit card carried. An atom id is scoped to ONE knowledge base — the same tweet in two people's stores is one id in each — so opening a foreign id without its kb either finds nothing or hands you your own copy of the same source.

aggregateA

A state-of-play skeleton over a SCOPE of the KB — counts by kind/source, trust coverage, topic/entity distribution, and the most-recent atom DESCRIPTIONS (mechanical, so safe to read without opening). Use it to draft a dossier or "what do I have on X", THEN open() the pivotal atoms to ground each claim in raw text. Scope is optional: omit everything for the whole store, or filter by tags / what_kind / source_type / who_id / date_from / date_to.

This takes IDs, not handles. To scope to a person, call search(who="@handle") first and pass its insights.resolved_who[].who_ids here.

oracleA

Choose who to trust: turn the people you already curate (follows, Lists, bookmarks, subscriptions, likes) into your Oracles — the sources the KB deep-ingests and roots trust on. Runs entirely in chat.

NOT the setup tool. onboard readies the machine (keys, consent, the first curation pull); this decides WHO is in. Reach for this when the user asks who to trust, wants to see or change their people, or asks whether their sources are current.

FLOW: call action='screen' → read the ranked candidates to the user (the PRE-TICKED ones are people you've corroborated with ≥2 distinct signals — your default-yes set; the rest are shown unchecked; non-persons are demoted to the end, never hidden) → ask which to keep → call action='confirm' with the kept canonical_ids → then, before action='ingest', ask the user how far back to pull and pass their answer as x_lookback.

Why that question is not optional: the default is only ~6 months, so a user who wanted their Oracle's whole visible history gets a fraction of it and is never told. (It is no longer a COST question — X reads are free since the cutover — it is a completeness one, which is the same reason to ask and a different reason to give.) action='screen' returns the exact presets and defaults under lookback_options — offer those, don't invent your own. The web archive is FREE and already pulls in full, so ask about it (web_lookback) only if the user wants it NARROWED.

To add someone NOT in the list, pass their X @handle or Substack URL in add_handles — they're resolved and added on the spot.

action: • "screen" (default) — the ranked candidate payload. Each candidate carries its reflected signal ("you follow · subscribe · bookmarked 12×"), pre_ticked / shown_by_default / is_person flags, distinct_signals, and its canonical_id (pass these to confirm). classify.ran=False means the kind classifier degraded open (LLM unavailable) — everyone stays person-eligible. • "confirm" — commit Oracle picks. canonical_ids = the ones the user kept (verbatim from screen); add_handles = raw X handles / Substack URLs to add (resolved-at- confirm). Idempotent. Returns {confirmed, unresolved, unknown, total_oracles} — surface unresolved (handles a lookup couldn't find) to the user. • "ingest" — deep-ingest confirmed Oracles into the atom-KB. For each (all confirmed, or just the canonical_ids you pass) run discovery — which mines their trusted blog/Substack for their OTHER profiles — then ingest each trusted personal profile as atoms attributed to the Oracle; an org link becomes an affiliation; an ambiguous one is left for review. Returns a per-source outcome report, with the windows actually pulled under lookback — read those back. • "candidates" — the OTHER half of the promotion decision. screen ranks people by how hard the USER vouched for them (distinct curation signals); this ranks the same people by what they actually write. Pass query to ask a topic question ("who writes about agent memory"); omit it to list who is there. Evidence comes from TWO stores and every row names which, in basis: · "probed" — a light sample of their own timeline (~25 posts). UNVETTED: nobody vouched for this text, only for the person being worth a look. Never cite it as knowledge-base content or quote it as fact. · "saved" — a post the USER saved, so it IS a knowledge-base atom and is citable (open it first). Usually exactly ONE post, and it is a positive example rather than a sample of their output: it matched partly BECAUSE the user kept it. Good evidence for "worth reading more of", weak evidence for "this is what they mostly write about". Scores are comparable only WITHIN a basis; the two are interleaved by rank, never added. Read back no_local_material — a candidate absent because nothing of theirs is stored looks exactly like one whose writing did not match, and those need opposite actions.

Is my stuff still current? You do not ask — screen answers it unasked, under oracle_freshness: per-Oracle, per-source last_pulled_at / hours_overdue / never_refreshed / breaker_open, worst first. If needs_attention is true, read its note out — that flag means either nothing has ever opted in to refreshing, or the cycle has stretched past twice its target. Both are silent failures otherwise.

A model_routing key, when present, lists models that are dead (no OpenRouter provider survives the deny-list — the stage using them cannot run) or fragile (one surviving provider — one withdrawal from dead). Read it out: it is absent whenever everything is routable, so its presence IS the news.

add_oracleA

Add a person to your knowledge base as an Oracle — a trusted source OPYT deep-ingests (their X timeline + Substack/blog archive + GitHub) and roots trust on. This is the atom-KB "add a person" — the only one: the old vault-era add_person tool, which wrote the legacy vault and couldn't admit a Substack/blog-rooted person, is retired.

SAFE, TWO-PHASE — always preview before you ingest: • FIRST call with confirm=False (the default) → a PREVIEW. It resolves reference and returns who they are (name, bio, followers) — or, if already known, their roster entry — and writes NOTHING. Read it back to the user to confirm it's the right person. If the reference doesn't resolve you get unresolved and there's nothing to confirm. • THEN, once the user agrees, call again with confirm=True → runs the full ingest and writes to the store. Never call confirm=True without showing the preview first — the guard is against ingesting the WRONG PERSON, which no later call undoes.

reference is polymorphic: an X @handle ("@karpathy"), a Substack/blog/site URL ("https://simonwillison.net"), or a canonical_id from oracle(action='screen') (to promote a below-the-cut candidate). To add someone by NAME, YOU resolve the name → their @handle or URL first (your own knowledge / a web search), then pass that — there is no name-search endpoint.

TWO windows, asked separately, because they answer to different constraints: • x_lookback — "6mo" (default) / "1yr" / "2yr". Hard-capped at 2 years whatever you pass. ASK the user before a confirm=True; the ~6-month default silently leaves most of a prolific account's history out. For someone ALREADY on the roster, "since_last" pulls only what is new since their last pull — the cheap top-up, roughly one request for a few days' gap. Reach for it when the user says "update" or "catch up", not "add". • web_lookback — "1yr" / "2yr" / "5yr" / "all" (default). A durable archive, so it already pulls everything. Pass it only to NARROW. A single shared window would be wrong for one of the two by construction — it either over-pulls X or truncates the archive. The result echoes the windows that actually ran (including the X clamp) under lookback — TELL the user how far back you pulled.

Reading the result — do not report ingested as if it were the whole story: • ingested counts sources that actually ingested; blocked counts sources where the host stopped us (Cloudflare, a truncated archive). A blocked source wrote nothing and is retried on the next run — say so plainly ("their Substack was blocked, nothing was saved, it'll retry") rather than implying it worked. errors is the "something is wrong, worth a look" bucket. • atoms_added vs dispatched: lookback/limit bound posts ATTEMPTED, not atoms saved, so these two diverge whenever posts are paywalled or fail the quality gate. If atoms_added is much smaller, tell the user the number they actually got. • producer_failed > 0 means posts vanished mid-run — mention it; nothing else records it.

The result may ask you to do something — check for followup. A confirm=True result carries one, and acting on it is how this tool finds a person's blog / YouTube / podcasts at all. OPYT's four probes are deterministic (X bio, Substack convention, GitHub, Semantic Scholar); the open-web step is YOURS, because you have web search and OPYT would otherwise pay a second model for a worse version of it. So: run the search it describes, then call this tool AGAIN with the same reference, confirm=True, and the URLs in extra_source_urls. Send everything plausible — you do NOT need to verify ownership, because the trust graph re-checks every URL and rejects what it cannot corroborate. A URL you drop is invisible; a URL it rejects lands in needs_review.

onboardA

Set up OPYT on this machine. Call this first on a fresh install, and any time setup looks incomplete. Idempotent and re-entrant — it recomputes where you are from disk on every call, so calling it twice never repeats a finished step.

It runs in up to three calls, because two steps wait on a human:

  1. OpenRouter — a browser tab opens; click Approve. Nothing to paste.

  2. Your browser session — reads your own logged-in X cookies, on this machine only. This is the ONLY way OPYT reads X: there is no API key and no third party. If no browser holds an X session, Opyt can open one for you to log into (guided_login=true). A couple of browsers still trip a native consent prompt (Full Disk Access for Safari, Keychain for Arc); when one applies, this tool warns you before it appears.

  3. Consent — one question, two commitments, and you may answer them separately.

Arguments are decisions, never credentials: • browser_profile — which Chrome profile holds your X session, when several are logged in. The answer is remembered in settings.yaml. • guided_login — accept the offer to have Opyt open a browser window you log into, when no browser on this machine has an X session. • consent — one of both | backlog | refresh | none. • skip_github — GitHub is optional and skipped by default.

Then call oracle to choose who to trust.

frontierA

The FRONTIER queue: recent artifacts (papers and repos — arXiv preprints, GitHub repos, and published literature across every discipline via OpenAlex) that the user's own standing queries pulled from the outside world, RANKED by how much they deserve attention right now. Read-only and free. Use it when the user asks what is new, what the frontier found, or what they have not looked at yet.

What the ranking is. Recomputed on every call from checkable facts, never stored: how many standing queries found the same artifact (the strongest signal — independent convergence), how many regions of the user's KB asked for those queries, how recent it is, how substantial it is for its kind (stars for a repo, abstract length for a paper — never compared across sources), minus how often it has already been shown.

One artifact is ONE card even when several sources staged it under different ids (the same preprint reached by DOI and by its /abs/ page, a paper deposited twice). Such a card carries duplicate_of naming the ids it stands for — it is a merge, so no signal is lost and total counts artifacts rather than rows.

Nothing is ever filtered out. Every term demotes; none excludes. Each candidate carries a state — "new", "seen" (shown before), "dismissed" (the user said stop), or stage 3's verdict — and a dismissed one still comes back, ranked last and labelled. Report a dismissed item as dismissed; do not hide it from the user and do not re-pitch it.

Calling it again advances the queue. This tool records what it showed you, and being shown demotes — so a second call surfaces the NEXT batch rather than re-pitching the same head. There is no cursor to pass. remaining > 0 means there are more below the cut; call again, or raise limit. Nothing gets stranded: an unseen candidate carries no penalty at all, so it outranks everything already shown.

There is no save step here, and you should not invent one. Admission into the knowledge base is Frontier stage 3's job and it is AUTONOMOUS — it runs on its own schedule, with no approval step and nothing for you to call. A candidate's state tells you what stage 3 has already decided: "materialized" means it is in the knowledge base, "rejected" means the fetch mechanically failed. "rejected" is NEVER a quality judgement — stage 3 has no judge. Report it as a fetch failure, never as "not good enough". Do not tell the user YOU added or kept anything, and do not offer to: nothing you do here admits an artifact, and as of 2026-08-13 there is no tool anywhere that admits one on request — the save_paper / save_repo vault writers were deleted. Stage 3 is the only admission path and it runs on its own.

Params: limit (default 20), dismiss (list of candidate_ids the user explicitly wants stopped — pass ONLY on an explicit request, never on inference), include_dismissed (default True; passing False hides them and reports how many it hid).

hopperA

SAVE something into the knowledge base — a link the user wants to KEEP. Hand it any URL and it works out what the thing is and routes it to the right ingester: a research paper, a GitHub repo, a Substack post, a plain article or blog post, or a single X post. This is the ONLY manual "keep this" path; there is no separate save-a-paper or save-a-repo tool.

Reach for this whenever the user says keep / save / add / remember / "put this in OPYT" about a link — including a link YOU just surfaced from a web search. It persists a link into the trusted corpus so the knowledge-base search tool can route to it later.

TWO-PHASE, and the first phase is free or near-free: • confirm=False (the default) → a PREVIEW. It reports which adapter the reference routes to, WHY it routed there, the atom id, whether the KB already has it, and what a confirm would spend. It NEVER writes. It fetches nothing for an article, paper, repo or Substack post — you can already read those yourself, so describe them to the user in your own words alongside the routing. The X exception: for an x.com status link the preview reads the post (~$0.00015) and returns a description. You cannot fetch x.com, and x:2086520133909168332 is unverifiable by a human — so read that description back before confirming; it is the only way the user can catch a wrong link. If unreadable comes back instead, the post is deleted / protected / keyless: say so and do NOT confirm. Paywalls are your job, not the preview's. This tool stores PUBLIC content only — a paywalled Substack post is skipped by the adapter and comes back "failed". It reads the same cookie-less public endpoint you do, so it cannot see past a wall you hit either. If the page you read was a subscriber teaser, say so BEFORE confirming instead of spending a round trip to be told no. • confirm=True → runs the ingest. This spends: a metered embedding always, plus a content gate for articles and ~$0.003 for an X post's thread. Show the preview first — a wrong route is SILENT (a paper filed as a blog post never errors, it just sits wrong).

Skip straight to confirm=True only when the user has already said "yes, save it" about THAT specific link.

already_present: true in a preview means a confirm is a no-op — say so and don't spend. Repeat calls are idempotent: an unchanged item is never re-fetched or re-embedded.

What it will not do — do not ask it to, and do not work around it: • It never adds a PERSON to the tracked roster. Saving someone's article does not start following them. add_oracle is the only way in, and it asks the user first. • It never writes vault notes. Atoms only. • It never guesses. A reference that is not a URL comes back unroutable with nothing written, rather than being filed somewhere plausible.

Every saved atom is stamped entry_mode='user-saved' — the same mark an X bookmark gets, because both mean the user personally saved it. That is load-bearing downstream: hand-saved items steer the Frontier's standing research queries.

sittingA

Read one topic of the user's knowledge base end to end, in publication order — as standing research queries, a briefing, a trajectory, or a search for what contradicts or is missing from it.

Reach for this when the user wants to know what their saved material actually SAYS about a subject over time — "what have I been collecting on agentic payments", "how has the thinking on X moved", "read everything I've saved about Y", "what's in my blind spots". It is the opposite of the search tool: search finds the few best-matching items, this assembles EVERY item on a topic and reads the whole set in date order. Search answers "where is it"; this answers "what happened".

Do not reach for it to look something up, to answer a factual question, or to find a specific post — that is the knowledge-base search tool, and it is free and instant. This assembles a large context and, on read, makes a model call (the other actions do not).

The five actions:

preview (FREE, the default) — name a topic and find out what is actually there. It grows the region and reports its size, the stretch of time it covers, how many people wrote it, a few of the items by name, and anything about its shape that would make a read disappointing. It calls no model. Costs one metered embedding for a typed phrase (a fraction of a cent) and nothing else. This is not a permission step. It is here because a phrase can resolve to four items or to two hundred and the user cannot tell which in advance — the size is a property of what they have saved, not of the words they typed. Skip it whenever the user has already said to go ahead. A preview alone queues nothing — consumption subscribes a region, construction does not. Nothing reads it, and nothing spends, until read or lens actually consumes it.

read (SPENDS) — reads the assembled region with a model. A topic too big for one sitting is read in PARTS, oldest stretch first; each read carries forward the claims every earlier part established and is asked to confirm, revise or refute them. Two lenses, pick with lens: - queries (default) — emits standing research queries from the material. Those then run on a schedule against papers, repos and datasets, catching what gets published NEXT in that thread. - claims — extracts 8-15 falsifiable claims the material actually makes, each one naming specifics (systems, numbers, dates), citing every atom that supports it, and stating what observation would prove it WRONG. Use this when the user wants to know what their saved material actually establishes, not what to watch next. Pass a sitting_id from a preview, or pass query to build and read in one step. The two lenses spend and read INDEPENDENTLY — reading a region for claims does not use up or block its queries read, and the reverse holds too.

render (FREE) — hand back a region that was already built, as the document a reader would see. Nothing is re-grown and nothing is re-read.

watchlist (FREE) — the standing questions currently being watched on the user's behalf, with how often each runs, how many times it has come up, and whether the user typed it or a read of their material proposed it. Pass a sitting_id or query to see one region's; pass neither for everything. SHOW THIS ONLY WHEN ASKED — "what am I watching", "show my watchlist", "did anything change". Never volunteer it at the start of a session or alongside unrelated work. add puts questions the user names onto the list; those never decay and are removed only by drop. drop retires a question EVERYWHERE — a question two regions both watch is retired for both, because the list is one list of questions, not a copy per region. Say so before dropping something the user did not name precisely.

lens (SPENDS only on material never lensed before) — hand back an instruction plus a document, and read them YOURSELF, right here in this conversation, to answer the user directly. This is how you answer a question ABOUT the material rather than generating queries against it. The document is NOT the region's raw text. A topic read across several sittings is summarised one stretch at a time, and what comes back is those summaries labelled with the dates they cover — so you are joining stretches, not re-reading everything. Each stretch is summarised once ever, so asking the same lens again is free, and asking a DIFFERENT question of the same lens is free too. Only material that has never been lensed this way costs anything. Pass lens to pick which reading: - briefing — what this material actually says, as knowledge, not a table of contents. - trajectory — how the thinking on this topic MOVED over time: what changed, reversed, or got abandoned. - disconfirmation — what in this material would UNDERMINE a belief. Pass claim with the belief being tested; without one, it red-teams the material's own apparent thesis. - gaps — answer a question using only this material, and if nothing here answers it, the CLOSEST it comes and why that falls short (never a bare "nothing here"). Pass claim as the question. - sprouts — everything no sitting has ever read: true orphans, unread regions, fracture leftovers. This is what "what's in my blind spots" means. Needs no sitting_id, query, or atom_ids — it is not about one topic. Like read, pass a sitting_id from a preview or a query/atom_ids to build one in the same call (sprouts needs neither). The answer YOU give is never written anywhere — no queries, no table, no record of it — because it is about the topic as it stands today and would be wrong the moment anything is added. This is a conversation, not a rail.

What comes back from a read, lens queries: a consensus — how the conversation moved, what reversed, what is unresolved — plus the queries it emitted. Show the user the consensus. It is the part written for a human.

What comes back from a read, lens claims: a claims list, each one {claim, falsified_by, atom_ids}. Show the user the claims themselves — falsified_by is what lets them decide whether to believe one, so surface it alongside the claim rather than dropping it.

What comes back from a lens: instruction and document. Read document following instruction and write the answer yourself — there is no second call to make, and nothing here reads the document for you.

Read the warnings in a preview back to the user. They say when a region is a poor fit for the question — a region spanning three days has no arc to find, a region that is 85% one author generates queries pointing back at that author's own work. Pass the lens you intend to use to preview and the warnings are specific to it (a short span breaks trajectory and barely touches briefing). They are advisory: nothing here refuses to read, because whether the region is right depends on what the user is asking and only they know that.

A region is read once per lens (by read). A second read of the same sitting_id with the SAME lens is refused as already read — it would be the same input for the same money. The two read lenses do not share this guard: a region read for queries can still be read for claims, and the reverse. A region is re-read (same lens) when it has GAINED enough new material to be worth redoing, and the rail decides that on its own; to force it, preview the same phrase again, which grows a fresh region over the corpus as it is NOW. lens (the action) has no such limit — each stretch is summarised once and reused after that, so reading the same region's briefing twice costs nothing the second time.

shareA

SHARE this knowledge base with someone — returns a link to send them.

Reach for this when the user says share my KB / send my knowledge base to X / let X search what I've read. It hands back one link. The person who opens it can install Opyt if they need to, and after that their assistant can search this corpus, with every result attributed here.

TWO-PHASE, and the preview is the consent step, so run it first: • confirm=False (the default) → a PREVIEW. It publishes nothing, mints nothing and hands nobody anything; on an install that has already shared it asks the service whether an export has landed, and that is the only thing it sends. It reports WHAT would be shared — how many atoms, from which sources and authors, over what date span — and what sharing means. READ THAT BACK to the user before confirming. Sharing is the WHOLE knowledge base, standing, not a slice and not a snapshot: there is no way to share part of it, anyone given a link keeps access until it is revoked, and the copy refreshes itself when people read it. • confirm=True → registers this install with the service if it is not registered yet, starts the first upload, mints a one-time invite, and returns the link.

Skip straight to confirm=True only when the user has already said yes to sharing THIS knowledge base, having been told what is in it.

The first share uploads the whole corpus, which runs in the background and usually takes a minute or two. The link works immediately: a reader who accepts inside that window is registered normally, and it is their first SEARCH that comes back saying the copy is still arriving. The next one works. Later shares are instant.

WHAT THIS IS NOT. It does not publish anything on the open web — the service serves only people holding a link, one reader token per link, revocable. It does not send anything to the person for you: hand the user the link and let them send it.

acceptA

ACCEPT an invitation to search somebody else's knowledge base.

Reach for this the moment the user pastes an Opyt invite link or a grant code, or says someone shared their knowledge base with them. One call and it is done: from then on the search / open / aggregate tools take kb='<name>' and read that person's corpus, with every result attributed to them.

SINGLE-PHASE on purpose — there is no preview. A grant code buys exactly one reader token and then dies, so checking it would spend it, and pasting an invite is already the yes.

Pass whatever the user gave you: the whole link, the fragment, or the bare code. The code is found inside any of them.

unshareA

STOP sharing — either with ONE person, or with everybody. reader picks which.

READ THIS BEFORE CALLING. The two scopes are not the same act and only one of them is expensive to undo: • reader="Leo" → Leo loses access. Everyone else keeps reading, the served copy stays, and you can invite Leo again with share whenever you like. • reader omitted → EVERY reader is cut off AND the served copy is deleted. Every invite ever sent stops working, so sharing again means re-inviting everyone by hand.

So when the user names a person — "stop sharing with Leo", "cut Leo off", "revoke Leo" — reader is REQUIRED. Omitting it there does something much larger than what was asked, and the preview is where you catch that: it always says which of the two scopes it is about, in its first sentence.

Reach for the whole-knowledge-base form when the user says stop sharing / unshare / take my knowledge base down / revoke everyone. That form is one act and not two, because a person who says "stop sharing my KB" means both halves and will not say it twice.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/maimond123/Opyt'

If you have feedback or need assistance with the MCP directory API, please join our Discord server