Start here

Start with a corpus

Define the information you want to search, divide it into understandable datasets, inspect representative records, and collect real questions.

Name the corpus

Begin with the body of information you want people or applications to search. Give the corpus a name and state the subject or work it covers.

A corpus may include documents, database exports, messages, recordings, images, and other sources. The Concepts page defines corpus and the rest of the CoreCortex vocabulary in one place.

Write down the purpose

Write one page that a subject-matter expert can review. State what data belongs in the corpus, who will search it, what they need to decide, and which mistakes would be costly.

  • Domain: the body of knowledge and activity represented by the corpus.
  • Users: people or agents that will ask questions and consume evidence.
  • Decisions: research, review, action, or synthesis the evidence should support.
  • Boundaries: content, time periods, jurisdictions, products, languages, and exclusions.
  • Trust: reliable sources, access restrictions, retention, and when the system should say that it found nothing.

Inventory datasets and modalities

List each dataset inside the corpus separately. Record its structure, refresh pattern, authority, access policy, and likely retrieval needs.

QuestionWhat to capture
What is it?Source purpose, owner, format, modality, language, and time coverage
What does one item mean?Record identity, business meaning, updates, and deletion semantics
What carries meaning?Text, fields, tables, images, audio segments, relationships, and temporal order
Who may see it?Tenant, matter, role, jurisdiction, consent, or other access boundary
How does it change?Refresh cadence, late arrivals, corrections, versions, and source authority

Read representative records

Open several items from every dataset before designing search. Include common records, unusually long records, sparse records, restricted records, and records that have changed over time.

Ask a person who knows the subject to explain what one item means, which fields matter, how versions work, and which source should win when two records disagree.

Collect real questions

Ask users for questions they already need answered. Include identifier lookups, paraphrases, filters, comparisons, relationship questions, and questions whose answer is absent. Later, reviewers will mark which passages should answer each question.

Read several real records with the questions beside you. A field profile can count missing and repeated values. A subject-matter expert still needs to explain what those values mean.

Create corec.yaml from your source

corec init reads a document directory, CSV, XLSX, or JSONL file and writes a valid corec.yaml. For raw sources, you provide the acquisition date and either an allow list or an explicit public choice. Repeat --attribute-column for CSV or XLSX fields that retrieval must filter. The command prints both access and empty-attribute review warnings.

shellCoreCortex Core
corec init \
  --name reference-corpus \
  --dataset reference-documents \
  --source /absolute/path/to/source-documents \
  --pattern '**/*.xml' \
  --record-type reference_document \
  --title-element title \
  --provider "reference document export" \
  --observed-at 2026-08-29T00:00:00Z \
  --allow group:readers \
  --output .corec/reference-corpus/corec.yaml

corec validate .corec/reference-corpus/corec.yaml
corec source normalize \
  --config .corec/reference-corpus/corec.yaml \
  --dataset reference-documents \
  --output .corec/reference-corpus/records.jsonl

Register, ingest, and check access

Runtime commands use UUIDs returned by PostgreSQL. A tenant slug, corpus name, or dataset name cannot replace one of these IDs. Provision the tenant, apply corec.yaml, inspect the corpus, then copy each returned ID into the next command.

Core ingestion runs the chunker and projections in the active configuration. Core retrieval accepts a principal and applies access before returning evidence. Enterprise query routing is an optional step before this retrieval call.

The local vector index is process-local. Before vector retrieval, Core compares it with the active canonical fragments in PostgreSQL. A new process, external ingestion, or deletion triggers a refresh; an unchanged projection stays in memory. Separate ingest and query commands therefore run semantic retrieval without a vector service. Use a persistent adapter when this refresh work becomes material.

shellCoreCortex Core
export DATABASE_URL=postgresql://dbuser@localhost/postgres
corec db migrate
corec tenant provision --slug tutorial-team --display-name "Tutorial team"
export TENANT_ID=<tenant-uuid-from-output>

corec apply \
  --tenant-id "$TENANT_ID" \
  --actor analyst@example.com \
  --idempotency-key reference-config-v1 \
  .corec/reference-corpus/corec.yaml
export CORPUS_ID=<corpus-uuid-from-output>

corec corpus inspect --tenant-id "$TENANT_ID" --corpus-id "$CORPUS_ID"
export DATASET_ID=<dataset-uuid-from-output>

corec ingest \
  --tenant-id "$TENANT_ID" \
  --corpus-id "$CORPUS_ID" \
  --dataset-id "$DATASET_ID" \
  --actor analyst@example.com \
  --idempotency-key reference-records-v1 \
  .corec/reference-corpus/records.jsonl

corec query retrieve \
  --tenant-id "$TENANT_ID" \
  --corpus-id "$CORPUS_ID" \
  --plan default \
  --principal group:readers \
  --query "How is source identity preserved?"

What happens next

Normalize the records, create searchable passages, and run a simple keyword baseline. Have reviewers mark the expected passages for a small set of questions. Then compare chunking, embedding models, and search methods. Test generated answers separately from search.

The tutorial shows this process with a prose dataset and a structured dataset.

Continue readingConcepts→