Which Records Should Botie Bring into the Conversation?
The manual collection is larger than one request can hold. Select permitted evidence, leave room for the reply, and keep each excerpt attached to its source.
15 sections · 4 questions · 1 coding challenge
The arrow keys move between sections too.
A Model Could Read Retrieved Material at Answer Time
BOTIE
Our workshop isolates a later application problem: given ranked candidate passages, which may enter this request and which fit? It does not reproduce the paper’s learned retrieval or training procedure. That separation lets us inspect permission and budgeting mistakes without disguising a deterministic list operation as semantic search.
Sources for this history
The Relevant Page Is Buried in a Room Full of Manuals
A technician asks about a seal on P-2. Botie has maintenance manuals for several sites, years of service tickets, and a limited amount of text it can send in one model request. Copying everything would include irrelevant records and perhaps records this technician is not allowed to read.
We need to choose what enters the conversation. This means finding useful material, respecting permissions, and preserving enough of its identity to check the eventual answer.
The supplied token counts are invented whole counts. This workshop does not tokenize text or call a retriever.
Step 1 of 2
Keep source identity beside each passage
These candidates are already ordered by a separate retriever. The first one is not permitted for the current caller.
| Source ID | Asset | Supplied token cost | May this caller read it? |
|---|---|---|---|
| M9 | P-9 | 4 | No |
| M2a | P-2 | 6 | Yes |
| M2b | P-2 | 5 | Yes |
M9
- Asset
- P-9
- Supplied token cost
- 4
- May this caller read it?
- No
M2a
- Asset
- P-2
- Supplied token cost
- 6
- May this caller read it?
- Yes
M2b
- Asset
- P-2
- Supplied token cost
- 5
- May this caller read it?
- Yes
Step 2 of 2
Allocate the window before adding excerpts
The model input and possible answer share a finite allowance in this teaching budget.
| Allocation | Tokens | Purpose |
|---|---|---|
| Total window | 20 | Request and answer allowance |
| Reserved input | 8 | Instructions, question, tool descriptions and message overhead |
| Answer reserve | 4 | Room for generated output |
| Available evidence | 8 | Whole candidate passages |
Total window
- Tokens
- 20
- Purpose
- Request and answer allowance
Reserved input
- Tokens
- 8
- Purpose
- Instructions, question, tool descriptions and message overhead
Answer reserve
- Tokens
- 4
- Purpose
- Room for generated output
Available evidence
- Tokens
- 8
- Purpose
- Whole candidate passages
Context is selected evidence with a boundary
Permission filtering must happen before this prefix is packed. Reserving output and input keeps the final evidence allocation explicit.
Which source IDs survive the request budget?
Filter candidate passages by asset permission before taking the ordered prefix that fits. Try a passage that consumes the remaining room exactly.
BOTIE
Selected source IDs in order
- 0M2a
Follow the operations
1. Ranked candidate excerpts with supplied costs
[ { "id": "M9", "asset": "P-9", "tokens": 4, "text": "P-9 installation." }, { "id": "M2a", "asset": "P-2", "tokens": 6, "text": "P-2 seal inspection." }, { "id": "M2b", "asset": "P-2", "tokens": 5, "text": "P-2 bearing inspection." } ]2. Assets this caller may read
- 0P-2
3. Keep permitted records
[ { "id": "M2a", "asset": "P-2", "tokens": 6, "text": "P-2 seal inspection." }, { "id": "M2b", "asset": "P-2", "tokens": 5, "text": "P-2 bearing inspection." } ]4. Total token allowance
20
5. Non-evidence input reserve
8
6. Subtract
12
7. Output token reserve
4
8. Subtract
8
9. Take a prefix within budget
[ { "id": "M2a", "asset": "P-2", "tokens": 6, "text": "P-2 seal inspection." } ]10. Read a field from every record
- 0M2a
11. Result
- 0M2a
Costs are supplied, ranking is already done, and the prefix rule is deliberately simple. No selected-ID list proves relevance or factual support.
1. Separate retrieving a candidate from selecting context
Retrieval produces candidates likely to help answer a question. A lexical search can match words; an embedding search can compare representations; a reranker can reorder candidates using another scoring method. These methods have different failure cases. None automatically knows every application permission or guarantees that a passage answers the question.
Our inputs begin after ranking. We receive records containing an ID, an asset, text and a supplied token cost. Selection decides which permitted records reach the model. Keeping those stages distinct lets us ask whether a failure came from missing candidates or from discarding useful candidates later.
A relevant-looking passage about a different pump can be dangerous if the asset identity is lost during selection.
2. Filter by permission before constructing the request
The authenticated caller’s scope determines which records are eligible. Apply access restrictions during retrieval where supported, and enforce them before selected content reaches the model or any externally visible log. A prompt saying “do not reveal restricted manuals” is too late if the service already sent the restricted text.
In this example, a record is eligible when its asset occurs in an authoritative allowed list. A real document system may require organisation, role, document version and operation-specific checks. Asset membership is our deliberately small permission model.
The workshop lets you inspect the candidate records locally. Its fixtures contain no private documents; they illustrate where an application would enforce the boundary.
3. Reserve space for the parts we cannot discard
A model request contains more than excerpts. Instructions, the question, tool schemas and conversation messages all consume context. The reply may need an allowance as well, depending on the model’s limit semantics. Start by measuring or reserving those parts, then decide how much remains for evidence.
Our invented accounting uses one total window and explicit input and output reserves. Costs are supplied whole-token counts; word count is not token count. Message wrappers and formatting can add overhead, so a production implementation should count the final serialised request with the correct model tokenizer and leave margin where needed.
Total allowance = 20 tokens
Reserved non-evidence input = 8 tokens
Reserved output = 4 tokens
Evidence allowance = 20 − 8 − 4 = 8 tokensIf reserves exceed the total, reject the configuration or deliberately shorten something. Do not silently call the remaining budget zero and claim the request fits.
4. Choose a packing rule and admit what it leaves out
After filtering, our rule keeps complete records in ranked order until the next record would exceed the available budget. It stops at that point. This preserves a prefix of the ranking and avoids chopping a sentence in half.
It can waste room. If the first permitted passage is too large, a shorter passage later in the list will not be selected. Skipping oversized passages, compressing them, or changing chunk sizes are different policies with their own tradeoffs. State which policy you use so a test can distinguish an intended choice from a bug.
Permitted passage costs = [6, 5]
Evidence allowance = 8
Take the first passage: used = 6
The next total would be 6 + 5 = 11
11 exceeds 8, so stopThe result contains one source. We have made a budget decision, not shown that the remaining source is sufficient to answer the question.
Keep an ordered prefix of simple costs
This small program demonstrates the budget rule without permissions or document records. Notice that it stops instead of skipping to the last item.
costs = [3, 8, 2]
budget = 7
used = 0
selected = []
for position, cost in enumerate(costs):
if used + cost > budget:
break
selected.append(position)
used += cost
print(selected)
print(used)[0]
3The final cost of 2 would fit on its own, but this chosen prefix policy never reaches it.
Check yourself
Questions on Parts 1 to 4
Question 1 of 2
Which passage positions are selected?
Use the information below.
Total allowance is 30 tokens, reserved input is 10, and reserved output is 5. Permitted passages in order cost [8,9,2]. Use the stop-at-first-overflow prefix policy.5. Carry the citation through every transformation
A passage should retain its source ID, document version and useful location such as a page or section. If it is split, keep the chunk-to-document mapping. If it is summarised, retain the underlying evidence and make the summary’s status clear. Otherwise an answer can name a document without giving anyone a way to check the relevant text.
A citation ID proves only that the answer points somewhere. Check whether the cited material supports the claim, refers to the right asset, and was available to the user. An outdated manual can be perfectly cited and still inappropriate for the current machine.
The workshop outputs IDs from the selected records. Read the corresponding text in the input records to inspect what the model would actually receive.
6. Treat retrieved instructions as document content
A service ticket may contain an instruction directed at the assistant. A manual page might even include a quoted conversation. Keep that text labelled as evidence, as we did in the prompt lesson. It must not change the application’s tool permissions or approval state.
Retrieval makes prompt injection a practical data-flow problem: content from outside the application enters the model’s input. Restrict available tools and validate their calls regardless of how convincing the generated explanation sounds. If a task only needs an answer from manuals, do not grant it a general-purpose write tool.
Encoding the document cleanly helps inspection, but it does not establish that a model will respect the data boundary.
7. Decide what the conversation should remember
Conversation history can consume the same room as evidence. An old summary may omit a qualification or carry forward an earlier mistake. Keep durable facts separate from provisional model statements, and preserve source links for facts that need verification.
A short-lived conversation state is different from a long-term user memory. Decide which values should persist, who may see them, how corrections replace stale values, and when they expire. Loading every past message is a memory policy, even if it was chosen accidentally.
For this maintenance task, the asset ID and current question matter. An unrelated ticket from last week should not displace the manual excerpt needed now.
8. Measure missing evidence before changing the prompt
When an answer fails, inspect the selected records. Was a relevant passage retrieved? Was it authorised? Did it fit? Did the selected text actually contain the needed fact? A prompt change cannot recover evidence that the request never contained.
Evaluate retrieval coverage on labelled questions separately from answer support. Include a case where no permitted document answers the question. The correct system behaviour may be to explain the gap or request more information, rather than invent a plausible maintenance interval.
A later observability lesson will record these stages. Here the selected IDs make the budgeting consequence visible without a live model.
Check yourself
Questions on Parts 1 to 8
Question 1 of 2
What still needs checking?
Use the information below.
The selected document cites an older machine version. The answer repeats its interval accurately, but the question asks about the new version.Try it with Botie
Build with Botie
Write and run Python