Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
OMNISEEK_CONTACT_EMAILNoOptional but recommended: set for a faster lane with Crossref, SEC, and Unpaywall.

Instructions

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

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

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

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

Tools

Functions exposed to the LLM to take actions

NameDescription
omniseek_sourcesA

List all sources — call this to ROUTE before searching.

BOUNDED ORIENT: a bare (no-arg) call does NOT dump every source's facets. It returns the routing VOCABULARY (available_domains / available_regions with counts) + the capabilities verb index + source_names (the bare inventory) + counts, so the orient payload stays small no matter how far the roster grows (brain_orient's lesson). The per-source FACETS (kind / domains / regions / modes, needs_credentials, explicit_only, stability, health, ...) plus the prose description arrive when you NARROW or ask verbose — reach for them on demand: • domain="jobs" / "papers" / … → only sources whose domains facet contains it, WITH their full descriptions. domain= is the most RELIABLE router; the no-arg call returns available_domains (the full closed vocabulary + counts) so you can pick a valid token, and a near-miss (e.g. "careers") returns did_you_mean instead of a silent empty. • query="singapore visa" → TOKEN-OVERLAP over name + description + domains + regions + cross-lingual keywords, ranked best-first (multi-word- and English↔中文-safe), WITH descriptions. • region="sg" / "ca" / "cn" → only sources whose regions facet contains it (the no-arg call returns available_regions; a near-miss returns did_you_mean). Region narrowing matters when the deployment's source pack is geographic. • verbose=True → the full unfiltered list, WITH every description. check_health=True does a fresh LIVE probe of every source (slow) AND returns a system block: the recall-index health (indexed_docs / embedder_available / vec_embed_failures / last_write_age_s) plus the observation-journal durability head, materialization cursor, pending count, and failures. and the openalex_usage attribution (which component spent the shared daily budget + remaining).

The no-arg (orient) call also returns capabilities: the non-search VERB index (field_skeleton, coauthors, transcribe, …) so you discover the whole toolkit here, not only after loading a tool.

Returns: {"count": N, "backend_count": M, "backend_breakdown": {...}, and EITHER

  • a BARE ORIENT: "source_names": [...] + "note" + available_domains + available_regions + capabilities; OR

  • a NARROWED (domain/region/query) or verbose call: "sources": [{name, backend, (description when narrowed/verbose), needs_credentials, explicit_only, explicit_only_reason? (present only when excluded; the full catalog of why-strings search's _meta.excluded_count no longer re-ships), param_hint? (the structured query a VERTICAL source wants — a stock code / ticker / author name — present only when the source declares one, so a named call is filled right the first try), stability, access_tier, health, health_as_of, kind?, domains?, regions?, modes?, (healthy, status if check_health)}]. (did_you_mean on a domain/region near-miss; system:{recall, openalex_usage, jobs:[{name, schedule, enabled, last_run, next_run, budget_s, desc}, ...]} when check_health — the background-job fleet.)}

count is the RAW source count; it over-states coverage when many logical sources sit on ONE upstream. backend_count is the distinct UPSTREAMS (the honest figure) and backend_breakdown names every upstream backing >1 source, e.g. {"openalex": 42} (40+ affiliation slices of one corpus + one API budget + one breaker = one backend, not 40 of coverage).

omniseek_searchA

Search the curated sources. The default for "best/latest on X". ONE verb, three shapes.

DISPATCH (deterministic): • DEFAULT (raw=False): DEDUP + RANK across sources into ONE list. Cross-source duplicates merge (same paper from arxiv + openalex + … → one entry, the others in metadata.also_in); ordered by a relevance+recency+engagement blend (metadata._rank) you may re-sort — each doc's named signals map (e.g. citations / upvotes / stars, each provenance-stamped) + its date are on the doc. CROSS-LINGUAL + SEMANTIC (default on): also runs VECTOR recall over the local perception-memory index, so a Chinese query surfaces relevant ENGLISH docs (and vice-versa) and paraphrases match with no shared words — fused with the lexical + live results by the SAME transparent ranker (the eye still only retrieves + scores mechanically; you judge). semantic=False forces exact-token lexical-only (an arXiv id / exact title); semantic=True biases toward the vector recall. _meta.index reports {lexical, vector, mode}. Empty query ranks by recency (browse mode). • raw=True + EXACTLY ONE source name (the DRILL idiom, replaces the old omniseek_fetch): fetch that ONE source UNBOUNDED (with wait_s=None the generous single-source backstop; set wait_s to bound it). Reach for it BY NAME on a walled/CDP or slow source (xiaohongshu, zhihu, yipinsanfendi, xiaomuchong, twitter_x, and the explicit_only set): the broad sweep DEADLINE-DROPS these, so only a named drill waits for them — a broad search that comes back without them is NOT evidence they have nothing. full=True returns WHOLE content per doc. A cold walled drill self-warms its cache, so an immediate repeat with the SAME query + SAME limit is sub-second (keep limit identical or the key differs). On an EMPTY / ERRORED drill the result carries _meta.diagnostic (failed-egress evidence + the adapter's source-file path) for the /eye-fix loop; a drill with results carries no _meta (zero noise). • raw=True otherwise (broad buckets): search many sources in parallel → PER-SOURCE buckets, uncollapsed (each source's raw take separately, a tight content preview per doc). limit acts PER SOURCE here. Drill a chosen doc with omniseek_read (whole content), or drop raw for the ranked list.

ROUTING (all shapes): sources=None = all non-explicit_only, deadline-bounded — slow ones drop and are listed in _meta.timed_out. explicit_only sources (browser/CDP + twitter_x) are excluded from the broad sweep → _meta.excluded_count (the size; the full name->reason map is in omniseek_sources) + _meta.excluded_relevant (the query-AWARE subset: walled/slow sources whose facets thematically match THIS query, each with a copy-paste sources=[...] re-run hint). Name them to include their (deeper, login-walled) coverage.

TIME + STALENESS: wait_s = patience budget (None = sensible default; the engine's deadline). staleness ∈ {"fresh","cached_ok","cache_only"} (default cached_ok): "fresh" bypasses the cache (live data); "cache_only" is the fire-then-collect PICKUP half (ranked shape) — with NO live work it reads only what has already SELF-WARMED for the NAMED sources and NEVER re-fires a still-cold walled source (zero extra CDP / account traffic, poll-safe). Fire-then-collect: FIRE omniseek_search(query, sources=[walled...], wait_s=12), then COLLECT omniseek_search(query, sources=[walled...], staleness="cache_only"); use the SAME limit both times (the cache key includes it; a different limit silently misses). _meta.empty = sources not yet warm.

FIRE-THEN-COLLECT IS NOT JUST FOR WALLED SOURCES: it is the BEST way to run an ORDINARY broad search, and it is both faster AND more complete than waiting. A plain broad call blocks ~16s for ~223 docs. Instead FIRE omniseek_search(query, wait_s=3) -> first results in ~3s, then COLLECT omniseek_search(query, staleness="cache_only") ~20s later -> ~296 docs. Measured over 3 quiesced reps (2026-07-25): 5x faster to first result AND ~33% MORE docs than the blocking call. It wins on both axes because sources the deadline would have cut keep running detached and warm the cache with no deadline over them, so the collect reads MORE than the 16s window could ever hold. The cache plateaus by ~+20s (no gain at +35s), so collecting later buys nothing. Same limit both calls. vs the open web: searches only OmniSeek's curated sources; pair with WebSearch for open-web breadth (orthogonal, often use BOTH).

PER-DOC METADATA is LEAN by default: internal ranking/recall telemetry (recall_rrf / freshness_class / relevance_hook / merge_basis / ...) is omitted (~25% of a ranked doc); the SIGNAL stays (_rank, also_in, seen_before / first_seen_at, source-native signals). debug=True keeps the full telemetry (/eye-fix).

Returns (default): {"query", "count", "documents": [...], "_meta": {..., excluded_relevant, "deduped": {in, out}}, routing_hint? (TOP-LEVEL: the strongest excluded vertical/walled matches for THIS query, overlap-ranked, each with its param_hint — name one for its authoritative coverage; present only on a broad sweep with a strong match)}. (raw one-source drill): {"source", "query", "count", "documents": [...], "_meta": {"diagnostic": {...}} # only when empty/errored}. (raw buckets): {"query", "results": {source: [...]}, "total_count", "_meta": {searched, empty, timed_out, errored, excluded_count, excluded_relevant, truncated, progressive:{fast,slow,timed_out}, ...}}. An unknown staleness value is treated as cached_ok and a "note" is added to the return.

omniseek_field_skeletonA

Map a research field's shape — use WHEN you need its citation neighborhood (foundational core by citations vs frontier by date) to cluster yourself, from a topic or seed papers.

A thin graph primitive, NO judgment: given query (auto-picks top-relevance seeds) or seeds (OpenAlex work-ids YOU chose as anchors — preferred once you know the field), it returns the field's complete citation neighborhood: every node with raw metadata, date, and ONE signal in_degree (how many in-field papers cite it).

YOU are the cartographer — do ALL the intelligence over this raw data: • SEEDS: if the auto-seeds are off (e.g. a generic survey crept in), re-call with seeds=[...] you pick from the nodes. • SOURCE: source="openalex" (default, rich for established fields) or source="s2" (Semantic Scholar — far better arXiv coverage + accurate citation counts; use it for recent/bleeding-edge fields where OpenAlex's graph is sparse). s2 nodes also carry influential (S2 flags the citation link to a seed as substantive, not a drive-by) and intent (methodology/background/result, when S2 classified it): strong cues for what to read first, and contexts ([{snippet, intents}]: the RAW citing SENTENCE(s) S2 extracted). READ a snippet to judge a citation's POLARITY yourself (does the citer SUPPORT, CONTRAST/refute, or merely MENTION the seed): OmniSeek exposes the sentence, YOU classify; S2 has no polarity field and OmniSeek makes no such judgment. contexts is empty when S2 never parsed the citing PDF. For a young/hot field the best "graph" is often a human-curated survey/awesome-list, fetch that yourself instead. • FOUNDATIONAL vs FRONTIER: high in_degree = the foundational core; recent date (filter it yourself) + your relevance read = the frontier. There is no frontier flag — you judge it. • DATA HYGIENE: OpenAlex occasionally has a poisoned title (e.g. a 14k-citation paper titled "AI Consciousness" by T.B. Brown IS a corrupted GPT-3 record). You recognize these — no code does. Use a node's url to verify / omniseek_read to read the real paper. • Cluster + narrate relevance and sub-fields from titles + concept + your knowledge. • GAP DETECTION (your seed set's blind spots): each non-seed node carries seed_ref_freq (how many of YOUR seeds reference it = a foundational ref your reading list is MISSING) and seed_cite_freq (how many seeds it cites = a frontier citer you are MISSING). Sort non-seed nodes by these to find what your input lacks. edges (the in-corpus [citer, cited] citation DAG) lets you build the citation / co-citation / bibliographic-coupling maps yourself (co-authorship: use omniseek_coauthors). • BUDGET: there is an overall wall-clock cap (deadline_s, ~25s default). On a slow/throttling S2 the assemble bails early with a PARTIAL map (_meta.deadline_hit: true) rather than hanging — retry shortly, raise deadline_s, or use source=openalex.

Returns: {seeds, n_nodes, n_edges, edges:[[citer_id, cited_id]], nodes:[{id, title, year, date, cited_by, in_degree, concept, first_author, doi, url, is_seed, seed_ref_freq, seed_cite_freq}]} (sorted by in_degree as a default view only; seed_ref_freq/seed_cite_freq on non-seed nodes). _meta carries seed_titles + seed_note (auto-seed drift check), degraded, deadline_hit, partial.

omniseek_paper_recommendA

Use WHEN you have a paper and want more like it — semantically-similar papers (SPECTER embeddings) that keyword search and the citation graph miss, including very recent work. Uses Semantic Scholar's recommendation model (SPECTER embeddings + co-citation), so it surfaces conceptually-related work that omniseek_search (keyword) and omniseek_field_skeleton (citations) miss — including very recent papers the citation graph has not caught up to.

Pass seed paper ids (arXiv ids / DOIs / S2 ids — a paper you found via omniseek_search or omniseek_field_skeleton). One seed = "more like this"; several = recommendations from that set. This is OmniSeek's "semantic search": it routes to S2's existing embeddings rather than building any. For an openalex omniseek_search result pass metadata.paper_id (or metadata.doi), NOT source_id — the OpenAlex W-id is a graph id the paper tools do not accept.

Returns: {"seeds", "n", "papers": [{id, title, year, date, cited_by, first_author, doi, url}]} (ordered by S2 relevance; YOU re-judge). Citation neighborhood instead → omniseek_field_skeleton; keyword search → omniseek_search.

omniseek_paper_enrichA

Use WHEN you need ONE paper's open-access full-text PDF, retraction / integrity status, or citation count — signals omniseek_search / field_skeleton do NOT give cleanly. Keyless, mechanical: YOU decide when + on which papers.

Pass DOIs and/or arXiv ids (e.g. "2306.08543", "10.1145/3292500.3330701"; use a node's doi from omniseek_field_skeleton, or metadata.paper_id/metadata.doi from an openalex omniseek_search result — NOT its source_id, the OpenAlex W-id, which is not a DOI/arXiv id). Enrich only the handful you care about, not a whole map. For each id: • is_oa / pdf_url — the open-access full text (arXiv always OA; real DOIs via Unpaywall). Feed pdf_url to omniseek_read (or read it yourself) to get the WHOLE paper, not just the abstract — then YOU synthesize. (This thin PDF primitive is why we did NOT add a synthesis engine.) For FIGURES / architecture diagrams / result plots: download the PDF and Read its pages with your own VISION — they render in context with captions, so no figure-extraction channel is needed. • integrity.retracted + integrity.notices (retraction / expression_of_concern / correction / …) from Crossref's Retraction Watch feed — check before trusting a high-stakes citation. (retracted=None means "not checked" / backend unreachable; notices=[] means clean. arXiv ids are checked too: an author withdrawal marker plus the journal DOI, when present, run through the same Crossref retraction path.) • citation_count — this paper's citation count (DOI: Crossref is-referenced-by-count; arXiv: S2 citationCount). The single-paper count's home, so you need NOT repurpose omniseek_field_skeleton to read one node's count. (None when the backend was unreachable.)

Returns: {"results": [{id, kind, doi, is_oa, pdf_url, oa_url, citation_count, integrity:{retracted, notices}}, ...]} (or {id, error} for an unrecognized id).

omniseek_resolve_identityA

Resolve a PERSON's name to candidate author ids — the shared front door for EVERY relationship layer (you must know WHICH person before you can map their connections).

OmniSeek's other tools keyword-search PAPERS; this resolves an AUTHOR. It NEVER silently picks — it returns ranked CANDIDATES so YOU disambiguate (the homonym trap: "Zhennan Shen" is three different people in OpenAlex). hint (e.g. an institution like "HKUST", or a field) only RE-ORDERS candidates, never filters them. source: "auto" (OpenAlex first, pulls in Semantic Scholar when the top OpenAlex hit is sparse — i.e. a likely junior / arXiv-frontier author OpenAlex hasn't indexed), "openalex", or "s2".

paper (an arXiv id / DOI / title of a KNOWN paper by this person) is the reliable way to pin a COMMON-NAME JUNIOR — it resolves straight from the paper's author list, where a bare name search fails (e.g. many distinct researchers share a common name like "Wei Zhang"; their paper fixes the exact id).

Use the returned id with omniseek_coauthors. ambiguous: true means two comparable candidates — confirm with a hint / a paper / a known co-author before trusting either.

likely_same_person (when present) groups same-name same-backend candidates that are likely ONE person SPLIT across ids, with a ready-to-paste merge_token ("A123+A456") you can hand straight to omniseek_coauthors as one input; it never auto-merges, just surfaces the candidate merge.

Returns: {query, source, candidates:[{id, source, name, works_count, cited_by, institution, via_paper?}], ambiguous, note, likely_same_person?:[{source, ids, name, merge_token, note}], degraded?:{openalex}}. degraded (when present) means the OpenAlex lookup FAILED (rate-limited / upstream down): an empty/thin result is then missing-data, NOT a confirmed "not in the graph" — retry, or pass source='s2' / paper=.

omniseek_coauthorsA

Use WHEN you want WHO a researcher collaborates with — advisor + closest collaborators by joint-paper count, or how a paper's author group is connected (WebSearch cannot build this). One LAYER, not the whole graph — co-authorship is one edge type; YOU overlay the others (advising, institution cohort, citation, code, social) and judge what each connection MEANS.

Pass author NAMES and/or ids (from omniseek_resolve_identity). A brand-new arXiv paper is not in the graph yet, so this reconstructs from each author's PRIOR work: • N=1 -> that author's frequency-ranked coauthor neighborhood. The advisor + closest collaborators surface by joint-paper count (e.g. Yi R. Fung -> Heng Ji ~51x = her PhD advisor, no advisor field needed — YOU read that signal). • N>1 (e.g. a paper's whole author list) -> additionally the PAIRWISE prior joint-work edges among them (with the actual joint paper titles as evidence) + BRIDGE collaborators (people who co-authored with >=2 of the inputs but are not in the set). This is the "how is this author group actually connected" reconstruction.

Each input may be a NAME, an id, or '+'-joined ids ("id1+id2") for ONE person SPLIT across ids — their works are MERGED (OpenAlex/S2 routinely split a junior's recent papers; merging recovers the complete network). Each becomes a node with resolved, ambiguous + alternatives (juniors often need source="s2", a paper anchor, or an explicit id — the node note says so when unresolved). The output also carries cooc: which of the network's top external coauthors co-appear on the same papers, i.e. the SUB-COMMUNITY structure (an ego's distinct 'research worlds'). Mechanical throughout: "these two share these N papers" is a fact; advisor-vs-peer, what a cluster MEANS, is YOUR judgment. For the citation/influence layer use omniseek_field_skeleton; for the others, assemble from the dossier recipe (github, bluesky, exa, cdp_fulltext, omniseek_read).

hints / papers are parallel lists for per-author disambiguation (an institution hint, or a known paper that pins a common-name junior).

Returns: {source, n_authors, nodes:[{query, resolved, ambiguous, alternatives, works_seen, top_coauthors:[{id,name,joint}], degraded?}], edges:[{a,b,joint_count,papers:[{title,year,id}]}], bridges:[{id,name,shared_by,total_joint}], cooc:[{a,b,n}], degraded?}. (top_coauthors/bridges carry a representative id you can harvest and pass back to omniseek_coauthors to drill that person.) A top-level/node degraded means that author's OpenAlex lookup FAILED (rate-limited / upstream down): an empty graph is then missing-data to RETRY, not "no collaborators".

omniseek_institution_cohortA

Use WHEN you need the people-ROSTER of a lab / department / university (who actively publishes there, optionally scoped to a field) — the "who's at this lab" question, orthogonal to co-authorship ("same lab, never co-authored" is still a tie, and the people-roster of a target lab is exactly the SG/Canada cohort question).

Resolve the institution (+ optional FIELD) -> roster ranked by their output AT that institution IN that field (so juniors with a few papers surface, not just senior profs). IMPORTANT: without concept you get the institution's most-prolific people across ALL fields (e.g. "Hong Kong University of Science and Technology" -> chemistry/materials profs, not the ML group) — pass concept="machine learning" / "natural language processing" / etc. to scope to a cohort. year_from (e.g. 2022) biases toward the CURRENT cohort (recent publishers). The roster is a STARTING POINT you drill (omniseek_coauthors / omniseek_read on homepages), not a verified lab-member list — OpenAlex has no "PhD student" flag.

Returns: {institution:{id,name}, filters, n, people:[{id, name, works_at_institution_in_field}], note}.

omniseek_readA

Read text from any URL OR document FILE — OmniSeek's single "read this deep" verb. AUTO-ROUTES.

ROUTING: if target is a local filesystem path OR ends with a document extension (.pdf / .pptx / .docx / .xlsx / .txt / .md / .csv, case-insensitive, a ?query is tolerated) it routes to the DOCUMENT reader (below); otherwise it routes to the URL reader. start_char / max_chars window the body on BOTH branches (see below); export_media / ocr apply only to the document branch (a URL read has no image-extraction path) and are IGNORED on the URL branch.

URL BRANCH: fetch + normalize ONE URL. Tries each registered adapter until one claims it — a specific article link (a Reddit post, an arXiv paper, a Bluesky post) as a normalized document. arXiv is two-tier by design: an /abs/<id> URL returns abstract-level metadata (title / authors / abstract, a fast lookup), while an /pdf/<id> URL routes to the PDF extractor and returns the WHOLE body (e.g. 2203.02155v1 → 68 pages of full text). Pass the URL whose depth you want. vs the open web: reads ONE specific URL you already have; to FIND open-web pages use WebSearch first, then omniseek_read to normalize the page (a common pairing). The normalized body is WINDOWED by start_char / max_chars (default 24000), exactly like the document branch: a big page (a SEC 10-K/20-F is ~2 MB → ~200k chars, a long article) would otherwise return one blob that overflows the tool channel and is unreadable. When truncated is true, re-call with start_char bumped by returned_chars to page through the rest. A small page (< max_chars) returns whole, truncated=false — unchanged from before. URL branch returns: {"url", "matched": bool, "document": Document as dict | None, "total_chars", "returned_chars", "start_char", "truncated"} (the last four only when matched). On matched:false a reason is added: walled (anti-bot challenge -> retry the source via CDP, e.g. omniseek_search(sources=[...], raw=True, full=True)) vs empty vs blocked, so you can tell "gated, drill it another way" from "genuinely nothing there".

DOCUMENT BRANCH (pptx / docx / xlsx / pdf / txt / md / csv): read the FILE into readable, structured text — the document counterpart of omniseek_transcribe (speech). Free, keyless, cached. WHERE THE FILE LIVES:

  • the operator's machine: scp it to OmniSeek host inbox first — scp "" :omniseek-inbox/ then call with "omniseek-inbox/".

  • Anywhere on the web: just pass the URL (conference slide decks, a shared docx, a PDF). WHAT COMES BACK: outline = per slide/sheet/page {label, chars, media} — the MAP of the whole document, always complete and tiny; text = the readable content ("## Slide 3" / "## Sheet: budget" / "## Page 5" headers), windowed by start_char/max_chars for big docs (truncated=true + total_chars tell you to re-call with start_char to continue); media/media_total = the image inventory per section. THE IMAGE HALF (be honest about it): a figure deck or scanned doc carries its meaning in IMAGES — text extraction alone is NOT the document. Two ways to read it: omniseek_view delivers the figures to your OWN vision in-band (judging the figure is yours); ocr=True here runs OCR over every embedded image and folds the recognized text-in-pixels (scanned page body, chart labels, palette HEX/RGB codes) into the body under a '图中文字 (OCR)' section — mechanical text transcription, NOT figure interpretation, and labeled as possibly imperfect. Use ocr for text-bearing images (scans, labels); use omniseek_view to SEE the figure. Document branch returns: {source, format, title, outline, text, total_chars, returned_chars, start_char, truncated, media_total, media, media_dir, ocr_images?, cached} — or {source, error, inbox_files?}.

omniseek_transcribeA

Transcribe the SPOKEN content of a video / podcast / audio URL via local SenseVoice ASR (free, keyless, private, cached forever; chosen over Whisper after a real-audio benchmark — Whisper hallucinates on Chinese podcast intros). For the 干货-in-audio case where the substance is in the audio, not any text: bilibili videos (论文精读 / 方法论 / 读博 / 求职 talks), 小宇宙 podcasts, or any direct audio-file URL. (youtube already returns its captions via omniseek_read — no ASR needed; use that instead.)

THE LONG-EPISODE PATTERN: do NOT transcribe a 2-3h episode whole (30k+ chars nobody reads). Pull the chapter timestamps from the episode's shownotes (小宇宙 episode pages list them; use omniseek_search(query, sources=["xiaoyuzhou"], raw=True, full=True) / omniseek_read first), judge WHICH chapter matters, then transcribe just that slice: start="1:02:30", duration="12:00". Accepts seconds ("3750") or MM:SS / HH:MM:SS. Slices are also fast to start — on direct/enclosure audio only the slice region is downloaded. The flat transcript covers [start, start+duration] of the source audio. Pass segments=True to ALSO get a per-VAD-segment segments: [{start,end,text}] list (seconds) so a no-shownote episode becomes navigable / time-citable (the flat transcript is unchanged; segments costs an extra VAD + a batched re-transcribe pass, so request it only when you need the offsets).

Whole-item transcription remains right for short/dense items (a 10-min talk, a keynote clip); it is SLOW on first call for a long item, then cached forever. Reach for it deliberately on ONE item you've judged worth it, never as part of a broad sweep.

language: "" auto-detects; set "zh" / "en" to skip detection and sharpen accuracy when you already know the language.

diarize=True answers WHO said what (interviews / 对谈 / multi-host podcasts): segments become [{start,end,text,speaker}] with per-turn speaker labels and speakers gives the distinct count. It routes through a Chinese-focused diarization pipeline (Paraformer-zh + cam++ speaker clustering), a SEPARATE and heavier pass than the flat SenseVoice path, so request it only when the speaker turns matter, and expect zh accuracy (English audio is not its target). Cannot combine with plain segments (diarize supersedes it). speaker values are cam++'s cluster indices (0,1,2,...).

speakers=N pins the diarization to N speakers (the KNOWN head-count: a 1-on-1 interview = 2, a solo talk = 1, a 3-host panel = 3). PASS IT whenever you know the count: cam++'s automatic estimate is unstable on short / noisy slices and will over- or under-split, so pinning N is what makes the turns track reality. Leave it 0 (auto) only when the count is genuinely unknown. Ignored unless diarize=True.

Returns: {url, transcript, chars, audio_seconds, asr_seconds, source, title, cached, start_seconds?, duration_seconds?, segments?, speakers?} — or {url, error, transcript:""} if no audio resolved.

omniseek_viewA

SEE with your own vision, IN-BAND — document figures, loose image URLs, or video frames. ONE verb; kind="auto" picks the branch (or force it with kind=document|images|video).

ROUTING (kind="auto"): a document path/extension (.pdf/.pptx/.docx/.xlsx/…, as in omniseek_read) → DOCUMENT figures; a video URL (youtube/bilibili/douyin host or a .mp4/.webm/.mov suffix) → VIDEO frames; otherwise → loose IMAGE URLs (target may be a comma-separated URL list). The images come back as image content you can look at directly (no download/scp dance); OmniSeek only renders the pixels, what they MEAN is yours to read.

WHICH PARAMS BELONG TO WHICH KIND: • document: sections (comma-separated slide/page numbers to pull, "" = all), names (comma-separated exact image names from the omniseek_read outline media[].name), max_images (full-res cap; a wider selection falls back to a contact sheet). THE TWO-STEP: first omniseek_read to get the outline (which slides/pages hold images), then call this — with NO sections/names you get a CONTACT SHEET (every image a labeled thumbnail tiled into one montage; triage ~30 for the cost of one), then pull the few that matter full-res by sections="8,15" or names="s08_02_image.png". Covers pptx / pdf / docx (the image-bearing formats); text formats return a note. render_pages="8,15" is the COMPLEMENT (PDF): it renders those WHOLE pages to images, the channel for a page whose substance is VECTOR figures / dense tables / a layout carrying NO embedded raster (where sections/names find nothing). This is how you READ a visual page you cannot trust as parsed text: route to the doc, omniseek_read for the page you want, then render + see it with your own vision. • images: target = image URLs comma/space/newline separated (paste a walled post's media[] list — xiaohongshu / zhihu note images, where the 干货 often lives). max_images caps per call. • video: start / duration (optional slice: "8:30", "90", "1:02:30"; default the whole video, capped at 30 min), n (frames to sample, default 12, max 24). The VISUAL half of omniseek_transcribe: its on-screen slides / diagrams / code / charts as ONE labeled contact sheet (a timestamp under each frame). Pair with omniseek_transcribe on the same slice for BOTH halves. (bilibili frames ride the same activated playurl session as bilibili audio — the ASR path's visual sibling.)

Returns image content blocks: document = [contact-sheet montage + legend] or [manifest + one block per figure]; images = [manifest + one block per URL that loaded]; video = [contact-sheet + timestamp legend]. Or an error / honest "nothing to show" note.

omniseek_curator_viewA

Use WHEN running the source-curation protocol (judge the admission queue or a source audit) — READ curator state: queue | packet | audit. Never mutates. Pick a view with what:

• what="queue" -> the candidate-admission backlog (optionally filtered by state: new / probed / awaiting_verdict / admitted / watching / rejected / owner_review / redline_blocked / parked_p2 / error). The judging agent's entry point: list awaiting_verdict, then view each packet. See the /curator protocol. • what="packet" -> the last-built evidence packet for candidate_id (a fresh agent picks it up cold); {"error": ...}/{"state": ...} if none built yet. A foundry-grade draft (the submitter's WORKING row + fixture + probe summary) is surfaced verbatim under draft. • what="audit" -> the per-source NEUTRAL audit dossier (P3): facts + LABELED descriptive ratios

  • the mechanical safety flags per source, NO verdict key. Read this, then render KEEP / WATCH / PRUNE via omniseek_curator_act(verb="source_verdict", ...).

Unknown what returns an error dict listing the valid values.

omniseek_curator_actA

Use WHEN acting on the source-curation protocol — WRITE a source-lifecycle action (submit / probe / decide / admit / retire ...); every safety gate lives in the impl, unchanged. Pick the action with verb; each verb's REQUIRED args (see the /curator protocol):

• submit (name, urls, mode, domain, family; optional kind, regions, rationale, draft) -> add a CANDIDATE source to the admission backlog. mode ∈ STRUCTURE/UNWALL/TRANSCRIBE/RECALL/MONITOR. draft (foundry-grade) is a WORKING artifact ({"row", "fixture", "probe_summary"}) surfaced in the packet and preferred as stage_commit's ready-to-paste block. • probe (candidate_id) -> run the MECHANICAL evidence-gatherers, persist + return the packet. • wall_probe (candidate_id) -> P2 re-probe: RENDER the candidate in the network-isolated jail (egress only via the SSRF-pin proxy) so a source whose real content the plain-HTTP probe MISSED (client-rendered SPA / anti-bot / soft-login-wall) is measured on its REAL content. Eligible on a parked_p2 candidate OR an awaiting_verdict one YOU judge to be a client-rendered shell (WHEN to spend a render is your call, not an auto-gate). Surfaces content -> lands in awaiting_verdict on the rendered packet (parked_p2 revives, awaiting_verdict re-enriches); nothing -> stays put with the reason. Facts are render-derived (M7): the code never admits, only surfaces. • decide (candidate_id, decision, reasons; baseline_ref required to admit) -> record the admit/watch/reject verdict. MECHANICALLY REFUSES an admit on hard red-line / incomplete evidence / empty baseline_ref / no packet. admit -> owner_review; watch -> watching; reject -> rejected. • apply_live (candidate_id) -> ONE-TAP LIVE ADMIT (rss-safe subclass only): a REVERSIBLE overlay row + live re-register, NO git. Non-auto families are refused (use stage_commit). • rollback_live (name, family) -> full revert of a live-applied overlay row (unregister + drop). • stage_commit (candidate_id) -> ONE-TAP STAGED COMMIT for the NON-auto subclass: prepares the git commit text (does NOT apply); the operator does the git add / commit / deploy by hand. When the candidate has a foundry draft, the draft row IS the ready-to-paste block (+ a provenance line). • retire_live (name; confirm) -> ONE-TAP PRUNE (needs an existing PRUNE verdict): confirm=False previews; confirm=True writes a reversible runtime explicit_only override + stages the git commit. • rollback_retire (name) -> drop the runtime retire override so the source rejoins the fan-out. • source_verdict (name, verdict, rationale; prune_class, coverage_impact) -> record KEEP / WATCH / PRUNE for an EXISTING source. MECHANICALLY REFUSES a PRUNE the source's safety flags forbid.

Unknown verb returns an error dict listing the valid values.

omniseek_gatherA

Run N independent read-only eye tools IN PARALLEL, returning results in one response.

The agent decides WHAT to call (judgment). OmniSeek executes them (mechanical). Each call runs independently; one failure does not affect others. Calls that depend on a prior call's result belong in a SEPARATE gather (the agent reads this batch first, then decides the next batch).

calls: [{"tool": "omniseek_search", "args": {"query": "..."}}, ...] Bounded: max 10 calls. Read-only tools only.

wait_s: the patience budget. gather returns when all calls finish OR wait_s elapses, whichever comes first; calls still running are reported with status "warming" (their background threads keep going and warm the cache — pick them up later with staleness="cache_only" or a second gather).

Returns: {results: [{index, tool, status, result|error|hint}, ...], elapsed_s, completed, warming, failed, total} On an errored call whose failure is a call-signature mismatch (a wrong / missing argument), hint names the tool's REAL parameters (e.g. "omniseek_read takes: target, start_char, max_chars, ...").

omniseek_graphA

Use WHEN you want HOW two entities connect, or what OmniSeek already knows AROUND a paper / author / entity; read-only, budgeted projections of its accumulated evidence graph with typed edges (ONE graph).

Everything OmniSeek perceives is a statement with provenance ("X relates to Y, per Z"); the evidence graph accumulates those typed edges in ONE store surfaced through N indexes. It stores FACTS + labeled CANDIDATES, never verdicts: mechanical world edges (tier M: cites, authored, coauthored, affiliated, published_in, about, observed, exact-id same_as) and alignment CANDIDATES (tier A: title-fingerprint / fuzzy-name same_as, name-match authored, string mentions, signal conflicts). Judgment (claims, gaps, identity rulings) is tier J and is STRUCTURALLY excluded from OmniSeek's store — the views project structure, YOU judge it.

ONE STABLE VERB: omniseek_graph(view, args). view names the projection; args is that view's OWN parameter dict (the views are an open family, their params disjoint per view, so the ABI is (view, args), not a flat union). THE SCHEMA IS FROZEN: future views and future per-view parameters change NOTHING in this signature; a no-view call returns the live view catalog (the surface is self-describing), and content is NEVER inlined (every view returns node ids + labels

  • edge tuples, so you zoom with the other eye tools).

• view="find", args={"label_query": ..., "kind"?: ...} -> the ENTRY POINT. A node id is minted by the backend that knows it, so a NAME ("Siva Reddy") is not a node until you resolve it: find does the mechanical token/substring match over node labels and returns candidate ids + kinds. Every other view takes an anchor id; find is how you get one. • view="stats", args={} -> counts by kind / type / tier. The cheap orientation call (also the cold-start check: see below). • view="neighborhood", args={"anchor": ..., "depth"?<=2, "types"?, "policy"?, "max_nodes"?} -> the bounded subgraph around a node. • view="between", args={"a": ..., "b": ..., "types"?, "policy"?, "max_nodes"?} -> bounded connection paths between two anchors, the "how do these relate" question. Bidirectional BFS, <=2 hops per side, up to 8 shortest paths; capped when more existed. No path -> paths:[]. • view="voices", args={"doc_ids": [...], "policy"?: ...} -> collapse a doc set to distinct upstream VOICES via same_as + authored; the independence counter (mirror collapse, shared-speaker docs merge, docs with zero evidence land in unresolved and are NEVER counted as a voice). Input capped at 64 doc ids by explicit error; non-doc: ids come back in skipped. • view="since", args={"anchor": ..., "date": ..., "types"?, "max_nodes"?} -> the accretion log: what accreted around an anchor after a date (YYYY-MM-DD or full ISO), STORED edges only, tier + method shown on every row, NO collapsing (accretion is a fact stream, not an identity question). Derived edges carry no timestamps and are structurally absent. The sensor consumer. • view="similar", args={"anchor": , "k"?: ...} -> vector-nearest doc CANDIDATES for an anchor doc, method align:embed, by RANK (k is a budget, never a score threshold). PROPOSALS only, never collapsed by any policy; verify, then ratify with omniseek_ruling. Coverage: any doc with an embedded title, ranked across the UNION of the indexed vec matrix AND the thin-title vec_thin matrix (P7), so a thin arXiv original and an indexed post rank in ONE space; candidates may be thin docs. A doc with no vector in either store (un-embedded yet) -> an error naming that. NON-GOAL: vec_thin does NOT feed search's recall arm (similar + future P5 consumers only). A no-view call (view="") returns the live view catalog: each view's params + one-line blurb, DERIVED from the registry, so new views appear here without a client restart. Identity rulings are WRITTEN via omniseek_ruling (this tool stays read-only, hence gather-safe).

policy (an arg on the collapsing views) = conservative | working | exploratory: NAMED METHOD-SETS for how far to trust identity (same_as) edges when collapsing, NOT numeric thresholds (a hand-picked constant is pseudo-precision; the METHOD is the honest epistemic unit, as recall fuses by rank only):

  • conservative: collapse on exact-id equality only (DOI / OpenAlex / ORCID / arXiv; default)

  • working: conservative + agent identity rulings from graph_rulings.json

  • exploratory: working + title-fingerprint / fuzzy-name alignment CANDIDATES Identity is an EVIDENCE-CARRYING EDGE, never a destructive merge: same_as edges carry tier + method, collapse is reversible, and a not_same_as ruling beats a same_as. OmniSeek never MAKES an identity ruling; it only applies the ones you already recorded.

COLD START (set the expectation or the first stats reads as failure): documents and same-work edges are LIVE FROM DAY ONE (derived over recall's docs — the wall is born pre-populated by construction). Document THIN rows (title + url only, from NON-indexed sources) now accumulate from EVERY search (stats.node_kinds.document_thin), so the perception history is complete, not just the ~40 enumerable sources. Entity kinds (work / person / institution / venue / topic) still fill in as the P2/P3 write taps ship and calls happen; emptiness of those kinds early is CORRECT, not broken.

BUDGETS (the no-silent-caps discipline): depth is clamped to <=2, max_nodes caps the node count, and any capped result stamps capped: true so a bounded view never reads as complete. Schema + the view registry live in omniseek.core.recall.graph.

FAIL-OPEN: a graph failure returns an error dict, never an exception — the graph is memory, it must NEVER break search or recall.

omniseek_sensorA

Use WHEN you want to MONITOR a query over time and be told only what's NEW — standing queries with novelty detection. ONE verb; action picks what to do.

The agent decides WHAT to monitor (judgment); the sensor diffs mechanically (a (source, source_id) fingerprint diff against baseline). Each action's REQUIRED args:

• action="create" (query; optional sources, schedule, notify) -> register a standing query that detects NEW results over time. Sensors run on their schedule automatically in the live service (hourly | daily | weekly; unknown = daily); use action="run" to trigger one manually. Returns the created sensor with its id. notify=True means the scheduler alerts when a scheduled run finds new results; optional notify_if=[keywords] narrows that alert to ONLY new results whose title/content match (notify_if_match="any" default, or "all"), so a broad standing query alerts on the sliver you care about instead of every new item. Optional detect_absence=True ALSO alerts when a tracked STABLE-source item DISAPPEARS (e.g. a page_watch policy page that goes dark / 404s); scoped to stable sources so a churny query sensor is unaffected. • action="list" -> all registered sensors with last-run stats {id, query, sources, schedule, last_run_at, last_new_count, total_runs, baseline_size}. • action="delete" (sensor_id) -> delete a sensor by id. Returns {deleted: true/false}. • action="run" (sensor_id) -> manually trigger one sensor NOW (the manual path beside the automatic scheduler): runs its query, diffs against baseline, updates state, returns a summary with new_count + new_titles. Tests a sensor on demand without waiting for its schedule.

Unknown action, or a missing required arg, returns {"error": ...}.

omniseek_rulingA

Use WHEN two graph nodes ARE (or are NOT) the same person / entity and you want views to collapse them — record / list / retract same_as | not_same_as rulings (the one judgment channel the graph's working policy applies).

OmniSeek never MAKES a ruling; it STORES yours as declarative state and APPLIES it at read time (the sensors.json precedent: judgment persisted as config OmniSeek executes mechanically). A ruling says "these two graph nodes ARE / are NOT the same entity"; omniseek_graph's working and exploratory policies then collapse (or reject) that pair when projecting a view. The pair is the KEY: it normalizes to src < dst, re-creating a pair REPLACES the prior verdict (declarative state, not a log; git history is the audit trail).

action picks what to do: • action="create" (src, dst, verdict="same"|"not_same"; optional note) -> record the ruling. Returns {created: true, ruling, replaced} (replaced=true if it overwrote a prior verdict for the pair). A bad verdict / empty or identical endpoints -> {"error": ...}. • action="list" -> {rulings: [{src, dst, verdict, note, ruled_at}], count}. • action="delete" (src, dst) -> {deleted: true/false} (false if no ruling existed for the pair).

This is a SEPARATE tool from omniseek_graph (not an omniseek_graph action) because omniseek_graph is batchable in omniseek_gather ONLY because it is read-only; folding a write into it would let the gather whitelist write. Unknown action -> {"error": ...}.

omniseek_statementA

Use WHEN you've concluded a DIRECTED, decision-relevant relation OmniSeek does NOT already store mechanically (X acquired_by Y, paper P refutes claim Q, path R requires gate S) and want the graph to carry it forward — record / list / retract typed relation statements (the general sibling of omniseek_ruling; identity types belong to omniseek_ruling).

OmniSeek never MAKES a statement; it STORES yours as declarative state and PROJECTS it at read time (the rulings / sensors.json precedent: judgment persisted as config OmniSeek applies mechanically). A statement is a DIRECTED, typed relation between two graph node ids: "openai --acquired_by--> someone", "paper X --refutes--> claim Y". It surfaces in omniseek_graph's neighborhood / between / since under working / exploratory (never conservative — the pure mechanical world) AND, since the write-side read-back, AMBIENT on any future omniseek_search hit of an endpoint (the metadata.graph.judgments stamp): recording is NOT write-only — your judgment returns to you when you next touch the node. The directed triple (src, dst, type) is the KEY, so re-creating it REPLACES the prior note; direction is YOUR assertion, never normalized.

WHAT EARNS A STATEMENT (the value gate — all three must hold, else it is noise that BURIES the edges carrying a real decision; the graph's value is inverse to its noise density):

  1. NON-MECHANICAL — a relation OmniSeek does NOT already store as a fact. cites / authored / affiliated / coauthored / published_in / about and bare bibliometric counts are the mechanical M/A world; re-asserting them here pollutes the judgment channel, which is for what an API cannot read off: YOUR read.

  2. DECISION-RELEVANT — resurfacing it would change a future call (a positioning, a gate, a disqualifier, a fit verdict, a trajectory read). A true-but-inert edge (both-about-RAG, everyone-at-lab-X-affiliated-with-X) is noise.

  3. AS-OF-STAMPED IF A SNAPSHOT — a point-in-time relation (leads / rising / froze_hiring) drifts while its endpoints stay; put the as-of date in the note, or route it to a sensor, so a future reader never mistakes a stale snapshot for the present.

type is FREE agent vocabulary (mechanically slugged: lowercase, spaces -> underscores, [a-z0-9_] only, <= 40 chars; views never branch on it). An OPEN family, NOT a menu — coin your own; some exemplars across domains: • positioning: attacks_premise_of / near_miss_of / validates_premise_of / does_not_flatten / anchors / introduces (map a competitive / thesis landscape around a claim node). • provenance / motive: sourced_from_motivated_party / covers (a source's motive; a walled or cross-lingual source covering what another missed). • DECISION-space (the non-academic half, easiest to forget): requires / blocked_by / gated_on (a blocking precondition), disqualified_by / ruled_out_because (an option-eliminator), good_fit_for / misaligned_with / froze_hiring / rising (fit + trajectory), reached ... via (a PATH-SAMPLE: how someone actually reached an outcome). Two types are REFUSED with a pointer to omniseek_ruling: same_as / not_same_as — identity is a pair-keyed, symmetric judgment the collapse machinery consumes, kept to omniseek_ruling's one channel.

MEMORY-vs-GRAPH boundary: prose understanding (a lesson, a conclusion, context, confidence, scope) is the ATOM — it lives in YOUR own notes / memory, or in this statement's note. The graph statement is a POINTER, minted only when there is a specific PAIR of wall-addressable nodes whose FUTURE retrieval must carry the judgment; its note / doc point BACK at the prose rather than restating it. Default to prose; the edge is an opt-in index. (Everything is both a thought and an edge; the test is whether two NAMED nodes must carry it forward.)

Endpoints may be ANY node id, even ones no tap minted (claim:..., org:..., inst:label:openai): a statement may pre-date the wall. Such HAND-MINTED ids FRAGMENT across sessions (claim:c3_wedge vs claim:c3_exact_wedge silently orphans the edge), so REUSE an existing id: a create echoes similar_anchors (existing near-match hand-minted ids) so you reuse one instead of minting a near-duplicate; keep a stable slug for your durable anchors.

action picks what to do: • action="create" (src, dst, type, note; optional doc) -> record. note is the REQUIRED reasoning; doc the optional provenance node id (a doc:{source}:{sid} or a note id, strongly encouraged). Returns {created, statement, replaced, similar_anchors?}. A bad type / empty endpoint / empty note / a refused identity type -> {"error": ...}. • action="list" (optional about=node id, optional type) -> {statements, count}, filtered to statements touching about and/or of type. Capped at 200 with a capped flag. • action="delete" (src, dst, type) -> {deleted: true/false}.

Like omniseek_ruling this is a SEPARATE tool from omniseek_graph (omniseek_graph stays read-only, hence batchable in omniseek_gather). Unknown action -> {"error": ...}.

Prompts

Interactive templates invoked by user choice

NameDescription
investigateParameterized investigation recipe. shape picks the WAVE 1/2 pattern: person (researcher/advisor/practitioner), lab (research group/institution), field (topic/landscape), product (tool/company/service), chase (walled-source depth-pursuit). Unknown shape falls back to the person recipe with a note.

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

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

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Battam1111/omniseek'

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