How to Build a Policy Lookup System for Approval Workflows
Let approval workflows automatically check company policies before routing for human review.
What This Integration Does
Approvers spend half their time looking up the policy that applies to the request in front of them. This workflow does that lookup automatically: every approval request hits a Knowledge query against your indexed policies first, and the matching excerpt is shown next to the request when the Human approver opens it. Decisions get faster and more consistent, and the audit trail records exactly which policy text informed each approval.
Operationally, the workflow accepts approval requests via webhook (from your purchasing system, expense tool, or internal admin UI), retrieves the relevant policy section, optionally auto-approves cases that clearly fall inside policy thresholds, and routes everything else to a Human node with the policy excerpt attached. Each approval is logged with the matched policy sourceId so a future audit can replay the reasoning.
Prerequisites
- A Knowledge collection containing your approval policies, delegation of authority documents, and expense guidelines.
- A way for requests to arrive: typically a Webhook Trigger from your purchasing or expense system.
- A Slack or resend/smtp connection to notify approvers.
- A mongodb or mysql connection for the audit log.
Step 1: Webhook Trigger
Add a Trigger node and set the sub-type to Webhook. The expected payload is the approval request itself: requestType, amount, currency, requesterId, costCenter, and a free-text description. Set up basic validation - reject obviously malformed payloads early so they don't pollute the audit log.
Step 2: Knowledge Node - Retrieve the Applicable Policy
Add a Knowledge node in Query mode. Point Collection at the persistent collection holding your policy documents. Write a natural-language Prompt that pulls in the most relevant signals from the request, pick the Model that synthesizes the answer, and set Result Count to how many chunks to retrieve (default is 5):
Summarize the approval policy that applies to a {{ input.requestType }}
of {{ input.amount }} {{ input.currency }} in cost center {{ input.costCenter }}.
Quote the relevant thresholds and required approver levels.
Set the Output Variable to policyContext. The query returns a synthesized answer over the matching policy excerpts, which is what you will later attach to the audit record.
Step 3: Knowledge Query with a Response Schema - Extract the Threshold and Required Approvers
You can have the same Knowledge query return a structured decision instead of free text. Add a second Knowledge node in Query mode against the same policy collection, write a Prompt that asks for the decision, and supply a Response Schema so the output is forced into JSON:
{
"type": "object",
"properties": {
"withinPolicy": { "type": "boolean" },
"requiredApproverLevel": {
"type": "string",
"enum": ["manager", "director", "vp", "cfo"]
},
"policyQuote": { "type": "string" },
"rationale": { "type": "string" }
},
"required": ["withinPolicy", "requiredApproverLevel", "policyQuote", "rationale"]
}
In the Prompt, restate the request ({{ input.requestType }}, {{ input.amount }} {{ input.currency }}) and ask the model to decide whether it falls within policy and which approver level is required. Constraining requiredApproverLevel to an enum keeps the model from inventing a level. Set the Output Variable to decision.
Step 4: Condition - Auto-Approve, Auto-Reject, or Route
A Condition node branches true/false, so chain two of them to get three outcomes:
- First Condition (auto-approve) - test
{{ decision.withinPolicy }} == trueAND{{ decision.requiredApproverLevel }} == "manager"AND the amount is under a small workspace threshold (e.g. $250). The true branch handles legitimately routine spends. - Second Condition (auto-reject) - on the false branch of the first, test
{{ decision.withinPolicy }} == falsewith a clear violating policy quote. The true branch notifies the requester rather than wasting an approver's time. - Human review - the remaining false branch routes everything else to the Human node, which is almost always the bulk of traffic.
Step 5: Human Node - Present the Policy with the Request
Add a Human node on the review branch. Use the Message field to surface the request fields plus the structured {{ decision }} and the policy summary from {{ policyContext }}, so the approver sees the matched policy text alongside the request. Set Approval slots (the only required field) to the people or roles who can sign off: each slot holds one or more atoms (a specific User, a Role like Admin, or a Team), any atom satisfies its slot, and approval completes only when every slot is satisfied. Set a Timeout (minutes) if requests should not sit indefinitely. The approver acts in the Approvals inbox; the outcome is either Approved (the workflow continues, with output { approved: true, approvalId, outcome: "APPROVED" }) or Rejected (which halts the run). A timeout is treated as a reject.
Step 6: Notify and Audit
On each branch, notify the requester. Use a Connector node in Direct mode calling slack send-message, or resend send-email (or the built-in Send Email node if you do not need a custom from-address). Then write the audit record with a Connector node calling mongodb insert-documents or mysql insert-rows: the request payload, the policy excerpt from {{ policyContext }} that informed the decision, the structured {{ decision }}, who approved ({{ approvalId }}), and the timestamp. Note that a rejected Human approval halts the run, so place the human-path audit write on the branch after the approval continues; for auto-reject, log before notifying the requester.
Tips
- Re-index policies on every change - an out-of-date policy retrieval is worse than no retrieval. Build a CI step that re-runs your policy indexing workflow whenever the underlying documents change.
- Show, don't summarize - approvers trust quotes more than generated summaries. Always include the policy excerpt in the Human node message, not just the structured decision.
- Time-box auto-approvals - keep the auto-approve threshold conservative until you've seen enough audit data to be confident. Raising the cap later is easy; clawing back over-approvals is not.
Common Pitfalls
- Policy excerpts that miss the threshold table - chunking can split a table away from its heading. If your policies rely on numeric thresholds, make sure the chunk includes the table; consider indexing the table separately with explicit metadata.
- Ambiguous policies - if the query can't find a clear threshold, the model tends to invent one. Constraining
requiredApproverLevelto an enum in theResponse Schemahelps, and you should route anything uncertain to human review. - Currency conversion - thresholds are usually stated in one currency. Convert
amountto that currency in a Transform step before the Knowledge query and threshold check.
Testing
Pick three request shapes you know the policy outcome for by hand: one obvious auto-approve, one obvious auto-reject, one ambiguous case that should go to a human. Submit each via the webhook. Confirm each lands in the right branch, that the audit record cites the correct policy excerpt, and that the human-review case shows the approver useful context.