@humbleaf/trigger-verify
v0.1.0
Published
The missing middleware for risky workflows. Add one line to stop unsafe Trigger.dev tasks before value moves.
Maintainers
Readme
@humbleaf/trigger-verify
Wrap any Trigger.dev v4 task with policy-gated settlement in one line.
The missing middleware for risky workflows. Before a task sends money, refunds a customer, or deploys to prod, AgentChain evaluates policy and returns a receipt that is safe to settle against.
Quick Start (5 minutes to first blocked action)
1. Install
pnpm add @humbleaf/trigger-verify @humbleaf/agentchain-sdk2. Register middleware
// trigger/init.ts
import { tasks } from '@trigger.dev/sdk';
import { agentchainMiddleware } from '@humbleaf/trigger-verify';
tasks.middleware('agentchain', agentchainMiddleware({
apiKey: process.env.AGENTCHAIN_API_KEY!,
agentId: process.env.AGENTCHAIN_AGENT_ID!,
approvalMode: 'soft-fail',
}));3. Add invoiceSafe() to a task
import { task } from '@trigger.dev/sdk';
import { invoiceSafe, agentchain } from '@humbleaf/trigger-verify';
export const payInvoice = task({
id: 'pay-invoice',
...invoiceSafe({
vendor: (p) => p.vendorWallet,
amount: (p) => p.amount,
evidence: (p) => ({ invoiceHash: p.hash, vendorId: p.vendorId }),
}),
run: async (payload) => {
const receipt = agentchain.getReceipt();
if (receipt?.policyVerdict !== 'released') {
return { paid: false, approvalUrl: receipt?.approvalUrl };
}
const tx = await transferUSDC(payload.vendorWallet, payload.amount);
return { paid: true, tx, receiptId: receipt.receiptId };
},
});4. Happy path → Released ✓
Trigger run: pay-invoice
Payload: { vendorWallet: "0xAcme", amount: 480, hash: "0xabc..." }
AgentChain: ✓ Policy passed (5 checks)
Result: { paid: true, tx: "0x...", receiptId: "rcpt_abc123" }5. Blocked path → Denied ✗
Trigger run: pay-invoice
Payload: { vendorWallet: "0xUnknown", amount: 480, hash: "0xdef..." }
AgentChain: ✗ Denied — COUNTERPARTY_NOT_APPROVED
Result: { paid: false, reason: "Vendor not on allowlist" }6. Open dashboard → See receipts
Both results appear as receipts in your AgentChain dashboard with full policy evaluation details.
Presets
| Preset | Use Case | Policies Activated |
|---|---|---|
| invoiceSafe() | Pay invoices, rewards, refunds | Max value, counterparty allowlist, duplicate prevention, approval threshold |
| deploySafe() | Deploy to production | Evidence required, time window, restricted action escalation |
deploySafe() example
import { deploySafe } from '@humbleaf/trigger-verify';
export const deployService = task({
id: 'deploy-to-prod',
...deploySafe({
service: 'payments-api',
environment: 'production',
evidence: (p) => ({
gitSha: p.commitHash,
testsPassed: p.ciGreen,
rollbackArtifact: p.rollbackDigest,
}),
}),
run: async (payload) => { /* ... */ },
});Approval Mode
Controls what happens when policy returns pending_approval:
| Mode | Behavior | Best For |
|---|---|---|
| 'throw' | Task fails with AgentChainApprovalRequired | Simple workflows |
| 'soft-fail' | Receipt stored, task continues | Queue handoff, Slack alerts |
| 'wait' | Polls until approved or timeout | Human-in-the-loop |
agentchainMiddleware({
apiKey: '...',
agentId: '...',
approvalMode: 'soft-fail', // ← your choice
});Approval Queue Handoff
When approvalMode: 'soft-fail', use the approval URL for dashboard handoff:
if (receipt?.policyVerdict === 'pending_approval') {
await slack.send({
text: `⏳ Invoice $${payload.amount} needs approval`,
url: receipt.approvalUrl,
});
}License
MIT
