Opyt
Allows pulling full-text arXiv papers from authors' archives into the knowledge base, and lets standing questions run against arXiv to stage new findings.
Allows ingesting GitHub repositories and READMEs from confirmed authors, and lets standing questions run against GitHub to discover relevant new work.
Allows importing Substack subscriptions and saved posts as full-text searchable content, and pulling authors' Substack archives into the knowledge base.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OpytSearch my knowledge base for posts about AI safety from people I follow."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Opyt
Your attention is the context your AI is missing.
Website · Docs · Use cases · Compare
A knowledge base that grows from your attention across the platforms you already use, served to your AI client over MCP.
Every bookmark, follow and subscription was you deciding whose thinking is worth your time. Opyt pulls the full public archive of those people from X, Substack, GitHub, their own blogs and arXiv, and turns it into one SQLite file your assistant can search, read and count over. There is no new app and no chat UI. Your client calls the tools; your client's model does the reasoning, on the subscription you already pay for.
If it is useful to you, star it. That is how other people find it.
Why Opyt
Nobody you did not choose. Candidates are ranked off your own follows, Lists, subscriptions, bookmarks and likes. There is no recommendation model and no trending list. Zero hits is an answer: nobody you trust has touched the claim.
Your backlog is searchable on the first run. Everything you saved before today comes in during setup. You are not starting from an empty store.
It grows on the days you never open it. Reading a topic end to end emits standing questions. Those questions keep running against arXiv, GitHub and OpenAlex, and stage what they find for you to review when you feel like it.
Full archives, not the three posts you bookmarked. Confirm one person and Opyt finds their other platforms, verifies them, and pulls years of posts, repos and essays in full text.
Free of new subscriptions. Reading and reasoning run on the AI client you already have. One metered key covers classification and embeddings, on cheap open models.
One local SQLite file. Everything lives in
~/.opyt/opyt.db. No vault of markdown, no dashboard, no daemon, no account.Any MCP client. Claude Code, Claude Desktop, Cursor, Windsurf, Codex, or anything else that speaks MCP over stdio.
MIT licensed. Read the source.
Related MCP server: X Archive Daemon
Quick start
1. Install
# once per machine, if you do not already have uv
curl -LsSf https://astral.sh/uv/install.sh | sh
claude mcp add Opyt -- uvx --from opyt==0.1.0a4 opyt-mcpWithout a terminal: download opyt-0.1.0a4.mcpb, double-click it, and review the install screen Desktop shows you. The bundle carries its own Python and every package it needs, so it wants no uv, makes no network call at launch, and starts in about eleven seconds. That is why it is a 198 MB download.
Or from a terminal:
curl -LsSf https://astral.sh/uv/install.sh | sh
# absolute path: uv edited your shell profile, not this shell
~/.local/bin/uvx --from opyt==0.1.0a4 opyt-install-client --claude-desktopcurl -LsSf https://astral.sh/uv/install.sh | sh
~/.local/bin/uvx --from opyt==0.1.0a4 opyt-install-client --cursorThis merges Opyt into ~/.cursor/mcp.json beside whatever servers are already there, and copies the old file aside first. Running it twice changes nothing, and --uninstall removes the entry and leaves the rest.
curl -LsSf https://astral.sh/uv/install.sh | sh
~/.local/bin/uvx --from opyt==0.1.0a4 opyt-install-client --windsurfMerges into ~/.codeium/windsurf/mcp_config.json, backing up the old file first.
Install uv, run which uvx to get its absolute path, and add this to whatever the client calls its MCP config:
{
"mcpServers": {
"Opyt": {
"command": "/Users/you/.local/bin/uvx",
"args": ["--from", "opyt==0.1.0a4", "opyt-mcp"]
}
}
}Use the absolute path, not a bare uvx. A desktop app spawns its servers with a minimal PATH that never sources your shell profile, so the directory uv's installer added to that profile does not exist as far as the process is concerned.
Paste this into the client you want Opyt in:
Install the Opyt MCP server for this client, from useopyt.com/docs.html.
0.1.0a4is a pre-release, so the version is pinned explicitly. Drop the pin once a stable release exists.Opyt does not run at claude.ai. Your client starts Opyt as a process on your own machine and pipes to it, and a browser tab cannot start a process on your machine. Claude Desktop is the same account and the same models, and takes one double-click.
2. Say onboard
Restart your client. Opyt appears as twelve tools. Then:
you › onboard
⚙ onboard()
x bookmarks 691 saved posts, full text
x likes 99 liked authors
x follows 492 accounts
x lists 6 lists
substack 19 subscriptions · 12 saved posts, full text
read from your logged-in browser · no API key, no password
claude › Everything you saved is in. 703 posts are now searchable,
and Opyt knows the 1,193 accounts they came from.A browser tab opens for the one key it needs and you click Approve. Nothing is ever pasted into chat. It then looks for a browser already signed into x.com, which is how Opyt reads X, so there is no X key to get.
3. Say oracle
you › oracle
⚙ oracle()
1 @jasonfurman you follow · you subscribe · saved 12×
2 @drvolts you follow · saved 8×
3 @karpathy liked 4×Confirm the ones you want and Opyt pulls each person's whole archive: their X posts, their GitHub repos and READMEs, their essays on their own site, going back years.
The tools
Twelve tools. Every argument, its type and default, what each call returns and what it costs are in the full reference. The docstring on each tool in mcp_server/ is the authoritative version of the same thing.
Tool | Effect | What it does |
writes · re-entrant | Acquires the one key, reads your browser session, takes consent, runs the first import. | |
writes · spends | Screens the people your own signals already point at, confirms them, ingests them. | |
| two-phase · spends | Adds one person by handle or URL, finds everywhere they publish, pulls the archive. |
read-only | Ranked retrieval over the store, filterable by tag, kind, source, author and date. | |
read-only · free | The full stored text of one atom, plus its live source URL. | |
read-only · free | Counts across the whole store rather than a sample: by topic, author, kind, date. | |
writes · spends | Reads every atom on one topic end to end, in publication order, through a lens. | |
writes · free | The ranked review queue of what your standing questions found. | |
two-phase · spends | Takes any URL, works out what it is, and saves it as an atom. | |
two-phase · publishes | Shows you what is in your store, then hands you a link that lets someone search it. | |
single-phase · writes | Registers a knowledge base somebody shared with you, from the link they sent. | |
two-phase · deletes | Cuts off one reader, or every reader plus the served copy. |
The server owns only the last segment of each name. A client that namespaces adds its own prefix, so search reaches Claude Code as mcp__Opyt__search. All twelve return a JSON object.
search, open and aggregate are the LLM-free retrieval core: they return data and your host model does the reasoning. They are also the only three that take kb=, which reads a knowledge base someone shared with you.
Examples
Find something
you › Are tariff price effects one-off or recurring?
⚙ search("are tariff price effects one-off or recurring")
claude › Three of your own sources speak to this. The closest is a post
you bookmarked yourself in June:
0.81 @jasonfurman x post 2026-06-11 you bookmarked this
0.74 @m_c_klein essay 2026-05-04 from an author you confirmed
0.71 @nicktimiraos x post 2026-04-22search is a router, not an answer. Each hit is a card plus a pointer, and open(atom_id) returns the full stored text before you assert what a source says. Ranking is pure relevance: a BM25 arm and a semantic arm fused by rank, with no trust or popularity re-rank on top.
Read a topic end to end
you › Read everything I've got on GLP-1 drugs and muscle loss,
and lay out what it actually claims.
⚙ sitting(action="read", lens="claims")
claude › Eleven claims came back, each paired with what would break it
and each citing the documents it came from. The first three:
claim what would disprove it
The headline number hides what came Body-composition scans published
off: fat and muscle go together. beside the headline figure.
A 28% loss is not comparable to a 15% One measurement standard adopted
one unless both measured lean mass across the trials.
the same way.
At population scale the binding Oral dosing flattening the
constraint is people staying on the discontinuation curve.
drug, not how well it works.A sitting is the complement to a search. Search returns the best few; a sitting walks every document on the topic in publication order, so a position that changed over time reads as a change instead of a contradiction. Five lenses read the same material differently:
Lens | What it returns |
| Every claim, each paired with what would disprove it. |
| What holds, what is still open, and where your authors converge. |
| The phases the thinking moved through, in publication order. |
| The case against a claim you name, from your own sources only. |
| Whether your material answers a question, and the nearest misses if not. |
Every sitting also emits standing questions, which is what feeds the next section.
Catch up on what arrived
Tuesday
you › Read everything I've saved on data-center grid costs.
codex › Three questions came out of that read and they are still
running. You typed none of them.
Friday · you ran nothing in between
you › Anything new?
⚙ frontier()
codex › Six things came in since Tuesday, ranked by how many of your
own questions reached each one:
1 paper Who Pays for the Load? Data-Center Demand and Retail Rates
all 3 questions · 2 of your topics
2 repo PyPSA/pypsa-eur 1 question · 1.2k stars
3 paper Interconnection Queue Times by Region, 2019 to 2026
1 question
+ 3 more staged, ranked the same wayThe queue sits on your machine and waits. Opyt says at the start of a session that something is there, and never pushes the list itself into context uninvited.
Count what you actually read
you › What have I been reading most since March?
⚙ aggregate(date_from="2026-03")
cursor › Tariffs and inflation is your biggest topic since March,
with grid and data centers close behind:
tariffs & inflation 96
grid & data centers 84
interconnection queues 53
GLP-1 trials 41This is a count over everything you saved, in one pass, not an impression from what you remember saving.
Keep something
you › Save this: arxiv.org/abs/2608.01144
⚙ hopper("arxiv.org/abs/2608.01144")
routed → paper ingester
preview: "Marginal Cost Allocation for Large Flexible Loads" · 22 pages · confirm?
you › yes
claude › Saved in full text, searchable beside everything else.One sentence. No folders, no tags, no deciding where it belongs.
What it reads
Source | What comes in | Access |
X | bookmarks · likes · follows · Lists | your browser session |
Substack | subscriptions · saved posts, full text | your browser session |
GitHub | a tracked person's repos and READMEs | public |
Blogs | a tracked person's whole archive, found by feed or sitemap | public |
arXiv · OpenAlex | papers matching your standing questions | public |
Any URL | a paper, post, article or repo you hand it, saved in full | you |
posts and articles from the people you track | coming soon | |
Aggregators | Hacker News · Hugging Face · npm · crates.io · Stack Overflow · Product Hunt · Homebrew | coming soon |
Funding | company and round data, asked by name | coming soon |
X and Substack are read from the browser session you are already signed into, on this machine only. There is no API key and no password.
How it works
Content enters the store as atoms, Opyt's unit of stored content, one per post, repo or paper. Two independent paths put them there.
Track a person. add_oracle (or oracle to browse candidates first) takes a handle or URL. Opyt auto-detects which of X, Substack, a personal blog and GitHub that person actually publishes to, then pulls their full archive from each. Candidate ranking is lexicographic: person-level acts such as a follow, a subscription or a List outrank content-level ones such as a bookmark or a like. A background rail keeps every tracked person's sources current without you asking again.
Let Frontier watch your standing topics. Frontier is a passive discovery rail. It runs the standing questions your sittings emitted against arXiv, GitHub and OpenAlex on a schedule, judges what it finds against your topics, and stages the good ones. You read the queue with frontier when you want to.
Everything lands in one SQLite database at ~/.opyt/opyt.db: atoms, their chunks, a full-text index, and the entity and trust edges between tracked people. The MCP server is the only interface, and it creates its own store on first use.
Several background rails also spawn per session, refreshing tracked people's sources, running Frontier's stages, pulling new X bookmarks. Each is independently gated, so a stalled or failing rail never blocks the others or the server itself.
What it costs
Opyt is free and MIT-licensed. The expensive part is the reading and reasoning, and that runs on the AI subscription you already pay for.
For | Cost | |
Your AI client | every question, every answer, all the reasoning | your existing subscription |
OpenRouter | sorting and extracting what comes in, on a cheap open model, plus the embeddings search ranks with | pay-as-you-go credits |
X | posts, timelines, profiles, threads | free, through your own browser |
Everything else | papers, blogs, GitHub, Substack, any URL you hand it | free |
opyt-keys --list shows which credentials are set, never their values. .env.example documents each one.
Share a knowledge base
search, open and aggregate take a kb= argument that reads someone else's store instead of your own.
you › I need to pick an eval setup for retrieval.
Has anyone already been through this?
⚙ search("evaluating retrieval quality", kb="ana")
⚙ search("evaluating retrieval quality", kb="ravi")
claude › Two of them have. Ana read the framework and its repo in March,
and Ravi has the benchmark it is usually compared against.
Nothing on this in yours.Getting there is two sentences and no terminal. On your side:
you › share my knowledge base with Leo.
⚙ share()
claude › 2,876 atoms, mostly papers and X posts, from March 2024 to yesterday.
The top authors are @karpathy, @hypersoren and @swyx. Sharing sends
all of it, it lasts until you revoke it, and it stays current on its
own. Go ahead?
you › yes
⚙ share(confirm=True, as_name="David", for_whom="Leo")
claude › Send Leo this: https://useopyt.com/invite#Kq7f...On theirs:
you › someone sent me this: https://useopyt.com/invite#Kq7f...
⚙ accept("https://useopyt.com/invite#Kq7f...")
claude › Registered. Ask me anything and I can search David's reading too,
with kb="David".Publishing is self-service: no invitation and no account. The served copy refreshes itself when somebody has read it since your last push and your store has changed since then, so an unchanged store never re-uploads and a knowledge base nobody reads costs nothing. unshare(reader="Leo") cuts off one person and leaves the copy serving; unshare() cuts off everyone and deletes it.
Under it, a push is a full replace: an export is a projection of a store, not a log of changes to one, so the newest upload wins. opyt-push and opyt-redeem <url> <code> are the same two acts from a terminal, kept as operator rails.
Design principles
Three constraints hold across the whole codebase, enforced by an AST-based guard (scripts/guard.py) that runs in pre-commit.
Distributable. Nothing may assume a specific machine. Paths are derived at runtime from
sys.executableandPath(__file__), never hardcoded.Client-agnostic. The core and every knowledge tool run on any MCP client, not just Claude Code. Claude-Code-specific behavior is opt-in and never load-bearing.
Fail-safe. A missing optional input degrades to an empty result, not a crash. A failed external call skips cleanly. It never writes partial state and never marks unfinished work done.
Contributing
The install path above is for using Opyt. To work on it:
git clone https://github.com/maimond123/Opyt.git
cd Opyt
bash scripts/setup.sh # venv, editable install, git hooks
pytest tests/setup.sh assumes a python3 that already satisfies requires-python >= 3.10 and does not check. A stock macOS python3 is 3.9.6, as is the one xcode-select --install delivers. Read the header of that script before running it.
Issues and pull requests are welcome at github.com/maimond123/Opyt.
License
MIT. See LICENSE.
Built with ❤️ in New Jersey
Available Tools
12 toolsacceptAcceptA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | OPTIONAL — what `kb=` should call this knowledge base locally. Leave it out and the owner's own name is used. Pass one only if the user asks for a specific name. | |
| invite | Yes | the invite link or grant code. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so well. It discloses the single-phase no-preview nature, the one-time token consumption ('a grant code buys exactly one reader token and then dies'), and the post-condition that accepted KBs become available to search/open/aggregate with kb='<name>'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and trigger, and every subsequent sentence contributes operational detail: the no-preview principle, token irreversibility, and input flexibility. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description fully covers when to call, what input to pass, what happens after acceptance, and the irreversible side effect. Since an output schema exists, return-value details are not required, and there are no meaningful gaps for an agent deciding to invoke this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds useful meaning beyond the schema by explaining that the invite parameter accepts 'the whole link, the fragment, or the bare code,' and clarifies the optional name parameter is just a local alias used with kb=.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('ACCEPT'), resource ('an invitation to search somebody else's knowledge base'), and the concrete trigger forms ('Opyt invite link or grant code'). It also names downstream tools (search/open/aggregate) that rely on the accepted kb, distinguishing this from siblings like share or unshare.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit, actionable trigger: '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.' It clearly describes the context for use, though it does not explicitly name alternatives to exclude.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_oracleAdd 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.
| Name | Required | Description | Default |
|---|---|---|---|
| force | No | re-run DISCOVERY from scratch, ignoring the cached result. Discovery is cached for a person whose X profile is unchanged, because identity is stable while their CONTENT is not — a normal re-add should not re-derive who they are. Pass this when the user says their sources look wrong or incomplete and re-adding did not help. The cache key is their display name plus declared links, so a source they created after the last run leaves it identical and only this gets past it. Costs a full probe walk; do not pass it by default. | |
| confirm | No | False (default) = preview only, no writes; True = run the ingest. | |
| reference | Yes | an X @handle, a Substack/blog URL, or a canonical_id. | |
| x_lookback | No | window for the X timeline — "6mo" | "1yr" | "2yr" (default 6mo). | |
| web_lookback | No | window for the Substack/blog archive — "1yr" | "2yr" | "5yr" | "all" (default all). Narrows only. | |
| extra_source_urls | No | home/channel pages YOU found by web search (see `followup`). They enter as low-confidence candidates and are trust-checked like any other source — never trusted on your say-so. Individual posts/videos are dropped; send homes. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It reveals the safe two-phase write behavior, the 2-year hard cap on x_lookback, the fact that blocked sources write nothing and are retried later, the divergence between atoms_added and dispatched, and the trust-re-checking of extra_source_urls. This goes well beyond what the schema alone conveys.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with headers and bullets, and it front-loads purpose and safety workflow. Each section addresses a distinct operational concern—preview/confirm, lookback windows, result interpretation, and followup—so the length is proportional to the tool's complexity rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a six-parameter mutation tool with no annotations, the description covers the entire call lifecycle: reference resolution, preview/confirm behavior, lookback semantics, result-field interpretation, and the followup/extra_source_urls loop. The output schema supplies the raw return shape, and nothing an agent needs to invoke this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds significant meaning: it explains reference's polymorphic forms with concrete examples, notes that name lookup must be resolved externally, introduces the since_last x_lookback value, warns about the hard cap, and clarifies that extra_source_urls are low-confidence candidates that must be home pages, not individual posts. This substantially enhances the parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names a specific verb and resource: add a person to the knowledge base as an Oracle, with the effect of deep-ingesting their X timeline, Substack/blog archive, and GitHub. It also explicitly distinguishes itself from the retired add_person tool and claims to be the only atom-KB add-person tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit call pattern: confirm=False preview first, then confirm=True only after user agreement, and says never to call confirm=True without showing the preview. It also explains when to use the since_last window ('update'/'catch up', not 'add'), when to narrow web_lookback, and how to act on the followup, leaving no ambiguity about when and how to use the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
aggregateAggregateA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| kb | No | Summarize SOMEONE ELSE'S knowledge base instead of your own. Omit for yours. `trusted_atoms` then counts atoms whose author THAT owner confirmed, not you. | |
| tags | No | ||
| who_id | No | ||
| date_to | No | Latest atom date, INCLUSIVE. Same formats, widening the other way (date_to="2026" is 2026-12-31). | |
| date_from | No | Earliest atom date, INCLUSIVE — "2026", "2026-05" or "2026-05-11"; a partial widens to its natural edge (date_from="2026" is 2026-01-01). Any other shape RAISES rather than being ignored. | |
| what_kind | No | ||
| source_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral transparency. It explicitly states 'safe to read without opening' and describes itself as 'mechanical,' indicating a read-only, side-effect-free operation. It also provides a key constraint (takes IDs, not handles) without needing to infer from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately long but every sentence adds value: it explains the output, usage workflow, scope options, and the ID/handle distinction. It avoids redundancy and is structured logically, though it could be slightly tightened without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the tool's purpose, output nature (counts, distributions, recent descriptions), usage workflow, and a critical parameter constraint. It does not provide an explicit example or error handling, but it is complete enough for a typical agent to use the tool correctly given the schema annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has descriptions for only 3 of 7 parameters (43% coverage). The tool description adds minimal clarification—it mentions filterable fields and notes that who_id expects IDs—but leaves tags, what_kind, and source_type without semantic explanation. Parameter meaning is only partially clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: it provides a state-of-play skeleton with counts and distributions over a scoped knowledge base. It distinguishes itself from siblings by describing its role as a precursor to open(), making its unique function unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use this tool—for drafting a dossier or checking 'what do I have on X'—and when to use search (for handles) and open (for details). It also explains that scope is optional and how to filter, giving clear usage guidance relative to alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
frontierFrontierA
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).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| dismiss | No | ||
| include_dismissed | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden and does so thoroughly. It discloses that the ranking is recomputed and never stored, that artifacts are merged via duplicate_of, that nothing is filtered out, that calling again advances the queue, and the exact meaning of states like dismissed, materialized, and rejected.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized and front-loads purpose before diving into ranking, states, and params. However, the no-save/stage-3 warning is repeated across two separate paragraphs and includes a date-stamped tool-deletion detail that is somewhat redundant, making it slightly longer than necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that an output schema exists, the description need not spell out return shapes; it covers all calling-relevant context: ranking inputs, merge semantics, state meanings, pagination via remaining, the absence of a save step, and parameter constraints. An agent has enough information to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only provides names, types, and defaults, so the description adds essential meaning. It explains limit through the remaining/cut mechanics, dismiss as an explicit-only list of candidate_ids, and include_dismissed as a hide-and-report option. This fully compensates for the 0% schema description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names a specific resource ('FRONTIER queue') and defines exactly what it returns: recent papers/repos pulled by the user's standing queries, ranked by attention-worthiness. It also states read-only/free and provides concrete user-intent triggers. It clearly differentiates itself from save/admission mechanisms even though it does not name sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says when to use the tool: when the user asks what is new, what the frontier found, or what they have not looked at yet. It also gives strong when-not guidance: pass dismiss only on explicit request, do not invent a save step, do not claim admission, and report rejected items as fetch failures rather than quality judgments.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hopperHopperA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | No | False (default) = preview only, no fetch and no writes; True = run the ingest. | |
| kind_hint | No | OPTIONAL, and only consulted when the URL host matches nothing known — a recognized host always wins, because the host is a fact and your read is not. In practice there is ONE case worth passing it for: pass "substack" when you can see the page is a Substack post on a custom domain (a `/p/{slug}` path, a subscribe widget) rather than a `*.substack.com` URL. Nothing can detect that without fetching, and it matters — routed as a plain article the post gets a different atom id and will never dedupe against the same post saved from a bookmark. The other values ("paper", "github", "x") cannot override anything: those adapters check the host themselves and refuse a URL that is not theirs. | |
| reference | Yes | the URL to save — an article, paper (arXiv / DOI / .pdf), GitHub repo, Substack post, or x.com status link. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so thoroughly: two-phase preview/confirm behavior, costs, the X-post exception and unreadable handling, paywall limitations, silent wrong-route risk, idempotency, already_present no-op behavior, and the entry_mode stamp. This goes well beyond a generic mutation warning.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but densely structured and front-loaded: purpose first, usage second, then phase behavior, exclusions, and downstream context. Each section adds non-redundant operational detail, so the length is justified rather than bloated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with no annotations, the description covers triggers, routing, costs, failure modes, idempotency, exclusions, and downstream effects. The output schema handles return-value shape, so nothing essential is missing for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds meaning beyond the schema: confirm's default preview behavior, kind_hint's limited override role and the substack custom-domain case, and the exact URL types reference accepts. It clarifies when each parameter matters and what happens if misused.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'SAVE something into the knowledge base — a link the user wants to KEEP.' It names the supported reference types and explicitly calls itself 'the ONLY manual keep this path,' distinguishing it from siblings like add_oracle and search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit trigger phrases ('keep / save / add / remember / put this in OPYT'), covers links surfaced from web search, and states when not to use it: never for people (use add_oracle), never for vault notes, never for non-URLs. It also instructs when to skip straight to confirm=True.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
onboardOnboardA
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:
OpenRouter — a browser tab opens; click Approve. Nothing to paste.
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.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.
| Name | Required | Description | Default |
|---|---|---|---|
| consent | No | ||
| skip_github | No | ||
| guided_login | No | ||
| browser_profile | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses many behaviors: it is 'Idempotent and re-entrant', involves human interaction in steps, reads 'X cookies', opens a browser, prompts for consent, and warns about native consent prompts. It explicitly states 'when one applies, this tool warns you before it appears.' This is transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with numbered steps and bullet points, making it scannable. It is front-loaded with the core purpose. However, it is somewhat verbose with detailed explanations about browser quirks, but that serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the tool's purpose, usage sequence, parameter meanings, and notes a follow-up action ('Then call oracle'). It also explains the idempotent nature and human interaction requirements. Given the complexity, it is complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All four parameters are explained in the description: browser_profile, guided_login, consent, and skip_github. For example, it says 'browser_profile — which Chrome profile holds your X session' and lists consent options. Since the schema has no descriptions, this fully compensates.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Set up' and the resource 'OPYT' on this machine. It also specifies when to call it: 'first on a fresh install' and 'any time setup looks incomplete.' This gives a precise purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides usage context by saying 'Call this first' and then 'Then call oracle to choose who to trust,' establishing a sequence. It also mentions optional parameters like skip_github. However, it doesn't explicitly describe alternatives among sibling tools, but the guidance is sufficient for a setup tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openOpenA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| kb | No | ||
| atom_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even without annotations, the description fully discloses behavior: it returns specific fields, handles unknown IDs with an error, and explains how `raw` completeness relates to `body_state`. It also clarifies the meaning of 'complete', 'partial', and 'absent', and warns against treating partial content as the full article.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear paragraphs, front-loading the core purpose and then explaining return fields, body-state semantics, and the `kb` scoping rule. Each paragraph adds necessary information without redundancy, and the length is justified by the complexity of the behavior described.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of annotations and the presence of an output schema (not shown), the description is remarkably complete. It covers the returned fields, error behavior, the meaning of `body_state` values, the role of `payload`, and the importance of `kb`. An agent has enough context to call this tool correctly and interpret its results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description provides crucial semantics for `kb`: it must be the value from the hit card, and it scopes the atom ID to one knowledge base. It also explains the consequence of opening a foreign ID without `kb`. While `atom_id` is not explicitly defined, its meaning is evident from the tool's purpose and the schema's required field.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: follow an atom's pointer and return the raw snapshot text and source URL. It also distinguishes this tool from `search` by explaining that `search` only routes the agent to the atom, while this tool provides the actual content to reason from.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance on when to call this tool: before citing or asserting anything an atom says. It also explains the pre-citation check, instructing the agent to attribute partial content and send the reader to the source URL, and warns about the `kb` parameter needing to match the hit card carried.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
oracleOracleA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| floor | No | screen — minimum candidates shown by default before "see all" (default 15). | |
| force | No | ingest — the "ignore what we decided last time" override, and it now means TWO things. (1) Ingest a footprint source even when the single-author gate would skip or park it (for a solo publication the classifier mislabels). (2) Re-run DISCOVERY from scratch, ignoring the trust cache — reach for this when a person's sources look wrong or incomplete and their X profile has not changed, since the cache key only invalidates on a display-name or declared-link change. A source they created after the last run, or a fix on our side, leaves that key identical. | |
| query | No | candidates — a topic question to rank people by ("agent memory", "biotech funding"). Omit for "who has been sampled". | |
| top_n | No | candidates — how many people to return (default 30). NOT a screen knob: `screen` classifies every candidate and returns all of them. | |
| action | No | "screen" | "candidates" | "confirm" | "ingest". | screen |
| x_lookback | No | ingest — how far back to pull each Oracle's X timeline: "6mo" (the default), "1yr", "2yr". Hard-capped at 2 years whatever you pass. Ask the user — not for cost (the pull is free), but because the default truncates. "since_last" is the cheap top-up: pull only what has appeared since this Oracle was last pulled. Use it whenever the user wants someone brought current rather than re-ingested — a 5-day gap costs one request instead of ~19. It errors rather than guessing if the Oracle has never been pulled. | |
| add_handles | No | confirm — raw X @handles / Substack URLs to add beyond the ranked list. | |
| min_signals | No | candidates — only people with at least this many distinct curation signals (default 1 = everyone in the list). | |
| web_lookback | No | ingest — how far back to pull the Substack/blog archive: "1yr", "2yr", "5yr", "all" (the default). Only narrows; omit unless the user asks. | |
| canonical_ids | No | confirm — the kept candidates' canonical_ids; ingest — which confirmed Oracles to ingest (omit = all confirmed — usually NOT what you want for a top-up, so name the person). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so this description carries the full burden of behavioral disclosure. It is exceptionally transparent: it reveals the default lookback truncation issue, notes that X reads are free (so cost is not the reason to ask), explains idempotency of confirm, describes per-action returns including 'unresolved' items, discusses 'model_routing' semantics, and highlights silent failure conditions like breaker_open. This goes far beyond a basic summary.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it is well-structured with clear sections (FLOW, action breakdown, freshness, model_routing). Every paragraph adds necessary operational detail. The length is justified by the tool's complexity (four actions, many trap conditions). A slight deduction because the sheer length may initially overwhelm an agent, and some parenthetical asides could be tightened without loss.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and the absence of annotations, the description covers everything an agent needs to invoke it correctly: exact action semantics, expected return payloads, decision guidance for ambiguous cases (like 'no_local_material'), and how to surface critical status flags. The presence of an output schema is acknowledged, and the description complements it by explaining the meaning of key fields rather than duplicating schema output details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
While the input schema has 100% description coverage, the tool description adds meaningful semantic context beyond each parameter's own description. For example, it explains why 'x_lookback' must be asked (completeness, not cost), clarifies 'force' now means two things, and warns that 'canonical_ids' omission in ingest usually is not what the user wants for a top-up. These operational nuances help an agent select and use parameters correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-resource pair: 'Choose who to trust' and clearly explains this tool converts curated sources into Oracles for deep ingestion. It explicitly distinguishes itself from the 'onboard' sibling with 'NOT the setup tool', stating what this tool is versus what it is not. The multiple action modes (screen, confirm, ingest, candidates) further clarify scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: 'Reach for this when the user asks who to trust, wants to see or change their people, or asks whether their sources are current.' It also names the sibling alternative ('onboard') and explains the division of responsibility. Within the tool, it spells out the required sequence of actions and when to use optional parameters like 'add_handles' and 'web_lookback'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchSearchA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| k | No | Max atoms to return (default 8). `trace.cutoff` shows the score at the boundary, so you can tell whether raising it would have helped. | |
| kb | No | Read SOMEONE ELSE'S knowledge base instead of your own. Omit for yours (the normal case). A name here must be one this install has registered; an unknown one returns no hits and a notice naming the ones that exist. Every hit carries the `kb` it came from — "me" for your own — and an atom id means nothing outside its own store, so pass that same value back to `open(atom_id, kb=...)`. Attribute anything you repeat from a foreign hit to that knowledge base, not to the user. | |
| who | No | Restrict to one author by HANDLE — "@karpathy", "karpathy", a Substack/blog URL, or an id. THIS is how you answer "what did <person> say about X". Putting their name in `query` instead matches by CONTENT, so posts merely MENTIONING them rank alongside posts they WROTE (measured: 5 hits, 1 of them theirs). Resolved LOCALLY against people already in the store — free, no network, and it never invents anyone. A handle nobody has matches nothing, never everything, and `insights.resolved_who` + a `who_unresolved` notice tell you which case you hit: untracked person, or tracked person with nothing on this topic. | |
| mode | No | "hybrid" (default), "semantic", or "bm25". See `trace.ran` for what ran. | hybrid |
| tags | No | Restrict to atoms tagged with ANY of these topics (slugs, e.g. "ai-agents"). Matched as slugs: a value that normalizes to nothing matches NOTHING (never "no filter"), and `notices` tells you when a value was dropped or rewritten. | |
| query | Yes | Natural-language query. Rare literal tokens (a lib/symbol name) engage the keyword arm; conceptual phrasing leans on the semantic arm — both fire in hybrid. | |
| who_id | No | Restrict by EXACT entity id, one or several ("x:user:33836629", ["github:karpathy", "x:user:33836629"]). Use when you already have ids — from a prior hit's `who_id`, or `insights.resolved_who[].who_ids`. Prefer `who` when all you have is a handle; a person's atoms are spread across a PER-PLATFORM id each, so one id alone returns one platform's worth of them. | |
| date_to | No | Latest atom date to include, INCLUSIVE. Same formats; a partial widens the OTHER way, so date_to="2026" means 2026-12-31. | |
| date_from | No | Earliest atom date to include, INCLUSIVE. "2026", "2026-05" or "2026-05-11" — a partial widens to its natural edge, so date_from="2026" means 2026-01-01. ANY other shape is an ERROR, not a dropped filter: "5/11/2026" raises. THIS is how you answer "what did they post after <date>" — putting a date in `query` matches it as CONTENT, which is not a filter at all. | |
| what_kind | No | Restrict to a kind: "opinion" (saved posts) or "artifact" (repos). | |
| entry_mode | No | How the atom ARRIVED. Leave it OFF for the normal case: the answer then comes SECTIONED — `hits` is the full k over what the user saved, their Oracles published, or those Oracles cited, and `frontier_atoms` carries the keyword-crawl finds separately. Set it to scope the whole answer to one population instead: "frontier" with a larger `k` is how you dig into the crawl ("show me more of what the crawl found"), and a list like ["user-saved"] narrows to one arrival path. Scoping returns ONE list and no `frontier_atoms` key. | |
| source_type | No | Restrict to ONE source. Live values: "x", "github", "substack", "blog", "paper". |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description carries the full burden of behavioral disclosure, and it does so thoroughly. It reveals that hits are thin cards, not claims; explains score non-comparability and cosine bias; details `body_state` and `when_precision` caveats; and distinguishes reasoning keys from user-facing notices. This is exceptional behavioral transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it is well-structured with bolded key names, bullet-like sections, and a clear front-loaded purpose. Every section earns its place given the tool's complexity and the many subtle caveats. It is slightly longer than strictly necessary because some parameter guidance is duplicated in the schema, which keeps it just short of a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool this complex, the description is unusually complete. It covers the trust model, return-key semantics, score interpretation, body-state caveats, date precision traps, frontier atom separation, and knowledge-base scoping. An agent has nearly everything it needs to invoke the tool correctly and interpret its results safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents all 12 parameters at 100% coverage, so the baseline is 3. The description adds meaningful cross-parameter context beyond the schema, such as `mode="hybrid"` sometimes running only the semantic arm, `entry_mode` controlling whether results are sectioned, and filter choices surfacing in `trace`/`insights`. The schema still carries most parameter semantics, but the description enhances operational understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: "Route to the most relevant ATOMS in the trusted knowledge base." It immediately clarifies the tool is a router, not an answer provider, and explicitly distinguishes itself from `open(atom_id)` for reading actual source claims. An agent can tell exactly what search does and what it does not do.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear when-to-use guidance and names the key alternative: "To assert what a source actually claims, call `open(atom_id)`." It also explains when to quote snippets cautiously, how to offer frontier results, and when to surface notices. This is explicit routing behavior rather than leaving usage to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sittingSittingA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| add | No | for `watchlist` only — questions to start watching, in the user's own words. | |
| drop | No | for `watchlist` only — questions to stop watching, matched on their text. Retires them for every region, not just this one. | |
| lens | No | for `preview`, which lens's warnings to compute (default "queries"). For action `read`, which API lens to spend on: "queries" (default) | "claims". For action `lens`, which reading to return: "briefing" | "trajectory" | "disconfirmation" | "gaps" | "sprouts". | |
| claim | No | the belief or question being tested, for `lens="disconfirmation"` or `lens="gaps"` only. Optional on both. | |
| floor | No | how tightly related an item must be to join the region, 0-1. Leave unset. Higher is narrower, and a value below the corpus' measured noise ceiling is raised to it — down there an admission is not distinguishable from unrelated text. Two builds of one topic at different floors are two different regions with separate read histories. | |
| query | No | the topic, in the user's own words. It does NOT have to be wording that appears in their saved material — the match is by meaning, so "prediction markets" finds a thread nobody in the corpus ever called that. If nothing in the corpus is close enough, it says so rather than assembling something plausible out of near-misses. | |
| action | No | "preview" (default, free) | "read" (spends) | "render" (free) | "lens" (spends only on never-lensed material) | "watchlist" (free). | preview |
| atom_ids | No | seed from specific items instead of a phrase — the region around THESE. Free (no embedding). Use when the user points at something they just saw. | |
| sitting_id | No | an id from an earlier preview. Required for `render`; on `read`/`lens` it is the alternative to `query` (not needed for `lens="sprouts"`). | |
| budget_tokens | No | cap on how much is read in one sitting. Leave unset. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It does this exhaustively: it marks each action as FREE or SPENDS, warns about model calls, explains that preview queues nothing but consumption does, describes the read-once-per-lens guard, clarifies that lens summarization is cached and re-using it is free, and states that lens answers are never persisted. It also openly acknowledges that region size depends on the user's saved material, not the typed phrase.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but structured with clear action-by-action bullets and explicit cost labels, and it front-loads the core purpose and the contrast with search. While some information is repeated (e.g., the sitting_id/query alternation appears several times), the overall organization makes complex information scannable. For a tool with 5 actions and 10 parameters, the length is justified; there is little waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and the absence of annotations, the description covers virtually everything an agent needs to call it correctly: each action's behavior, cost implications, parameter combinations, return payloads (including consensus, claims, instruction/document), and warnings. It also explains the read-once guard and when re-reading is allowed. The presence of an output schema reduces the need to describe return shapes, but the description still does so extensively. No critical context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% coverage with rich descriptions, so the baseline is 3. The description meaningfully adds to this by clarifying the relationship between parameters (e.g., 'sitting_id' versus 'query' as alternatives), explaining that 'query' matches by meaning and need not appear verbatim in saved material, and contextualizing 'lens' differently across actions (preview, read, lens). This goes beyond the schema and aids correct parameter selection, justifying a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Read one topic of the user's knowledge base end to end, in publication order'. It then differentiates itself from the sibling 'search' tool by contrasting 'where is it' vs 'what happened', and explicitly names the opposite of the search tool. This is far beyond a generic 'read' or 'sitting' label; the agent understands exactly what this tool accomplishes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'Reach for this when the user wants to know what their saved material actually SAYS...' and equally explicit when-not-to: 'Do not reach for it to look something up... that is the knowledge-base search tool, and it is free and instant.' It further details when to choose each of the five actions and even which lens to pick based on the user's intent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Most tools target clearly distinct actions: search routes, open reads raw text, sitting reads a whole topic, share/unshare/accept handle sharing, and onboard/oracle separate setup from trust selection. The main overlap is oracle vs add_oracle, since oracle's confirm action can also add handles, but the descriptions make the direct-add path vs screen/confirm flow distinguishable.
Tool names mix imperative verbs (share, search, open, aggregate, accept, unshare), nouns (oracle, frontier, hopper, sitting), and compound forms (add_oracle, onboard). There is no consistent verb_noun or camelCase pattern, making the naming feel arbitrary even though each name is individually readable.
12 tools is a well-scoped count for a knowledge-base server covering setup, ingestion, retrieval, trust curation, opening/sharing, and accepting shared KBs. Each tool has a distinct job and the set does not feel padded or redundant.
The surface covers the main lifecycle: onboard for setup, hopper/add_oracle for adding content and people, search/open/aggregate/sitting/frontier for retrieval and analysis, and share/unshare/accept for access control. The only notable gap is the absence of any explicit delete/remove tool for atoms or the knowledge base itself, though this may be intentional.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Public social-data API and live docs for AI coding agents.
Governed, auditable knowledge your team curates for its AI assistants, self-hostable
The media memory layer for AI agents and their humans. Your AI client gets 29 tools to search your collection, add items, update ratings, preview music, and find patterns across everything you've read, watched, and listened to.
Social network for AI builders: agents post, read feeds, search, remix and follow over MCP.
Related MCP Servers
- FlicenseAqualityNot gradedmaintenanceA local-first knowledge base server that enables AI clients to store, retrieve, and manage documents using semantic search. Provides privacy-focused, offline-capable memory for AI assistants with tools for ingesting, querying, updating, and deleting knowledge.715
- FlicenseNot gradedqualityDmaintenanceArchives posts from X into a local SQLite database and provides tools for semantic analysis and natural language search. It enables agents to manage low-cost data ingestion and retrieve relevant posts using local embeddings and topic labeling.3
- AlicenseNot gradedqualityBmaintenancePrivacy-first personal knowledge database for your AI that ingests data exports (Google Takeout first) and exposes them via MCP tools like search and list items. Runs locally with no cloud or telemetry.MIT
- AlicenseNot gradedqualityBmaintenanceExposes a private social memory archive to AI assistants via MCP, enabling read-only queries about the user's posts, people, and preferences with tools like search, whoami, and timeline.MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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