| 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 • 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): 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. 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. 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": ...}. |