Ground AI answers in your own docs and data model
| You end up with | Your documents imported into a Beacon project and, in full Beacon, your DbContext exposed as a read-only data source, plus a check that an agent finds both |
| Time | about 25 minutes |
| You need | An application with Beacon wired in (MCP gateway or Integrate Beacon), Markdown files in your repository, and for the data model part full Beacon with an EF Core DbContext and a read-only database login |
| Applies to | Beacon 5.0 · Both. Documents: gateway and full Beacon. ExposeDbContext, the glossary and golden examples: full Beacon only, because the gateway has no data sources and no SQL tools |
Before you start
Section titled “Before you start”| Decision | Options | Default |
|---|---|---|
| Where the documents live | A folder copied to the output, or embedded in the assembly | Embedded, so the deployment cannot lose them |
| Expose the data model | Yes (full Beacon only), or documents only | Documents only |
| Tables an agent may read | An explicit allow-list | None: ExposeDbContext is default-deny |
| Columns hidden or masked | Excluded (invisible) or masked (visible, values ***) | Mask national ids and account numbers, exclude secrets |
1. Write documents that ground well
Section titled “1. Write documents that ground well”Each document is split into overlapping sentence windows (5 sentences, 1 overlap, by default), so a paragraph is retrieved on its own. Write for that.
- One topic per page, with a
title:in the frontmatter (else the first#heading is used). - Each paragraph makes sense without the paragraphs around it: name the thing in full instead of “it”.
- Use the words your people use in questions, and say once what they mean: “active customer means …”.
- Put definitions, rules and “where to find it” first, narrative last.
- State units, time zones and currencies.
- Keep each file under 512 KB (the default
MaxDocumentBytes; larger files are skipped with a warning). - No secrets, no personal data, no real customer names. The documents are readable by every caller who can read the project.
Only .md, .markdown and .txt files are imported.
2. Ship the documents
Section titled “2. Ship the documents”Embed them in the assembly:
<ItemGroup> <EmbeddedResource Include="..\docs\wiki\**\*.md" LogicalName="docs/wiki/%(RecursiveDir)%(Filename)%(Extension)" /></ItemGroup>The LogicalName is required: without it MSBuild mangles folder names and joins them with dots. To copy a folder
instead, see Shipping the documents.
3. Register the documents
Section titled “3. Register the documents”In the gateway:
builder.Services.AddBeaconMcpGateway(builder.Configuration, x =>{ // ... x.Docs(y => y.FromEmbeddedResources(typeof(Program).Assembly, "docs/wiki/"));});The gateway sets the project name for you and syncs the host project the first time it is needed. You add no startup call.
In full Beacon:
var beacon = builder.Services.AddBeaconServices(builder.Configuration, o => { /* your options */ });
beacon.ExposeDocs(o =>{ o.ProjectName = "Back Office"; // the project every Expose* call of this host uses o.FromEmbeddedResources(typeof(Program).Assembly, "docs/wiki/"); // or o.FromDirectory("docs/wiki").Exclude("drafts/**");});
beacon.UseSqlServer(); // ends the builder chain: call ExposeDocs before it
var app = builder.Build();// ... apply migrations ...await app.Services.SyncBeaconHostAsync(); // data sources first, then documentsSyncBeaconHostAsync is idempotent: a document whose content hash is unchanged is left alone, a changed one is
updated and re-chunked, a removed file is archived. It is safe to run from several replicas at once.
4. Expose the data model (full Beacon only)
Section titled “4. Expose the data model (full Beacon only)”Skip this step in the gateway: it has no data sources, so there is nothing for ExposeDbContext to attach to and no
SQL tool to ground.
beacon.ExposeDbContext<ShopDbContext>(o =>{ o.Name = "Shop"; o.ProjectName = "Back Office"; // the same project as ExposeDocs o.ReadOnlyConnection("BeaconReadOnly") // ConnectionStrings:BeaconReadOnly, a read-only login .AllowTables("Loan", "LoanInstallment", "Customer") .ExcludeColumns(x => x.Table == "Customer" && x.Name.StartsWith("Kyc")) .MaskColumns(x => x.Name is "SSN" or "AccountNumber");});Beacon reads the tables, columns, keys and foreign keys from the EF model without opening a connection, and takes
descriptions from HasComment or, with GenerateDocumentationFile on, from your XML <summary> comments. Write
those comments in business words: they become the column and table descriptions the agent reads. Columns whose names
contain password, secret, token and similar words are excluded whatever you write. See
Host DbContext for every option.
5. How it reaches agents
Section titled “5. How it reaches agents”| Tool | What the agent gets from your material |
|---|---|
search | Documents as [IMPORTED_DOC] hits with their path and title, found by keyword, and by meaning when embeddings are enabled. Tables and columns too, in full Beacon. |
get_documentation | The project-level answer ends with a list of your documents. document takes a path or an exact title and returns that document in full. datasource_name, table_name and schema_name narrow to the data model. |
get_context | format: "agents_md" returns a project brief: data sources, key tables, glossary terms, document titles and how to use the tools. Built from the catalog, with no LLM call. |
ask (full Beacon) | A conceptual question is answered from project documentation, including your documents; a data question is grounded in the schema, sample values, glossary and verified examples. |
get_query_context (full Beacon) | The same grounding context ask would use, so an agent can write its own SQL. |
Documents work with no LLM and no embedder: keyword search matches title, path and chunk text. Embeddings, when configured, add meaning-based matching (Semantic retrieval).
6. Teach the vocabulary and verified answers (full Beacon only)
Section titled “6. Teach the vocabulary and verified answers (full Beacon only)”Two kinds of grounding are curated by an Admin after the data source exists:
- Business glossary: terms, synonyms and a metric expression, through
/beacon/api/glossary(API only, no page). The top matches (GlossaryTopK, default 5) enter the prompt. See Business glossary. - Golden examples: human-verified question to SQL pairs. An Admin promotes an answer rated
correcton the MCP Learning page (/beacon/mcp-learning, tab Golden candidates). The top matches (GoldenExemplarTopK, default 4) enter the prompt as authoritative. See Golden examples.
Both are scoped to the project, so another project that shares the data source never sees them.
Check it works
Section titled “Check it works”- Startup completes. In full Beacon
SyncBeaconHostAsyncran after migrations. -
GET /beacon/api/projects/{id}/imported-documentsreturns your documents (needs Read in the project). - Connect an MCP client (Connect Claude Code, Cursor or VS Code) and say this:
Search the Back Office project for "active customer" and show me which documents match.Then read the best match in full with get_documentation.-
searchanswers with an[IMPORTED_DOC]line for your page, andget_documentationwithdocumentset to its path returns the text. - Full Beacon only:
get_documentationwithtable_namereturns the descriptions you wrote, and masked columns are flagged as masked. - Change one sentence in a document, redeploy, and the new text comes back from
get_documentation.
If something goes wrong
Section titled “If something goes wrong”| Symptom | Cause and fix |
|---|---|
| No documents are listed | The sync has not run (full Beacon: call SyncBeaconHostAsync after migrations), the folder is wrong, or the glob matched nothing. A configured directory that does not exist fails startup. |
Folder names look like _40_web or the path has dots | The embedded resources have no LogicalName. Set it as in step 2. |
| A file is missing and the log has a size warning | It is over MaxDocumentBytes (512 KB). Split it. |
| Two files with names that differ only by case, one missing | Paths compare ignoring case; the second is skipped with a warning naming its path. Rename one. |
The project is called Back Office (host) | A project that is not host-managed already had that name. The host project is created beside it. See The host project. |
search finds nothing for a paraphrase | Embeddings are off, so matching is by keyword. Use the people’s own words in the document or enable embeddings. |
| A table is not visible to the agent | It is not in AllowTables / AllowEntity, or the caller cannot read the project. |
| A query on a host data source is refused for an unqualified table | Host data source SQL must be a single SELECT with schema-qualified table names, such as dbo.Customer. |
- Host docs: every option, the sync rules and the REST routes for imported documents.
- Host DbContext: the allow-list, masking and the execution-time policy.
- Knowledge base and SQL grounding: what goes into an
askprompt and who curates it. - Ask your data questions: use the grounding you just built.