Expense policy check
Your expense tool posts each new expense to a webhook. Claude reads it against your policy and answers OK or FLAG with a reason. A condition step sends clean expenses straight back as approved, and stops flagged ones at an approval gate with the reason attached.
- Check policy Claude API · Sonnet 5
- Flagged? Condition
- Review flagged expense You
- Send: approved after review Shell
- Send: within policy Shell
What each step does
Check policy
Claude API · Sonnet 5Reads the expense against your policy and answers OK or FLAG with the rule that applies.
Flagged?
ConditionSends flagged expenses to you and clean ones straight on.
Review flagged expense
YouShows you the flagged expense and the reason. Reject to stop and handle it in your expense tool.
Send: approved after review
ShellSends the expense back as approved, with your comment.
Send: within policy
ShellSends the expense back as within policy.
From copy to first run
- Copy the pipeline JSON with the button above.
- In Jimothy, open Pipelines → New pipeline, paste it under “Or import a pipeline JSON” and click Import.
- Fill in the variables below under Pipeline settings → Variables.
- Triggers → Add trigger → Webhook. In Zapier, Make or n8n, post each new expense to the URL with the fields below.
Send title (employee · merchant · amount), description (the memo), key (the expense id) and the extra fields employee, amount, currency, merchant, category, date and receipt (yes or no). They reach the prompts as {{issue.raw.amount}} and so on.
What to fill in
The prompts and commands read these as {{vars.<name>}}. The examples are placeholders: replace them with your own.
| Variable | What to put in it | Example |
|---|---|---|
expensePolicy | Your expense policy in plain language. The check only enforces what is written here. | Meals: up to $75 per person per day while travelling; alcohol is not reimbursed. Flights… |
resultWebhookUrl | Where decisions are sent, e.g. a Zapier catch hook that approves or comments on the expense. | — |
Show the pipeline JSON
{
"jimothyPipeline": 1,
"name": "Expense policy check",
"description": "Checks a submitted expense against your policy, auto-approves clean ones and asks you about flagged ones.",
"icon": "workflow",
"color": "#10b981",
"repo": {
"mode": "scratch"
},
"concurrency": 5,
"variables": {
"expensePolicy": "Meals: up to $75 per person per day while travelling; alcohol is not reimbursed. Flights: economy for trips under 6 hours. Hotels: up to $250 per night. Software subscriptions need a manager-approved request. Receipts are required over $25. Personal items, fines and upgrades are never reimbursed.",
"resultWebhookUrl": ""
},
"steps": [
{
"id": "check",
"name": "Check policy",
"type": "agent",
"description": "Reads the expense against your policy and answers OK or FLAG with the rule that applies.",
"harnessId": "anthropic-api",
"model": "claude-sonnet-5",
"timeoutMinutes": 5,
"retries": 1,
"passPattern": "^\\s*DECISION:\\s*(OK|FLAG)\\b",
"systemPrompt": "You check employee expenses against this policy and nothing else:\n\n{{vars.expensePolicy}}\n\nWhen the policy does not cover an expense, flag it rather than guessing.",
"prompt": "Expense {{issue.key}}\nEmployee: {{issue.raw.employee | default:\"(unknown)\"}}\nMerchant: {{issue.raw.merchant | default:\"(unknown)\"}}\nAmount: {{issue.raw.amount | default:\"(unknown)\"}} {{issue.raw.currency | default:\"\"}}\nCategory: {{issue.raw.category | default:\"(none)\"}}\nDate: {{issue.raw.date | default:\"(unknown)\"}}\nReceipt attached: {{issue.raw.receipt | default:\"unknown\"}}\nMemo: {{issue.description | default:\"(none)\"}}\n\nAnswer in exactly this format:\nDECISION: OK or DECISION: FLAG\nREASON: one sentence naming the policy rule that applies"
},
{
"id": "flagged",
"name": "Flagged?",
"type": "condition",
"description": "Sends flagged expenses to you and clean ones straight on.",
"dependsOn": [
"check"
],
"condition": {
"match": "all",
"rules": [
{
"value": "{{steps.check.output}}",
"op": "matches",
"compare": "DECISION:\\s*FLAG"
}
]
}
},
{
"id": "approve",
"name": "Review flagged expense",
"type": "approval",
"description": "Shows you the flagged expense and the reason. Reject to stop and handle it in your expense tool.",
"dependsOn": [
"flagged"
],
"approvalMessage": "**{{issue.title}}** was flagged.\n\n{{steps.check.output}}\n\nMemo: {{issue.description | default:\"(none)\"}}\n\nApprove to send it back as approved (your comment is attached). Reject to stop here and handle it in your expense tool."
},
{
"id": "send_reviewed",
"name": "Send: approved after review",
"type": "shell",
"description": "Sends the expense back as approved, with your comment.",
"dependsOn": [
"approve"
],
"timeoutMinutes": 2,
"command": "printf '{\"expense\":%s,\"decision\":\"approved_after_review\",\"check\":%s,\"note\":%s}' {{issue.key | json}} {{steps.check.output | json}} {{steps.approve.comment | default:\"\" | json}} | curl -fsS -X POST -H 'Content-Type: application/json' --data @- {{vars.resultWebhookUrl}}"
},
{
"id": "send_ok",
"name": "Send: within policy",
"type": "shell",
"description": "Sends the expense back as within policy.",
"dependsOn": [
"flagged"
],
"onBranch": {
"flagged": "no"
},
"timeoutMinutes": 2,
"command": "printf '{\"expense\":%s,\"decision\":\"within_policy\",\"check\":%s}' {{issue.key | json}} {{steps.check.output | json}} | curl -fsS -X POST -H 'Content-Type: application/json' --data @- {{vars.resultWebhookUrl}}"
}
]
}More for accounting & finance, and beyond
Month-end variance commentary
Compares this month’s trial balance with last month’s, explains every material swing, and files the write-up after you sign off.
Accounting & financeInvoice intake and GL coding
Reads each incoming vendor invoice, extracts the details, suggests GL codes from your chart of accounts, and sends it to your AP tool after you check it.
Accounting & financeOverdue invoice reminders
Reads your AR aging report every week, drafts a reminder for each overdue customer in the right tone for how late they are, and sends the ones you pick.