How to Answer Client Questions in Front from a Knowledge Base of Past Deliverables

Watch your client inbox with an Email trigger, draft a cited answer from your past deliverables and SOW collection with a Knowledge query, have a reviewer approve the draft on a Human node, then reply in the original Front conversation: all built in Spojit.

What This Integration Does

Professional services teams answer the same client questions over and over: "What deliverables were in scope?", "When is the next milestone?", "What did we agree on rates?". The answers already exist in your past statements of work, project plans, and delivered reports, but finding them and writing a clean reply takes a senior person ten minutes every time. This workflow turns that into a draft-and-approve loop. When a client emails a question, Spojit pulls the most relevant passages from a Knowledge collection of your deliverables, drafts a grounded answer that cites where each fact came from, routes it to a reviewer for a quick approval, and then sends the reply back inside the same Front conversation so the thread stays intact.

The workflow is triggered by an Email trigger polling a connected client-facing mailbox. On each new message it runs a Knowledge node in Query mode against a persistent collection you maintain, returning a structured draft (answer text plus the source documents it leaned on). A Human node pauses the run until a reviewer approves or rejects the draft. On approval, a Connector node on the front connector in Direct mode calls send-message to post the reply into the conversation. The collection is long-lived and unchanged by a run, so re-running on the same email is safe and simply produces a fresh draft. A rejected draft halts the run with no reply sent, so nothing reaches the client without sign-off.

Prerequisites

  • A connected mailbox for the Email trigger: add it under Connections > Add connection > Gmail (trigger) or Outlook (trigger) (OAuth, read-only is enough).
  • A front connection (API key) with permission to send messages, added under Connections > Add connection.
  • The Front channelId you want to reply from. Use a Connector node on the front connector with list-inboxes or list-conversations once to discover your channel identifiers, or copy it from your Front admin settings.
  • A persistent Knowledge collection (create it in the Knowledge section via New Collection) holding your past deliverables: signed SOWs, project plans, delivered reports, and rate cards. Upload them with Upload Document and Upload & Embed, and wait for each document to reach READY.
  • At least one teammate (or a Role/Team) to act as the approval reviewer.

Step 1: Build the deliverables Knowledge collection

Before the workflow can answer anything, it needs source material. In the Knowledge section of the sidebar, choose New Collection, name it something like client-deliverables, and pick an embedding model (the default Gemini Embedding 001 is fine). Open the collection and use Upload Document to add your SOWs, project plans, and delivered reports as PDF, Word, or Markdown, then Upload & Embed. Confirm each row shows status READY in the document table before relying on it. This is a persistent collection, so any workflow in your workspace can query it and re-running a workflow never alters it. Keep filenames meaningful (for example acme-sow-2026-q1.pdf) because those names become the citations your reviewer sees in the draft.

Step 2: Add the Email trigger to watch the client inbox

Create a new workflow and set the Trigger type to Email. Select your connected Gmail or Outlook mailbox, pick the folder to watch, and set a poll interval (1 to 60 minutes; the default of 2 is fine for client questions). To avoid drafting replies to internal chatter, set an optional From allowlist of client domains and an optional Subject regex if you only want certain threads. Each new message makes the trigger output available downstream, including {{ input.subject }}, {{ input.from }}, {{ input.textBody }}, and {{ input.conversationId }}. The body of the client's question is what you will hand to the Knowledge query in the next step.

Step 3: Draft a cited answer with a Knowledge node in Query mode

Add a Knowledge node and set its mode to Query. Choose your persistent client-deliverables collection (not Transient: you want the durable archive, not a one-off). In the Prompt field, feed in the client's question and instruct the node to answer only from retrieved passages, for example:

You are answering a client's question using only our past deliverables and
statements of work. The client asked:

"{{ input.subject }}
{{ input.textBody }}"

Write a concise, professional answer. Only state facts supported by the
retrieved documents. If the documents do not contain the answer, say so
plainly and do not guess. List the source filenames you used.

Pick a synthesis Model, set Result Count to around 5 so it has enough context, and define a Response Schema so the output is reliable structured JSON instead of free text:

{
  "type": "object",
  "properties": {
    "answer": { "type": "string" },
    "confidence": { "type": "string", "enum": ["high", "medium", "low"] },
    "sources": { "type": "array", "items": { "type": "string" } }
  },
  "required": ["answer", "confidence", "sources"]
}

Set the Output Variable to draft. Downstream you can reference {{ draft.answer }}, {{ draft.confidence }}, and {{ draft.sources }}. The Knowledge node is the place where Miraxa, the intelligent layer across your automation, grounds its answer in your own documents rather than general knowledge.

Step 4: Pause for reviewer approval on a Human node

Add a Human node so no reply leaves Spojit without sign-off. Give it a Label like Approve client reply and a Message that shows the reviewer exactly what will be sent, using the draft variables:

Client: {{ input.from }}
Question: {{ input.subject }}

Proposed reply (confidence: {{ draft.confidence }}):
{{ draft.answer }}

Sources: {{ draft.sources }}

Set a Timeout (minutes) if a stale draft should expire rather than linger, choose an Urgency, and optionally turn on Email approvers so reviewers get notified by email. The only required field is Approval slots: add a slot and place an atom in it (a specific User, a Role, or a Team). The reviewer acts in the Approvals inbox at /approvals. On Approved the run continues with output { approved: true, outcome: "APPROVED" }; on Rejected or Timed out the run halts and no reply is sent. Branching a different path on reject is not supported, which is exactly what you want here: a rejected draft simply stops.

Step 5: Reply in the Front conversation with a Connector node in Direct mode

Add a Connector node on the front connector and choose Direct mode so the call is deterministic and costs no AI credits. Select the send-message tool and map its inputs:

  • channelId: the Front channel you reply from (from your Prerequisites).
  • to: an array with the original sender, for example ["{{ input.from }}"].
  • subject: a reply subject such as Re: {{ input.subject }}.
  • body: the approved answer. The body field supports HTML, so wrap the draft in basic markup, for example <p>{{ draft.answer }}</p>.

Because the message is sent from the same client channel, Front threads it into the existing conversation the client started, keeping the history clean. If you want to associate the reply with the original thread explicitly, you can first add a Connector node calling get-conversation with id set to {{ input.conversationId }} to confirm the conversation exists before sending. Since this node only runs after the Human node approves, the only messages that ever reach a client are the ones a person signed off.

Step 6: Notify the team in Slack and tag the conversation (optional)

To close the loop, add a Connector node on the slack connector in Direct mode using send-message to post a short note to your team channel, for example Replied to {{ input.from }} re: {{ input.subject }} (confidence {{ draft.confidence }}). You can also add a Connector node on the front connector with add-tag to label the conversation as answered. These steps run only after a successful reply, so the Slack note is an accurate record of what went out.

Tips

  • Watch {{ draft.confidence }}. Route low drafts to a more senior approval slot, or add a Condition node that skips the reply entirely and instead pings a human when the collection clearly lacks an answer.
  • Keep the Knowledge prompt strict about "only answer from retrieved documents". This is what prevents a confident-sounding but unsupported reply going to a client.
  • Front's body accepts HTML, so format the reply with simple paragraphs and lists rather than a single wall of text. Avoid pasting raw source filenames into the client-facing body; keep those in the reviewer message instead.
  • Re-embed updated SOWs and reports when scope changes. The collection is the source of truth, and a stale document produces a confidently wrong draft.

Common Pitfalls

  • Querying before documents finish processing. A document stuck in PROCESSING is not searchable yet; confirm READY in the collection's document table first.
  • Mixing embedding models. Always embed and query a collection with the same embedding model, or retrieval quality drops sharply.
  • Missing or wrong channelId on send-message. Front sends from a channel, so an inbox-only identifier will fail. Discover the real channel with list-inboxes or list-conversations first.
  • Expecting a reject branch. A rejected or timed-out Human node halts the run; there is no "on reject, do X" path. Build any alternate handling as a separate workflow or upstream condition.
  • Email trigger noise. Without a From allowlist or Subject regex, internal forwards and out-of-office replies can trigger needless drafts and approvals.

Testing

Start small. Seed the collection with two or three known documents and confirm they reach READY. Send a test email from a controlled address that matches your From allowlist, asking a question you know the documents answer. Watch the run in execution history: confirm the Knowledge node returns a sensible {{ draft.answer }} with correct {{ draft.sources }}, then approve it yourself in the Approvals inbox and verify the reply lands in the right Front conversation. Then test the negative path: ask something the documents do not cover and confirm the draft says it cannot answer, and reject it to confirm no message is sent. Only widen the From allowlist and turn the workflow on once both paths behave.

Learn More

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