The Cited Answer on Microsoft 365
An assistant over your own documents is the easy half and you may already have it. The half that makes it safe to rely on is the part nobody ships by default.
Used by
- AI Officer
- Business Systems Analyst
- Compliance Officer
- Quality Manager
How to get this live in your business
Free. The Cited Answer Build Standard: the objects, the checks in order, and the pass test.
Ready for
This is the build plan most likely to be read by somebody who believes they have already done it, because the tenant comes with an assistant and the assistant answers questions about documents. The distance between that and this standard is the distance between a citation and a dated clause, and it is the whole distance.
In short
What this is
A build plan for the cited answer standard on Microsoft 365. A library, four lists, three flows, five measures, and whichever assistant you already pay for on top.
The core rule
Retrieval runs over clauses with effective dates. A superseded clause cannot produce a live answer, and no general document assistant knows that on its own.
What it does not do
It never certifies, never issues or forecloses a certificate, and never resolves a conflict between two live instruments.
The hard part
Finding every answer that relied on an instrument that just changed, which is only possible if the cards were stored on the answers.
Take the spec to Claude, ChatGPT or Copilot. The sentence to paste is one click away.
Want the whole thing by email?
This paper, plus the rest of the library. One click to stop them.
1. Before you start, and the thing to get straight
Read the cited answer build standard first. Shared conventions are in building the standards on Microsoft 365.
Pointing a document assistant at a folder of standards does not implement this. A document-grounded assistant tells you which file an answer came from. This standard is about a clause, its edition, its jurisdiction and the date it was live, and about a retired clause being unable to answer at all. No general assistant has a concept of a superseded clause, because nothing in a document tells it one.
So the assistant is the part you already have. The clause library, the source cards and the change feed are the build, and they sit underneath whichever model you are paying for.
2. The lists, with their columns
For your developer. Show the fields
Site: Knowledge
LIBRARY Instruments the documents as issued
InstrumentId Text indexed
Title Text
IssuingBody Text
Jurisdiction Choice the states you operate in
Edition Text
EffectiveFrom DateTime
EffectiveTo DateTime blank means live
RetrievedAt DateTime
LIST Clauses retrieval runs over THIS
ClauseId Text indexed
Instrument Text lookup to Instruments
ClauseRef Text
Text Note
Supersedes Text a ClauseId, or blank
LIST SourceCards
Clause Text indexed. lookup to Clauses
Edition Text
Jurisdiction Choice the states you operate in
EffectiveFrom DateTime
AcceptedBy Person REQUIRED
AcceptedOn DateTime REQUIRED
RetiredOn DateTime blank means live
LIST Answers
Question Note
AskedOn DateTime
AskedAboutDate DateTime defaults to AskedOn, often is not
Jurisdiction Choice the states you operate in
Audience Choice internal | public
Body Note
SourceCardIds Text indexed. STORED. Not looked up later.
Queue Choice answered | declined | conflict
| change_pending
LIST ChangeDeltas
Instrument Text indexed. lookup to Instruments
DetectedOn DateTime
Summary Note
Status Choice pending | accepted | rejected
DecidedBy Person
DecidedOn DateTime
AffectedAnswers Text
An Answer with Queue = answered and no SourceCardIds should not
be representable. Enforce it in the flow, not in a review.SourceCardIds is stored as a value on the answer rather than derived when somebody looks. That is the entire mechanism by which you can later list every answer that relied on an instrument that has just changed.
3. Every check, and what enforces it
| The check | Enforced by | How |
|---|---|---|
| Retrieve clauses, not documents | Clauses list | The library holds instruments; the list holds clauses with their text. Retrieval runs over the list. A citation that says which document is not a citation. |
| Only clauses live on the asked-about date reach an answer | Answer flow | The retrieval filter includes EffectiveFrom and EffectiveTo against the date in question, not today by default, because people ask about the past. |
| Every answer carries a source card | Answer flow | The card is written with the answer and stored on it. Looking the citation up again later is not the same thing, because the clause may have moved. |
| No clause means decline, not the nearest answer | Answer flow | An empty retrieval is a terminating branch that writes a declined answer and names a person. It is not a fallback prompt. |
| A change is accepted by a named person before it is live | Change flow | A detected change writes a pending ChangeDelta, marks affected cards, and pushes answers into change_pending. Acceptance is an approval with a name and a date. |
| Public and internal are different policies | Answer flow | Audience is a field that selects the policy branch, not a sentence in a prompt that a clever question can talk around. |
4. The three flows
For your developer. Show the fields
FLOW 1 Answer
trigger a question arrives, from wherever you accept them
logic 1 establish jurisdiction and AskedAboutDate FIRST
2 retrieve Clauses filtered to that jurisdiction and
live on that date
3 if nothing retrieved -> write Queue = declined,
name a person, STOP. Do not call the model.
4 if two live instruments disagree -> Queue = conflict,
route to a person, STOP.
5 compose from the retrieved clause text only
6 write SourceCardIds onto the Answer
7 apply the Audience policy branch
never let the model answer from its own memory of a standard.
Step 3 is a branch, not an instruction in a prompt.
FLOW 2 Change feed
trigger scheduled, weekly
logic check each instrument at its source
on a change: ChangeDelta status = pending
mark the instrument's cards change pending
move answers relying on them to
Queue = change_pending
note from here those questions decline until accepted.
FLOW 3 Accept a change
trigger a pending ChangeDelta
logic request approval from the certifier group
on accept: write DecidedBy and DecidedOn, retire the
superseded cards, create the new ones
on reject: record that too, with the reason
never auto-accept. The interpretation is the professional
judgement and it is the reason this flow exists.Flow 1 step 3 is the line between this standard and a chatbot. A decline is a branch taken before the model is asked for anything, which is why it cannot be talked around.
5. The Power BI model and its measures
For your developer. Show the fields
Answers Cited =
CALCULATE ( COUNTROWS ( Answers ), Answers[Queue] = "answered" )
Uncited Answers = -- must be zero
CALCULATE (
COUNTROWS ( Answers ),
Answers[Queue] = "answered",
ISBLANK ( Answers[SourceCardIds] )
)
Decline Rate =
DIVIDE (
CALCULATE ( COUNTROWS ( Answers ), Answers[Queue] = "declined" ),
COUNTROWS ( Answers )
)
Serving Retired Cards = -- must be zero
CALCULATE (
COUNTROWS ( SourceCards ),
NOT ISBLANK ( SourceCards[RetiredOn] ),
SourceCards[RetiredOn] < TODAY ()
)
Change Acceptance Days =
AVERAGEX (
FILTER ( ChangeDeltas, ChangeDeltas[Status] = "accepted" ),
DATEDIFF ( ChangeDeltas[DetectedOn], ChangeDeltas[DecidedOn], DAY )
)Do not treat a falling Decline Rate as progress. It falls when the library genuinely improves and also when somebody loosens the retrieval filter, and those are opposite events. Read it against Uncited Answers, which must stay at zero.
6. The order to build it in
- Create the library and lists. Index ClauseId.
- Load one instrument and split it into clauses. One instrument is enough to prove the shape and small enough to check by hand.
- Create source cards for those clauses, with a real accepting person. If nobody will accept them, stop: that is the finding.
- Build Flow 1 up to step 3 and no further. Prove it declines before teaching it to answer.
- Add steps 4 to 7. Confirm SourceCardIds is written on the answer.
- Retire a clause and run the pass test.
- Build Flows 2 and 3.
- Connect Power BI. Uncited Answers on the front page, at zero.
7. Four traps specific to this build
Assuming Copilot over SharePoint satisfies this
It does not, and this is the most important line on the page. A document-grounded assistant cites the file it drew on. This standard is about a clause, an edition, a jurisdiction and an effective date, and about a superseded clause being unable to produce a live answer. Nothing in a general document assistant knows that a clause was retired. The clause library and the card layer are yours to build whichever assistant sits on top.
The instrument library as the only store
Dropping PDFs in a library and pointing retrieval at it gives you document-level answers and no way to retire a clause. Split them: the library keeps the instrument as issued, the list keeps the clauses with their dates.
Declining implemented as a prompt instruction
Telling a model to say it does not know is a request, not a gate. The decline must be the branch taken when retrieval returns nothing, decided in the flow before the model is asked to write anything.
No link from an instrument to the answers that relied on it
When an instrument moves you need the list of answers already given from it. That requires storing the card ids on the answer at the time. Reconstructing it later is exactly the work you will not do in the week it matters.
8. Where the automation stops
- Accepting a change to an instrument, and deciding what it does to existing cards.
- Resolving a conflict between two live instruments.
- Any certificate, sign-off or statement of compliance.
- Any answer where being wrong is somebody's safety rather than somebody's afternoon.
- Deciding a question is outside the body of rules you hold, and saying so to the person who asked.
The pass test. Retire one clause your assistant answers from: set its EffectiveTo and load the replacement with a later EffectiveFrom, then ask the same question again. The answer must either change and cite the new clause, or decline into change_pending until somebody accepts the delta. Then ask something adjacent that your library genuinely does not cover: it must decline and name a person, with no body text composed. A few minutes on your own material. If the first still answers from the retired clause, retrieval is not filtering on the date. If the second produces a plausible paragraph, the model is answering from memory and you have a chatbot with a citation field.