How to Build a Staff Knowledge Base for OTC Product and Store Policy Questions

Embed your over-the-counter product sheets and store policy documents into a Spojit Knowledge collection, then let counter staff ask plain-language questions and get a cited, structured answer back in seconds.

What This Integration Does

Front-counter staff in a pharmacy or health-retail store field the same kinds of questions all day: what pack sizes does an over-the-counter line come in, what is the store's returns window on opened cosmetics, how does the loyalty program work, what is the procedure for a price-match. The answers live scattered across PDF product sheets, a returns policy document, and an operations handbook. This workflow puts all of that retail and store-policy material into one searchable Spojit Knowledge collection and gives staff a single place to ask. They send a question, and Spojit returns a short answer plus the exact source documents it drew from, so the team can trust and verify it.

You build this in two parts. First, an embedding step (run once, or re-run whenever a document changes) loads your product sheets and policy files into a persistent Knowledge collection so they survive across runs and are readable by any workflow in your workspace. Second, a question-answering workflow is triggered by an incoming HTTP request (a Webhook trigger, which a Slack slash-command or an internal form can call). A Knowledge node queries the collection, a Response Schema forces a clean structured answer with a list of sources, and a Response node hands that JSON straight back to the caller. The workflow holds no state between runs: each question is independent, so re-running with the same question is always safe. This is strictly retail product information and store or admin policy content. It does not provide clinical guidance, diagnoses, dosing, or treatment advice, and you should not load clinical material into the collection.

Prerequisites

  • Your OTC product sheets and store/admin policy documents in supported formats (PDF, Word, Excel, CSV, Plain Text, Markdown, or HTML). Keep the content strictly retail and policy: pack sizes, prices, returns windows, loyalty rules, store procedures. No clinical or treatment material.
  • A persistent Knowledge collection created in the Knowledge section of the sidebar (name it something like store-kb), with its embedding model chosen at creation time. The same embedding model is used for embedding and querying automatically.
  • A Slack connection if you want staff to ask from Slack (used by the optional notification step). Add it under Connections.
  • A signing connection for the Webhook trigger (scheme Slack if a Slack slash-command calls it, or Custom for an internal form). See the prerequisite link in setting up a Webhook trigger.
  • Optional: the http and json connectors are built in and need no setup if you pull documents from an internal system's REST API.

Step 1: Create the persistent collection and embed your documents

Open the Knowledge section in the sidebar and choose New Collection. Give it a name (for example store-kb) and an optional description, then pick the embedding model (this is fixed once the collection is created). Open the collection and use Upload Document to drag in each product sheet and policy file, then Upload & Embed. The document table shows each file's chunk count and a status of PROCESSING then READY. This direct upload is the simplest way to seed a small, stable set of documents.

If your documents instead live in an internal system and you want Spojit to load them, build a small one-step embed workflow. Add a Knowledge node in Embed mode, set Collection to store-kb, set File Name (for example returns-policy.pdf), pick the matching Document Type, and pass the file bytes into Document Input as a base64 reference such as {{ download_result.content }}. Re-embedding a file with the same name overwrites it, so this is also how you keep the collection current when a policy changes.

Step 2: Add a Webhook trigger to receive the staff question

Create a new workflow for question answering. Add a Trigger node and set its type to Webhook. Spojit gives the workflow a URL that an external HTTP POST can call, and the trigger verifies the request using your signing connection. The parsed JSON body is available as {{ input }}. If a Slack slash-command calls it, the staff question arrives in a field such as {{ input.text }}; if an internal help form calls it, use whatever field name that form posts, for example {{ input.question }}. Because you will return an answer to the caller in Step 5, keep this a Webhook trigger (it supports a synchronous Response node), not a Mailhook trigger.

Step 3: Query the collection with a Knowledge node

Add a Knowledge node and set it to Query mode. Configure:

  • Collection: store-kb (the persistent collection from Step 1).
  • Prompt: a templated instruction that scopes the answer to retail and policy only, for example:
    You are answering store-staff questions using only the store's OTC product
    sheets and store/admin policy documents. Answer this question:
    {{ input.text }}
    
    Only use retail product facts and store policy. If the question asks for
    clinical, dosing, or treatment advice, do not answer it and say it is out
    of scope. If the documents do not contain the answer, say so.
  • Model: the AI model used to synthesize the answer from the retrieved chunks.
  • Result Count: leave at the default of 5, or lower it to 3 for tighter, faster answers.
  • Output Variable: for example answer.

The Knowledge node retrieves the most relevant chunks from the collection and uses the model to compose a grounded answer. For more on tuning queries, see querying your knowledge base.

Step 4: Force a structured answer with a Response Schema

In the same Knowledge node, fill in the Response Schema field with a JSON schema so the output is always shaped the same way: a plain-language answer, a short list of cited sources, and a flag for out-of-scope questions. This makes the result safe to render in Slack or a form without parsing free text.

{
  "type": "object",
  "properties": {
    "answer": { "type": "string" },
    "sources": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "document": { "type": "string" },
          "snippet": { "type": "string" }
        },
        "required": ["document"]
      }
    },
    "in_scope": { "type": "boolean" }
  },
  "required": ["answer", "sources", "in_scope"]
}

With the schema set, the structured result lands in your output variable, so you can read {{ answer.answer }}, loop or join {{ answer.sources }}, and branch on {{ answer.in_scope }}. Response Schema in a Knowledge query works the same way as in a Connector node Agent mode call, which is covered in using connector nodes in Agent mode.

Step 5: Return the answer with a Response node

Add a Response node at the end of the workflow to hand the structured answer straight back to whoever called the Webhook. Set the response body to your output variable, for example {{ answer }}, so the caller receives the answer text, the source list, and the scope flag as JSON. A Slack slash-command or an internal form can then display the answer and its sources to the staff member. For the mechanics of synchronous returns, see using Response nodes.

Step 6: Optionally post the answer into a Slack channel

If you would rather have answers land in a shared channel (so the whole counter team learns from them), add a Connector node on the slack connector in Direct mode and pick the send-message tool before the Response node. Map the channel and compose the text from your variables. To turn the cited sources into a readable line first, add a Connector node on the json connector using the stringify tool on {{ answer.sources }}, or use a Transform node to format them. A sample send-message body:

Q: {{ input.text }}

A: {{ answer.answer }}

Sources: {{ answer.sources }}

For the full Slack tool list, see the Slack connector reference.

Tips

  • Keep the prompt's scope guardrail explicit (retail and policy only, refuse clinical questions) so the structured in_scope flag is reliable, and only ever load retail and store-policy documents into the collection.
  • Re-embedding a file with the same File Name overwrites it, so updating a policy is a one-step re-upload rather than a delete-and-re-add.
  • Lower Result Count to 3 for snappier responses on short factual questions; raise it only if answers feel incomplete.
  • Ask Miraxa, the intelligent layer across your automation, to scaffold this for you with a prompt like "Add a Knowledge node in Query mode against the store-kb collection with a Response Schema, then connect it to a Response node," and fine-tune the fields in the properties panel afterward.

Common Pitfalls

  • Querying a collection that was embedded with a different embedding model than the one you query with returns poor matches. The collection's embedding model is fixed at creation and used for both sides automatically, so create a fresh collection rather than mixing models.
  • Reading the wrong input field. A Slack slash-command posts the question in {{ input.text }}, while a custom form may use {{ input.question }}. Check the actual body in the execution log after the first call.
  • Forgetting the signing connection on the Webhook trigger. Without a valid signing scheme the request is rejected before your nodes run.
  • Expecting documents in PROCESSING status to be queryable. Wait until the document table shows READY before relying on the answer.

Testing

Before pointing real staff at it, embed just two or three documents (one product sheet and one policy file) and confirm each shows READY in the collection's document table. Then send a test request to the Webhook URL with a known question whose answer you can verify, for example "What is our returns window on opened skincare?" Open the execution log to confirm the Knowledge node returned the right chunks, the structured output has a sensible answer, a populated sources list, and in_scope set to true. Finally send a deliberately out-of-scope question (a clinical or dosing question) and confirm the workflow returns in_scope: false with a refusal, proving the guardrail holds before you widen access.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.