How to Auto-Index Compliance Policies into a Persistent Collection from Email

Forward policy update emails to a Spojit Mailhook, pull the attached documents out of the message, and embed them into a persistent compliance knowledge collection so your team can ask questions against the latest version.

What This Integration Does

Compliance teams receive policy updates as email attachments: a revised handbook PDF from legal, a new data-retention standard from a vendor, an updated security procedure as a Word document. Filing those by hand into a searchable archive is slow and easy to skip. This workflow turns a single forwarded email into an indexed, queryable knowledge entry. You forward (or auto-forward) any policy email to a dedicated Spojit Mailhook address, and Spojit fetches the attachment bytes, embeds the document into a long-lived compliance collection, and posts a confirmation to Slack so the team knows the archive is current.

The workflow runs on a Mailhook trigger, so it fires within seconds of any mail landing at the generated address, with no mailbox or OAuth to manage. Each run reads {{ input }} from the email, pulls the matching attachment with an Attachment node, and embeds it into a persistent collection using a stable File Name so re-sending an updated version overwrites the old entry instead of duplicating it. The collection is workspace-scoped, so any other Spojit workflow can later query it. Re-runs are safe: Spojit deduplicates per message, and overwriting by file name keeps exactly one current copy of each policy.

Prerequisites

  • A persistent knowledge collection for compliance policies. Create it first under the Knowledge section of the sidebar with New Collection (for example, name it Compliance Policies). The embedding model is fixed at creation, so pick it now and keep it.
  • A Slack connection added under Connections, with a channel for compliance notifications (for example #compliance).
  • A way to deliver policy emails to the Mailhook address: a forwarding rule from your compliance inbox, or a sender (legal, a vendor) you can point at the generated address.
  • Policies sent as attachments in a supported format: PDF, Word, Excel, PowerPoint, CSV/TSV, JSON, XML, HTML, Plain Text, Markdown, RTF, Email (EML/MSG), or EPUB.

Step 1: Add a Mailhook trigger and generate the address

Create a new workflow and set the Trigger node type to Mailhook. Optionally set an Address prefix (1 to 24 characters, default mh) such as policies, then click Generate email address. Spojit produces a unique address like policies-a1b2c3d4e5f6g7h8@mailhook.spojit.com. Copy it and set up your forwarding rule or ask the sender to deliver policy updates there. The Mailhook fires whether the address is in To, Cc, or Bcc, and replies are not sent to the sender (the trigger is always asynchronous).

To keep noise out, set the optional From allowlist to the addresses that send policies (for example legal@yourcompany.com) and a Subject regex like (?i)policy|standard|procedure. The trigger output is available downstream as {{ input }}, including {{ input.subject }}, {{ input.from }}, {{ input.replyTo }}, and {{ input.attachments }}.

Step 2: Fetch the policy attachment

Add an Attachment node after the trigger. This node only saves in a workflow that has a Mailhook trigger, and it fetches the actual bytes of an attachment referenced by the email. Configure it to grab the policy document:

  • Mode: Single (returns the first match as an object).
  • Content type filter: application/pdf if policies are always PDFs, or leave broader (for example application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document) if Word documents also arrive.
  • Filename pattern: a glob such as *.pdf or *.docx to match the policy file and ignore signature images or logos.
  • Fail if no attachment matches: turn this on so an email with no usable document stops the run loudly instead of silently embedding nothing.

In Single mode the node outputs { filename, contentType, size, content }, where content is the base64 document body you feed straight into the Knowledge node. Default limits are 10 MB per attachment and 25 MB per run.

Step 3: Derive a stable file name for overwrite-on-update

To make sure a re-sent policy overwrites the previous entry rather than piling up, give each document a predictable name in the collection. Add a Transform node (or, for richer cleanup, a Connector node on the text connector in Direct mode using slugify) to turn the email subject or original filename into a clean key. For example, normalize {{ input.subject }} into a value like data-retention-standard.

A simple approach is to reuse the attachment filename directly via {{ attachment.filename }}. If you prefer the subject as the key, the text connector's slugify tool maps "Data Retention Standard v3" to data-retention-standard-v3. Keep version numbers out of the file name if you want each new version to overwrite the prior one; keep them in if you want every version retained separately.

Step 4: Embed the document into the persistent collection

Add a Knowledge node set to Embed mode. Configure it to write into your long-lived archive:

  • Collection: select your persistent Compliance Policies collection (not Transient, which would be discarded at the end of the run).
  • File Name: the stable key from Step 3, for example {{ policyKey }} or {{ attachment.filename }}. If the name already exists in the collection, embedding overwrites it, keeping exactly one current copy.
  • Document Type: match the attachment, for example PDF or Word.
  • Document Input: {{ attachment.content }} (the base64 bytes from the Attachment node).
  • Output Variable: for example embedResult, which holds the chunk count and metadata.

The embedding model is whatever you fixed when you created the collection, so you do not set it per run. After this node completes, the policy is chunked, embedded, and immediately queryable by any workflow in the workspace.

Step 5: Confirm the archive update in Slack

Add a Connector node on the slack connector in Direct mode and pick the send-message tool. Map channel to your compliance channel and build the text from the run's variables so reviewers know what changed:

channel: #compliance
text: Compliance archive updated. "{{ attachment.filename }}" ({{ attachment.size }} bytes) from {{ input.from }} was embedded into the Compliance Policies collection. Chunks indexed: {{ embedResult.chunkCount }}.

This gives the team a real-time audit trail of which policy landed, who sent it, and that it is now searchable. If you would rather notify a person directly, you can look up their Slack ID first with the slack lookup-user-by-email tool and message them.

Step 6: Acknowledge the sender (optional)

Because a Mailhook never replies automatically, add a Send Email node if you want to confirm receipt to whoever forwarded the policy. Set Recipients to {{ input.replyTo }}, a templated Subject like Received: {{ input.subject }}, and a short body confirming the document was indexed. Send Email uses Spojit's built-in mail service and needs no connection, though external recipients must be on your org allowlist under Settings > General > Email recipients.

Step 7: Verify the archive is queryable

To confirm the policy is searchable, build (or reuse) a second workflow with a Knowledge node in Query mode pointed at the same Compliance Policies collection. Set a Prompt such as What is our data retention period for customer records?, a Result Count (default 5), and a Model for synthesis, then read the answer from its Output Variable. Because the collection is persistent and workspace-scoped, any workflow, and Miraxa, can draw on the latest indexed policies.

Tips

  • Use a stable File Name in the Embed node so updated policies overwrite the old version. Include a version token only if you genuinely want to keep every revision side by side.
  • Set the Attachment node's Filename pattern tightly (for example *.pdf) so email signatures, inline logos, and banner images are never embedded as documents.
  • Keep the same embedding model for the whole life of the collection. It is fixed at creation, so embed and query always stay consistent.
  • If several policies can arrive in one email, switch the Attachment node to Multiple mode and wrap the Knowledge Embed node in a Loop over {{ attachment.attachments }}, embedding each one with its own file name.

Common Pitfalls

  • Choosing Transient as the collection. A transient collection is auto-created per run and cleaned up on completion, so your policies would vanish. For a long-lived archive you must select the named persistent collection.
  • Forgetting the File Name in Embed mode. It is required for persistent collections, and reusing it is what enables overwrite-on-update.
  • Oversized documents. Attachments above 10 MB each (or 25 MB total per run) exceed the defaults; split large policy bundles or send the core document only.
  • Mismatched Document Type. If you send a Word file but select PDF, embedding may fail or produce poor chunks. Map the type to the actual attachment.
  • Relying on the Mailhook to reply. It is always asynchronous and sends nothing back, so use a Send Email node to {{ input.replyTo }} if you need an acknowledgement.

Testing

Before pointing your real forwarding rule at the address, send a single test policy from an allowlisted sender to the generated Mailhook address. Open Executions and confirm the run fired, the Attachment node returned a non-zero size, and the Knowledge Embed node reported a chunk count in its output. Then open the Compliance Policies collection in the Knowledge section and check that the document appears in the table with status READY. Finally, run a Query node against the collection asking a question only that document answers. Once verified on one document, enable the forwarding rule for the full stream. Re-send the same file to confirm it overwrites rather than duplicates.

Learn More

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