POST /statutes/search, GET /statutes/section/{actId}/body.
The loop
1
Search on the user's message
Send the message to
POST /statutes/search. Scope with corpusType and
state if your bot already knows the jurisdiction.2
Pull the best section's text
Take the top result and fetch its full text with
GET /statutes/section/{actId}/body.3
Reply, grounded and cited
Give an LLM the section text and its citation, and have it answer only from
that text. Append the official source link so the user can verify.
Primary call: search
The full chatbot in one function
Python
The loop is the whole bot. To wire it into Slack or Discord, call
answer()
from your message handler and post the return value back to the channel. Nothing
about the retrieval or grounding changes.Making it feel good
Set the jurisdiction once
Set the jurisdiction once
If your bot serves one state, pass
state on every search so results stay
scoped. If users can switch jurisdictions, capture the two-letter state code
from the conversation and pass it through. Omit corpusType and state to
search the entire US corpus when the jurisdiction is unknown.Always show the source link
Always show the source link
Every reply ends with the citation and the official government URL. This is
what makes the bot trustworthy: users can click through and read the law
themselves. Vaquill complements existing research tools, it does not replace a
lawyer.
Handle the empty case honestly
Handle the empty case honestly
When search returns no results or the body is unavailable, say so plainly
instead of guessing. A statute bot that admits it did not find something is
more useful than one that invents an answer.
Related
Ground an LLM answer (RAG)
The deeper version: multiple sources, strict citation rules, prompt design.
Resolve a citation
Turn a citation string into verified, authoritative text.
Grounding LLMs
Why grounding on retrieved text prevents hallucinated law.
Vaquill MCP server
Expose these same tools to an AI agent over MCP.

