$ cat workspace-template.yaml
Unified Ontology Retrieval
// Answer a question with unified retrieval over the governed organization ontology: a lexical entity search and a semantic KB chunk search run in parallel, the chunk hits are bridged onto the knowledge graph, the two entity lists are fused with Reciprocal Rank Fusion, and a grounded, cited answer is synthesized from the chunks plus the fused entity ranking.
// Canvas Preview
// Instruction
Unified Ontology Retrieval
Overview
This workspace answers a question by fusing TWO retrieval entries over the governed organization ontology: a lexical entity search (Ontology Search) and a semantic content search over the KB's document chunks (KB Semantic Search). The semantic hits are bridged onto the knowledge graph (Ontology From Documents), the two entity lists are fused with Reciprocal Rank Fusion (Merge Ranked Lists), and Knowledge Synthesizer writes a grounded, cited answer from the retrieved chunks plus the fused entity ranking. Every path is permission-gated inside its backing API — the graph only wires governed primitives. All five nodes are read-only: this template has NO side-effect terminals.
Workflow Chain
Query Crafting (MANDATORY - do this BEFORE filling any node input)
The corpus (documents AND ontology entity names) is mostly Italian with some English; users ask in any language. Derive the node inputs from the user's question - never paste it verbatim into the search nodes:
- Extract the TOPIC terms (the subject, e.g. "cyber security"). NEVER drop them - a query reduced to generic words ("chi e il responsabile") retrieves noise.
- TRANSLATE the topic terms into Italian (primary) and English (secondary), whatever the user's language (Chinese, Italian, English, ...).
- Ontology Search.query - distinguish TWO cases (first variant ranks first): a) The question NAMES an entity (MAECI, Tajani, ...): variants = ONLY names/aliases/ translations of THAT entity, entity name FIRST: "Ministero degli Affari Esteri | Ministry of Foreign Affairs | MAECI". NEVER mix in relation/topic words - WRONG: "istituzioni supervisionate | MAECI" (the topic phrase becomes the top lexical hit and the pipeline profiles the wrong entity). Relation words go ONLY in KB Semantic Search. b) No named entity (thematic question): Italian and English TOPIC keywords as variants: "sicurezza cibernetica | cyber security". Never a question, no question words, no verbs, never the user's language alone.
- KB Semantic Search.query = a short Italian topic phrase (e.g. "chi si occupa di sicurezza cibernetica") - keep the topic words in it.
- Knowledge Synthesizer question = the user's ORIGINAL question, VERBATIM AND UNTRANSLATED
- translation applies ONLY to the search nodes (rules 2-4), NEVER here. Append this suffix: "Answer in the same language as this question." ALSO set the synthesizer's Response Language input to the language the user TYPED the question in (e.g. "中文", "Italiano", "English") - NEVER the corpus language. WRONG (observed): user asked in Chinese, agent passed "In quali eventi è intervenuto Tajani" with Response Language "Italiano" - the answer came back in Italian.
- COUNT / relationship questions ('quante persone...', 'chi lavora presso...') are answered by the Ontology Entity 360 node: it receives the TOP fused entity automatically and feeds its exact per-link-type counts (e.g. 'employed_by (incoming): 18') into the synthesizer. Do NOT let the synthesizer say 'cannot determine' when the Entity profile block in its context carries the count - the graph numbers are EXACT and gated, prefer them over document-chunk guesses.
Node Reference
- Ontology Search (input) — full-text search of ontology objects. Configurable inputs:
query(the entity terms),type(optional object-type filter, blank = all),mode(N2 retrieval arm:entitydefault = match by NAME, this flow's entity entry;schema/hybridreach the graph by RELATIONSHIP/THEME via matching types — leave atentityfor this template's Query Crafting, since thematic questions reach the graph through the KB→document bridge, and only setschema/hybridwhen the user explicitly asks the entity arm to search by relationship/theme),limit(default 10). Outputresultsfeeds Merge Ranked ListslistA. - KB Semantic Search (input) — vector search over KB document chunks. Configurable inputs:
query(thematic phrasing),k(default 100 — fetch WIDE; the rerank threshold, not k, is the precision filter),driveItemIds(optional Drive scope — folder and/or file ids, folders cover their whole subtree; empty = everything accessible). OutputchunkTextsfeeds Knowledge Synthesizercontext; outputdocumentIdsfeeds Ontology From Documents. - Ontology From Documents (process) — bridges document ids onto the graph: the ontology objects appearing in those documents, ranked by appearance frequency and connectivity, plus the links among them. Input
documentIdscomes from KB Semantic Search. Configurable inputs:limit(default 25),includeLinks(default true). Outputentitiesfeeds Merge Ranked ListslistB; outputtruncatedflags a cut page. - Merge Ranked Lists (process) — Reciprocal Rank Fusion of
listA(lexical entities) andlistB(bridge entities); items surfacing in both rank highest. Configurable inputs:idKey(default "id"),k(RRF constant, default 60),limit(default 25). Outputitemsis the fused ranking; outputitemsTextis its readable digest and feeds Knowledge Synthesizercontext. - Knowledge Synthesizer (process) — writes the grounded, cited answer for
queryfrom the fan-incontext(chunk texts + fused-entity digest). Configurable inputs:llmModelId(empty = the workspace's admin-configured default),language(default Italian). Outputtextis the final answer.
Execution Strategy
You MUST complete all 3 phases in order: Phase 1 → Phase 2 → Phase 3. Do NOT skip any phase.
Phase 1 — Configure
- Make ONE
requestUserDecisioncall bundling every input as separate questions: (a) the question to answer; (b) optional entity terms (names/acronyms such as "MAECI", "DGSD") if they differ from the thematic phrasing; (c) optional KB folder scope (yes/no — pick the folder later only if yes); (d) response language (default Italiano). Keep the free-text box as the last option. Do not prompt again after this. - Use
nodeFinderto get the fresh ids of the five nodes — ids from the template preview are stale after cloning. - Apply the answers with ONE
batchUpsertNodescall: set Ontology Searchqueryto the entity terms (or the full question when none were given); set KB Semantic Searchqueryto the thematic phrasing (or the full question); set Knowledge Synthesizerqueryto the full question andlanguageto the chosen language; if a folder scope was requested, callselectDriveItemand set KB Semantic SearchdriveItemIdsto[<folder id>]. Every{{query}}placeholder MUST be replaced in this step. Phase 1 complete. Now proceed to Phase 2.
Phase 2 — Run
- Execute the pipeline with
nodeExecutoron the Knowledge Synthesizer node — the wired upstream nodes (both entries, the bridge, the fusion) resolve automatically. - Read the results with
getNodeOutput: Knowledge Synthesizertext(the answer), Merge Ranked ListsitemsText(the fused entity ranking), and Ontology From Documentstruncated(whether the entity page was cut). If the answer says no context was available, check KB Semantic Search's outputs before reporting failure. Phase 2 complete. Now proceed to Phase 3.
Phase 3 — Verify and follow up
- Run
verification, then present the answer with its citations followed by the fused entity ranking. Iftruncatedwas true, say the entity list was cut at its limit and offer to raise it. - In
followUp, offer to: (a) expand a top fused entity one hop by adding an Ontology Traverse node (upsertNode, wire the entity id intoobjectId, choose alinkTypeseen in the bridge's links output); (b) re-run with sharper entity/theme terms; (c) narrow or widen thedriveItemIdsscope. Nothing in this template writes outside the graph, so no write confirmation is needed.
Configuration Tips
Error Handling
- Ontology Search fails with "query not provided" — a
{{query}}placeholder was left unreplaced. Re-do step 3. - KB Semantic Search returns empty outputs — nothing accessible matched. The bridge and the fusion degrade cleanly (empty lists) and the synthesizer will say the sources are missing; rephrase the thematic query, lower
rerankThreshold, or drop thedriveItemIdsscope. - Ontology From Documents returns empty entities despite documentIds — those documents mention no accessible ontology objects; the lexical branch still feeds the fusion, so the run is still valid.
- Knowledge Synthesizer answers "No context chunks available" — both context edges delivered nothing; inspect the upstream outputs from step 5 before re-running.
- A node fails with an authentication error — the workspace owner's token cannot reach the ontology/knowledge APIs; verify the workspace credentials, then re-run.
// Dependencies
1from input import OntologySearch # v1.4.02from input import KBSemanticSearch # v1.4.03from process import OntologyFromDocuments4from process import MergeRankedLists # v1.3.05from process import KnowledgeSynthesizer # v1.6.06from process import OntologyEntity360 # v1.0.1// Variables
1query:2 type: undefined3 label: "Query"4 description: "The user's question, verbatim and IN THE USER'S LANGUAGE. Do NOT bake it directly into the search nodes - the instruction's Query Crafting rules derive per-node queries from it (topic terms preserved, translated to Italian/English); the original goes to Knowledge Synthesizer so the answer comes back in the user's language."5 required: undefined$ git log --oneline
Ontology Search + Merge Ranked Lists 1.3.0 (B-prime lexical anchor): search now tags each hit `lexical` when the query terms are in the entity's name/keywords_en (not just a vector description-mention); merge.topId anchors to the top lexical list-A hit, skipping vector-only mentions, so Ontology Entity 360 profiles the entity the question names. Observed M1 (2026-07-21): a certification whose description_en mentioned the ministry surfaced via profile_vector kNN and ranked entity-search #1, so the old list-A-rank-1 anchor profiled it instead of MAECI.
Ontology Search + Merge Ranked Lists 1.3.0 (B-prime lexical anchor): search now tags each hit `lexical` when the query terms are in the entity's name/keywords_en (not just a vector description-mention); merge.topId anchors to the top lexical list-A hit, skipping vector-only mentions, so Ontology Entity 360 profiles the entity the question names. Observed M1 (2026-07-21): a certification whose description_en mentioned the ministry surfaced via profile_vector kNN and ranked entity-search #1, so the old list-A-rank-1 anchor profiled it instead of MAECI.
Ontology Search + Merge Ranked Lists 1.3.0 (B-prime lexical anchor): search now tags each hit `lexical` when the query terms are in the entity's name/keywords_en (not just a vector description-mention); merge.topId anchors to the top lexical list-A hit, skipping vector-only mentions, so Ontology Entity 360 profiles the entity the question names. Observed M1 (2026-07-21): a certification whose description_en mentioned the ministry surfaced via profile_vector kNN and ranked entity-search #1, so the old list-A-rank-1 anchor profiled it instead of MAECI.
Ontology Search + Merge Ranked Lists 1.3.0 (B-prime lexical anchor): search now tags each hit `lexical` when the query terms are in the entity's name/keywords_en (not just a vector description-mention); merge.topId anchors to the top lexical list-A hit, skipping vector-only mentions, so Ontology Entity 360 profiles the entity the question names. Observed M1 (2026-07-21): a certification whose description_en mentioned the ministry surfaced via profile_vector kNN and ranked entity-search #1, so the old list-A-rank-1 anchor profiled it instead of MAECI.
Ontology Search + Merge Ranked Lists 1.3.0 (B-prime lexical anchor): search now tags each hit `lexical` when the query terms are in the entity's name/keywords_en (not just a vector description-mention); merge.topId anchors to the top lexical list-A hit, skipping vector-only mentions, so Ontology Entity 360 profiles the entity the question names. Observed M1 (2026-07-21): a certification whose description_en mentioned the ministry surfaced via profile_vector kNN and ranked entity-search #1, so the old list-A-rank-1 anchor profiled it instead of MAECI.
Query Crafting rule 3 split: entity-named questions use entity-name variants only (M3-ZH topic-phrase anchor poisoning); ontology-search 1.2.1
topId anchor = list A rank 1 (merge 1.2.0); dep versions synced (entity-360 1.0.1, synthesizer 1.6.0)
1.1.0 (2026-07-19): query-crafting rules (translate to corpus language, keywords not questions, topic terms preserved) + answer in the user's language. Observed failures: an Italian run dropped the topic from every query; a Chinese run pasted the raw question into lexical entity search and got an Italian answer. 1.1.1 (2026-07-19): version realignment with the marketplace (manual re-import; same content as 1.1.0's query-crafting release). 1.2.0 (2026-07-19): Ontology Search 1.2.0 multi-variant pipe queries ('italiano | english'); instruction mandates the pipe pattern and setting the synthesizer's Response Language to the user's language.
1.1.0 (2026-07-19): query-crafting rules (translate to corpus language, keywords not questions, topic terms preserved) + answer in the user's language. Observed failures: an Italian run dropped the topic from every query; a Chinese run pasted the raw question into lexical entity search and got an Italian answer. 1.1.1 (2026-07-19): version realignment with the marketplace (manual re-import; same content as 1.1.0's query-crafting release). 1.2.0 (2026-07-19): Ontology Search 1.2.0 multi-variant pipe queries ('italiano | english'); instruction mandates the pipe pattern and setting the synthesizer's Response Language to the user's language.
1.1.0 (2026-07-19): query-crafting rules (translate to corpus language, keywords not questions, topic terms preserved) + answer in the user's language. Observed failures: an Italian run dropped the topic from every query; a Chinese run pasted the raw question into lexical entity search and got an Italian answer. 1.1.1 (2026-07-19): version realignment with the marketplace (manual re-import; same content as 1.1.0's query-crafting release). 1.2.0 (2026-07-19): Ontology Search 1.2.0 multi-variant pipe queries ('italiano | english'); instruction mandates the pipe pattern and setting the synthesizer's Response Language to the user's language.
1.1.0 (2026-07-19): query-crafting rules (translate to corpus language, keywords not questions, topic terms preserved) + answer in the user's language. Observed failures: an Italian run dropped the topic from every query; a Chinese run pasted the raw question into lexical entity search and got an Italian answer. 1.1.1 (2026-07-19): version realignment with the marketplace (manual re-import; same content as 1.1.0's query-crafting release). 1.2.0 (2026-07-19): Ontology Search 1.2.0 multi-variant pipe queries ('italiano | english'); instruction mandates the pipe pattern and setting the synthesizer's Response Language to the user's language.
1.1.0 (2026-07-19): query-crafting rules (translate to corpus language, keywords not questions, topic terms preserved) + answer in the user's language. Observed failures: an Italian run dropped the topic from every query; a Chinese run pasted the raw question into lexical entity search and got an Italian answer.
1.1.0 (2026-07-19): query-crafting rules (translate to corpus language, keywords not questions, topic terms preserved) + answer in the user's language. Observed failures: an Italian run dropped the topic from every query; a Chinese run pasted the raw question into lexical entity search and got an Italian answer.