AI tool definitions
The three tools the Qaf chat agent can call, with the exact descriptions and JSON Schemas sent to the model. Typical flow: lookup_catalog to resolve a named author or book, search for passages, then expand for surrounding context.
lookup_catalog
Resolve a named author or book to canonical catalog IDs before filtering search. Returns up to five candidates, their metadata and matchScore (0–1; higher means a closer name match). Select genres directly from the search tool's filters.genres enum. These records identify sources; they are not citation evidence. Disambiguate using the question, or ask the user when ambiguous.
- Up to 5 candidates. Output is catalog metadata, not citation evidence.
Input
| Field | Type | Notes |
|---|---|---|
type | enum: author | book | |
query | string | min len 1, max len 200 |
label | string | A concise, human-readable description of the catalog lookup intent in at most 5 words, in the user's UI language. Shown in the UI only; does NOT affect catalog matching. min len 1, max len 200 |
Input JSON Schema
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"author",
"book"
]
},
"query": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "A concise, human-readable description of the catalog lookup intent in at most 5 words, in the user's UI language. Shown in the UI only; does NOT affect catalog matching."
}
},
"required": [
"type",
"query",
"label"
]
}Output JSON Schema
{
"maxItems": 5,
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "author"
},
"id": {
"type": "integer",
"exclusiveMinimum": 0
},
"label": {
"type": "string"
},
"deathYearAH": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"deathInexactLabel": {
"type": [
"string",
"null"
]
},
"matchScore": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"type",
"id",
"label",
"deathYearAH",
"deathInexactLabel",
"matchScore"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "book"
},
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"label": {
"type": "string"
},
"authorId": {
"type": "integer",
"exclusiveMinimum": 0
},
"authorLabel": {
"type": "string"
},
"deathYearAH": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
]
},
"deathInexactLabel": {
"type": [
"string",
"null"
]
},
"categoryId": {
"type": "integer",
"exclusiveMinimum": 0
},
"matchScore": {
"type": "number",
"minimum": 0,
"maximum": 1
}
},
"required": [
"type",
"id",
"label",
"authorId",
"authorLabel",
"deathYearAH",
"deathInexactLabel",
"categoryId",
"matchScore"
],
"additionalProperties": false
}
]
}
}search
Search the Qaf corpus using hybrid semantic and lexical retrieval. Resolve author/book names with lookup_catalog first. Select source genres directly from filters.genres only when the user requests a genre; a topic alone is not a genre restriction. Filters restrict authorship and metadata, not mentions in a passage. filterOperator combines filter dimensions: AND requires all dimensions; OR accepts any dimension. Values within each dimension are alternatives; date bounds always apply together. The user's selected source scope always applies. Empty results can mean no new evidence; never silently remove requested filters.
strict: false— otherwise OpenAI Responses makes every optional filter required.- Retrieves 24 semantic + 24 BM25 candidates, reranks with
rerank-v4.0-pro, delivers 5 (server-setsearchResultLimitcan raise it). - Results are de-duplicated against passages already seen in this conversation; identical calls are cached per turn.
Input
| Field | Type | Notes |
|---|---|---|
query | string | The query to search for. It can be in arabic or english min len 1, max len 2000 |
filters optional | object | |
filters.authorIds optional | integer[] | min 1, max 20 |
filters.bookIds optional | string (uuid)[] | min 1, max 20 |
filters.deathYearAH optional | object | |
filters.deathYearAH.gt optional | integer | |
filters.deathYearAH.gte optional | integer | |
filters.deathYearAH.lt optional | integer | |
filters.deathYearAH.lte optional | integer | |
filters.genres optional | enum: 40 values[] | Optional source genres. Select only when the user requests a genre; omit otherwise. min 1, max 20 |
filterOperator optional | enum: AND | OR | Combine supplied filter dimensions with AND (default) or OR. Values within each ID list always use OR; all death-year bounds must hold together. User-selected source scope is always intersected. |
label | string | A concise, human-readable description of the search intent in at most 5 words, in the user's UI language. Shown in the UI only; does NOT affect retrieval. min len 1, max len 200 |
filters.genres — 40 slugs
creedsects-and-refutationsquran-commentaryquranic-sciences-and-principles-of-exegesisquran-recitation-and-readingshadith-collectionshadith-commentaryhadith-sourcing-and-indexeshadith-defects-and-scholarly-questionshadith-sciencesprinciples-of-jurisprudencelegal-maxims-and-jurisprudencelogichanafi-fiqhmaliki-fiqhshafii-fiqhhanbali-fiqhgeneral-fiqhfiqh-issuesislamic-governance-and-judiciaryinheritance-and-willsfatwasspirituality-etiquette-and-remembrancesprophetic-biographyhistorybiographies-and-generationsgenealogygeography-and-travelarabic-languagerare-words-and-dictionariesgrammar-and-morphologyliteratureprosody-and-rhymepoetryrhetoriccollected-works-and-compilationsbibliographies-and-guidesmedicinegeneral-booksother-sciences
Input JSON Schema
{
"type": "object",
"properties": {
"query": {
"type": "string",
"minLength": 1,
"maxLength": 2000,
"description": "The query to search for. It can be in arabic or english"
},
"filters": {
"type": "object",
"properties": {
"authorIds": {
"minItems": 1,
"maxItems": 20,
"type": "array",
"items": {
"type": "integer",
"exclusiveMinimum": 0
}
},
"bookIds": {
"minItems": 1,
"maxItems": 20,
"type": "array",
"items": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
},
"deathYearAH": {
"type": "object",
"properties": {
"gt": {
"type": "integer"
},
"gte": {
"type": "integer"
},
"lt": {
"type": "integer"
},
"lte": {
"type": "integer"
}
},
"additionalProperties": false
},
"genres": {
"description": "Optional source genres. Select only when the user requests a genre; omit otherwise.",
"minItems": 1,
"maxItems": 20,
"type": "array",
"items": {
"type": "string",
"enum": [
"creed",
"sects-and-refutations",
"quran-commentary",
"quranic-sciences-and-principles-of-exegesis",
"quran-recitation-and-readings",
"hadith-collections",
"hadith-commentary",
"hadith-sourcing-and-indexes",
"hadith-defects-and-scholarly-questions",
"hadith-sciences",
"principles-of-jurisprudence",
"legal-maxims-and-jurisprudence",
"logic",
"hanafi-fiqh",
"maliki-fiqh",
"shafii-fiqh",
"hanbali-fiqh",
"general-fiqh",
"fiqh-issues",
"islamic-governance-and-judiciary",
"inheritance-and-wills",
"fatwas",
"spirituality-etiquette-and-remembrances",
"prophetic-biography",
"history",
"biographies-and-generations",
"genealogy",
"geography-and-travel",
"arabic-language",
"rare-words-and-dictionaries",
"grammar-and-morphology",
"literature",
"prosody-and-rhyme",
"poetry",
"rhetoric",
"collected-works-and-compilations",
"bibliographies-and-guides",
"medicine",
"general-books",
"other-sciences"
]
}
}
},
"additionalProperties": false
},
"filterOperator": {
"description": "Combine supplied filter dimensions with AND (default) or OR. Values within each ID list always use OR; all death-year bounds must hold together. User-selected source scope is always intersected.",
"type": "string",
"enum": [
"AND",
"OR"
]
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "A concise, human-readable description of the search intent in at most 5 words, in the user's UI language. Shown in the UI only; does NOT affect retrieval."
}
},
"required": [
"query",
"label"
]
}Output JSON Schema
{
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"text": {
"type": "string"
},
"footnotes": {
"type": "string"
},
"pages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"vol": {
"type": [
"string",
"null"
]
},
"page": {
"type": [
"number",
"null"
]
}
},
"required": [
"vol",
"page"
],
"additionalProperties": false
}
},
"book_id": {
"type": "string"
},
"author_id": {
"type": "number"
},
"version_id": {
"type": "number"
},
"sequence_number": {
"type": "integer",
"minimum": 0
},
"book_name": {
"type": "string"
},
"author_name": {
"type": "string"
}
},
"required": [
"id",
"text",
"pages",
"book_id",
"author_id",
"version_id",
"book_name",
"author_name"
],
"additionalProperties": false
}
}expand
Read up to two neighboring passages on each side of a retrieved passage. Copy book_id, version_id and sequence_number from that passage; do not guess coordinates. Citation IDs in earlier answers are not expand coordinates; search again if the passage coordinates are unavailable.
- Returns up to 4 neighbouring passages (2 each side), excluding ones already seen.
Input
| Field | Type | Notes |
|---|---|---|
book_id | string (uuid) | The book id to expand. |
version_id | integer | The version id to expand. > 0 |
sequence_number | integer | The sequence number of the chunk to expand. ≥ 0 |
Input JSON Schema
{
"type": "object",
"properties": {
"book_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "The book id to expand."
},
"version_id": {
"type": "integer",
"exclusiveMinimum": 0,
"description": "The version id to expand."
},
"sequence_number": {
"type": "integer",
"minimum": 0,
"description": "The sequence number of the chunk to expand."
}
},
"required": [
"book_id",
"version_id",
"sequence_number"
]
}Output JSON Schema
{
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"text": {
"type": "string"
},
"footnotes": {
"type": "string"
},
"pages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"vol": {
"type": [
"string",
"null"
]
},
"page": {
"type": [
"number",
"null"
]
}
},
"required": [
"vol",
"page"
],
"additionalProperties": false
}
},
"book_id": {
"type": "string"
},
"author_id": {
"type": "number"
},
"version_id": {
"type": "number"
},
"sequence_number": {
"type": "integer",
"minimum": 0
},
"book_name": {
"type": "string"
},
"author_name": {
"type": "string"
}
},
"required": [
"id",
"text",
"pages",
"book_id",
"author_id",
"version_id",
"book_name",
"author_name"
],
"additionalProperties": false
}
}What the model sees in results
searchandexpandresults go throughformatChunkForModel:author_idis dropped, andauthor_name/book_nameare always Arabic, whatever the UI locale.- When the user picks sources in the composer, a scope note (author/book IDs, genre slugs, labels) is added on every step, and every search is intersected with it.
- Execution context (locale, filters, reranker override, retrieval session) is server-owned and never part of the model's input.