Gains:
- Set up access control (ACL) that filters retrieval based on user authority
- Writing a solid prompt template that places the context and user question correctly
- Practicing question independence and history management in multi-round conversations
We established the architecture; Now let's make it safe, consistent and conversational. There are three critical topics in this unit: (1) access control that filters retrieval based on the user's authority, (2) a robust prompt template that places the context and question correctly, (3) question independence and conversation history management in multi-round chat. Without these three, an assistant will either leak data, give inconsistent answers, or fall apart on follow-up questions.
Access Control: Unauthorized Data Should Never Arrive
Enterprise biggest risk: A document that a user shouldn't see leaks into the response. A very common beginner mistake is to "tell the model to 'show hidden documents' at the prompt." This is not safe. The model may forget an instruction or a prompt injection may evade it. The correct place is the retrieval phase: the unauthorized piece should not be brought in at all.
The way to do this is to apply the authority metadata (department, role, privacy level) you put on each part as a filter during the search. You safely determine who the user is (identity and roles) at the application layer and add an ACL (Access Control List) filter to the call.
# Filtered by authority retrieval (conceptual)user = authenticate(session) # authenticated from trusted source = user.roles + ["everyone"] # e.g. ["HR", "admin"]result = vektor_db.search( vektor=embed(question), top_k=20, filter={"permission_group": {"in": allowed}, # only allowed parts "privacy": {"lte": user.level}} # below the level)
Caution: Never ask the model for authority or rely on the prompt. Identity and authority are determined at the trusted layer of the application; The retrieval filter is mandatory, the prompt instruction is just an additional layer. "I wrote it in the prompt" is not security.
Solid Prompt Template
The prompt template is the skeleton that brings together the context, user question, and behavior instructions from the retrieval. Parts of a good template: role/task description, rules of conduct (grounding, I don't know permission, resource request, tone), context, question.
You are a corporate HR assistant. Your job is to answer employee questions ONLY based on the following CONTEXT. Rules:- If the answer is not clearly in context write "I couldn't find information on this in the documentation, check with HR team". Don't guess, don't make up.- If the sources in the context conflict, take the official policy as basis and state the contradiction.- Add the source you rely on as [Source: file, section] at the end of each claim.- Answer in a short, clear and professional language. CONTEXT:{numbered_parts}QUESTION: {user_question}
Numbering the context parts ([1], [2], ...) makes it easier to cite the model. Also, write the source at the beginning of each piece so that the model can cite it correctly.
Tip: Keep the prompt template constant and always place variables (context, question) in the same places. A fixed template both increases testability and reduces costs thanks to prompt caching in some systems.
CONTEXT:[1] (Source: ik_el_kitabi.pdf, Section 5.2) Annual paid leave is 14 days...[2] (Source: ik_el_kitabi.pdf, Section 5.4) Leave is 20 days for people with more than 5 years of service...
Weak Prompt / Strong Prompt
Weak (no grounding, no source, identity mixed):
Use these documents and answer the question: {parts}User: {question}# Problem: model goes out of context, makes up, does not cite sources, # behaves arbitrarily in contradiction.
Strong (role + rules + numbered context + source mandatory):
You are... Just rely on CONTEXT. Otherwise, say "I don't know". In conflict, choose official policy. Add [Source: ...] to each claim.CONTEXT: [1]... [2]... QUESTION: {question}# Result: answer that is faithful to the context, sourced, and manages the contradiction correctly.
Multi-Tour Conversation Management
A real user does not ask a single question and leave it alone; speaks. "How many days of annual leave do I have?" → “What about the 6-year employee?” → “How do I apply for it?” The second and third questions alone are meaningless; depends on the previous context.
You need to solve two problems. The first is for retrieval: make the follow-up question independent (question rewriting). “What about the 6-year employee?” → "How many days of annual leave is an employee of 6 years entitled to?" You search with this independent question. The second is for production: you also give the conversation history to the model so that it continues consistently.
# Two-step: independentize → search → generate with history (conceptual) independent = model.uret( "Use the conversation history to make the question understandable on its own:\nHistory: {history}\nQuestion: {follow_question}") context = retrieval(independent) # search with independent questionanswer = model.uret(prompt(context, history, follow_question))
As the history grows (long conversation), sending it all at a time becomes expensive and fills the context window. Solution: summarize the previous rounds or keep the last N rounds and reduce the previous ones to the summary. Thus, costs remain under control and consistency is maintained.
Status
problem
Solution
Follow-up question has no context
Retrieval searches meaningless
Make the question independent (rewrite)
long chat
Cost and window swells
Summary of past tours
User changed topic
Old context gets infected
Reduce past influence on new topic
Authority may vary between tours
Risk of leakage
Reapply ACL filter every round
Three Mini Cases
Case 1 — “Security” fallacy with prompt. A company put confidential salary documents on an assistant that anyone could ask, but only wrote "don't give salary information" on the prompt. The model leaked the salary range when a user asked the question in a roundabout way. When the ACL filter was added to the retrieval (salary parts only to the HR role), the leak was completely closed; because the part is never brought anymore.
Case 2 — Contextless stalking. In a support assistant, the user asks "return period?" → “what about the broken product?” The system brought irrelevant parts for the "broken product". When question independence was added ("How long is the return period for a broken product?"), the correct answer rate increased from 44% to 90%.
Case 3 — Swollen past. In 30 rounds of chats with an assistant, each call sent the entire history; The cost was increasing 3 times per round, and the responses were slowing down. When we switched to a structure that kept the last 6 rounds and summarized the previous ones, the token cost dropped by 62% and consistency was maintained.
Common mistakes
- Leaving authority to the prompt: Model forgets/bypasses; ACL filter is mandatory on retrieval.
- Not enumerating the context: The model cannot cite the correct source.
- Not independentizing the follow-up question: Retrieval searches pointlessly.
- Sending all history blind: Explodes in cost and delay; summarize.
- Not writing the contradiction rule: The model may present the unreliable source as official.
In summary
- Access control is implemented with a metadata filter during the retrieval phase; Unauthorized parts should never be brought.
- Identity and authority are determined at the trusted application layer; The prompt instruction is just an additional layer of defense.
- Robust prompt template includes role, rules of conduct (grounding, don't know permission, source, conflict), numbered context, and question.
- In multi-round conversation, follow-up questions are decoupled and the model produces consistent answers with history.
- By summarizing the long history, the cost and context window is kept under control; The ACL is re-applied every round.
Application task
(1) Define at least three authorization groups for your own assistant (e.g. everyone, department, manager) and write in a table which document type is open to which group. (2) Adapt and write the above prompt template according to your own role and tone; Make the context numbered and sourced. (3) Write a three-round realistic conversation scenario (question → follow-up → follow-up) and manually generate independent versions of each follow-up question. (4) Explain in one sentence why the ACL filter should be reapplied each round in this scenario.
checklist
- [ ] I implement access control with a retrieval filter, I just don't rely on the prompt.
- [ ] I add grounding, I don't know permission, source and conflict rule to my prompt template.
- [ ] I give the context parts numbered and referenced.
- [ ] I make follow-up questions independent before retrieval.
- [ ] I manage the cost and window by summarizing the long conversation history.