
Build a docs-scoped support assistant using Prismfy domain search — with a complete Python example, LLM integration, and guardrails for when docs don't have the answer.
Prismfy Team
April 17, 2026
If users ask support questions, the fastest answer is usually already in your docs. The problem is not lack of information — the problem is retrieval.
A docs-only assistant solves that by searching exclusively your documentation domain and answering from those results. No hallucination, no roaming the open web, no invented product behavior.
The assistant should be deliberately narrow:
That keeps answers accurate and prevents the model from guessing at product behavior it has not seen.
Prismfy supports a domain filter that scopes results to a single site. Point it at your documentation and the search engine handles the rest.
curl -X POST https://api.prismfy.io/v1/search \
-H "Authorization: Bearer ss_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "how do I rotate API keys?",
"domain": "docs.yourproduct.com",
"engines": ["brave", "bing"],
"language": "en"
}'
The response comes back with results — each result has a title, url, and content snippet pulled directly from your docs pages. No scraping setup, no proxy config, no CAPTCHA handling.
Here is a complete, runnable example using the Anthropic SDK:
import anthropic
import requests
PRISMFY_KEY = "ss_live_YOUR_KEY"
DOCS_DOMAIN = "docs.yourproduct.com"
client = anthropic.Anthropic()
def search_docs(question: str) -> list[dict]:
"""Search your docs domain and return the top results."""
resp = requests.post(
"https://api.prismfy.io/v1/search",
headers={"Authorization": f"Bearer {PRISMFY_KEY}"},
json={
"query": question,
"domain": DOCS_DOMAIN,
"engines": ["brave", "bing"],
},
timeout=30,
)
resp.raise_for_status()
return resp.json().get("results", [])[:4]
def format_context(results: list[dict]) -> str:
"""Format search results as a context block for the LLM."""
if not results:
return ""
return "\n\n".join(
f"[{i+1}] {r['title']}\n{r['url']}\n{r.get('content', '').strip()}"
for i, r in enumerate(results)
)
def answer_support_question(question: str) -> str:
"""Answer a support question grounded in docs search results."""
results = search_docs(question)
if not results:
return (
"I could not find relevant documentation for that question. "
f"You can browse the full docs at https://{DOCS_DOMAIN} "
"or contact support directly."
)
context = format_context(results)
message = client.messages.create(
model="claude-opus-4-5",
max_tokens=512,
system=(
"You are a product support assistant. "
"Answer questions ONLY using the documentation excerpts provided. "
"If the excerpts do not contain enough information, say so clearly — do not guess. "
"Always cite the source URL at the end of your answer."
),
messages=[
{
"role": "user",
"content": (
f"Documentation excerpts:\n\n{context}\n\n"
f"Support question: {question}"
),
}
],
)
return message.content[0].text
# Example
answer = answer_support_question("How do I rotate my API keys?")
print(answer)
To rotate your API keys, go to Dashboard → API Keys and click "Create new key".
Copy the new key immediately — it is only shown once. Then delete the old key
from the same page.
Source: https://docs.yourproduct.com/authentication/api-keys
Short, grounded, sourced. The model does not add anything beyond what the docs say.
The most important guardrail is what happens when search returns nothing — or returns results that do not actually answer the question.
def answer_support_question(question: str) -> str:
results = search_docs(question)
context = format_context(results)
# If retrieval came back empty, do not ask the model to guess
if not context:
return (
"I could not find that in the documentation. "
"Please contact support at support@yourproduct.com."
)
# Pass context to the model with a strict grounding instruction
...
This prevents the assistant from hallucinating product behavior when the docs do not have an answer.
| Approach | Risk |
|---|---|
| Open web search | Model can find outdated blog posts, wrong answers, competitor pages |
| Vector DB over docs | Requires embedding pipeline, index maintenance, chunking decisions |
| Docs domain search | Live index, no maintenance, scoped to exactly your content |
The domain filter gives you the benefits of retrieval-augmented generation without a vector database or embedding pipeline. The search index is always current — it reflects what is on your docs site right now.
Searching the full web first. The model will find Stack Overflow answers, outdated tutorials, and competitor docs. Use the domain filter from the start.
Answering when retrieval comes back empty. If search returns nothing, say so. An "I don't know" is far better than a confident wrong answer.
Dumping full page content into context. The content snippet from each result is already a short excerpt. Use the top 3–4 results and nothing more.
Hiding source links. Always show the user where the answer came from. It builds trust and lets them read the full page if they need more detail.
This works best when:
For docs behind authentication (internal wikis, Notion, Confluence), you need a different approach — either a vector store over exported content or a direct API integration.
Try it free
Free tier includes 3,000 requests per 30 days. No credit card required.