Published Build3 min read
Own the citation IDs, rent the model: two RAG write-ups agree on where the contract lives
Two practitioner posts, one on ticket triage and one on catalog PDFs, put the output schema and evidence identifiers in the application and make reranking wait for an eval.
Written for builders.See today for builders

What happened
- For a property-management SaaS that must turn support tickets into structured, cited answers, the author recommends a portable model contract for embeddings and chat completions, keeping retrieval in the application, and adding reranking only after an evaluation shows first-pass semantic search is losing relevant passages.
- The least complex useful version: chunk approved support documents, generate embeddings for those chunks and the incoming question, retrieve the nearest matches, and ask a chat model to answer only from those passages.
- The application, not the model, owns the citation IDs and the final schema; that boundary matters more than an elaborate orchestration framework because a triage result can route a tenant's urgent maintenance report, expose account data to an agent, or become part of an audit trail.
- A property-support triage record needs at minimum a category, a confidence value, an escalation decision, and citations whose identifiers can be resolved back to immutable document versions.
- The model may propose values, but the backend must validate the structure, reject unknown categories, and confirm that every cited identifier came from the retrieved set; a fluent answer with a fabricated citation is a failed transaction.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
Two dev.to posts published from different domains land on the same boundary: one on turning support tickets into structured, cited answers for a property-management SaaS [1], the other on semantic search over messy B2B catalog PDFs [8]. Both treat the model vendor as a replaceable part and put the durable contract somewhere else, which inverts the question most teams start with.
The triage post's recommendation is explicit: use a portable contract for embeddings and chat completions, keep retrieval in the application, and add reranking only after an evaluation shows first-pass semantic search is losing relevant passages [1]. The minimum useful system is small - chunk approved documents, embed the chunks and the question, retrieve nearest matches, and ask a chat model to answer only from those passages [2]. According to the author, the application, not the model, owns the citation IDs and the final schema, and that boundary matters more than an elaborate orchestration framework because a triage result can route an urgent maintenance report, expose account data, or end up in an audit trail [3].
The catalog post reaches the same place through storage. It names the durable contract as the evidence record: stable document version, stable chunk identity, normalized text, page bounds, catalog identifiers, and the embedding configuration that produced the vector [9]. Upload worker, embedding adapter, and Postgres repository are treated as replaceable components around it [10]. It also splits metadata into two jobs that teams routinely merge: filter metadata narrows candidates before ranking (tenant, catalog version, locale, availability, exact SKU), while evidence metadata explains the result afterwards (filename, page range, chunk identifier, content hash, extraction version) [11]. Collapsing both into one unversioned JSON blob, the author writes, makes migrations deceptively easy and audits painfully vague [12].
The validation rules are where this stops being architecture talk. A triage record needs a category, a confidence value, an escalation decision, and citations resolvable to immutable document versions [4]; the backend validates the structure, rejects unknown categories, and confirms every cited identifier came from the retrieved set, because a fluent answer with a fabricated citation is a failed transaction [5]. The schema stays narrow: category as an enum of maintenance, billing, lease, or other; needs_human as a boolean; citations as an array of chunk IDs, with the application mapping a validated category to an approved queue rather than letting the model invent workflow actions [6].
Neither post claims exactly-once inference. The triage version gives each ticket revision a deterministic processing key such as ticket-1842-r7, records corpus version, query hash, retrieved chunk IDs, model selection, validated result and request ID, and makes the write idempotent, so a retry after a 429 may re-run inference but does not multiply the queue assignment [7][13]. The catalog version does it with a unique constraint on (tenant_id, document_version, chunk_id) inside one transaction, plus a content hash so reconciliation can tell a new version from a retry [14].
Worth noting: both are single-author recommendation posts with no measured retrieval metrics [16]. The triage author says a generic vendor matrix cannot settle regional processing, retention, and subprocessor questions, and that legal and security review must [15]. The catalog author says none of the three chunking regimes wins universally [17]. So the thing to build first is the eval that tells you whether first-pass search is actually dropping passages [1], and the thing to watch is whether your citation IDs resolve to immutable versions when someone asks why one ticket reached one queue [18].
Claim ledger
Ranked by verification strength, evidence, and original report placement.
- [1]
For a property-management SaaS that must turn support tickets into structured, cited answers, the author recommends a portable model contract for embeddings and chat completions, keeping retrieval in the application, and adding reranking only after an evaluation shows first-pass semantic search is losing relevant passages.
- [2]
The least complex useful version: chunk approved support documents, generate embeddings for those chunks and the incoming question, retrieve the nearest matches, and ask a chat model to answer only from those passages.
- [3]
The application, not the model, owns the citation IDs and the final schema; that boundary matters more than an elaborate orchestration framework because a triage result can route a tenant's urgent maintenance report, expose account data to an agent, or become part of an audit trail.
- [4]
A property-support triage record needs at minimum a category, a confidence value, an escalation decision, and citations whose identifiers can be resolved back to immutable document versions.
- [5]
The model may propose values, but the backend must validate the structure, reject unknown categories, and confirm that every cited identifier came from the retrieved set; a fluent answer with a fabricated citation is a failed transaction.
- [6]
Keep the schema narrow: category as an enum such as maintenance, billing, lease or other; needs_human as a boolean; citations as an array of chunk IDs. Do not ask the model to invent workflow actions; the application maps a validated category to an approved queue, and low-confidence or policy-sensitive cases go to a person.
Sources & coverage · 1 publisher
The reporting this story was synthesized from, earliest first. Every link goes to the original.
- dev.toZylahMorn61835Aug 12Why I Chose PDF RAG Chunking and Metadata for Catalog Semantic Search
Cited in this coverage: dev.to post by irvincole5861
Cited in this coverage: dev.to post by zylahmorn61835
- dev.toIrvinCole5861Aug 12Direct Providers vs Portable Contracts — Ask-Your-Docs Semantic Search for SaaS RAG

