{
  "jimothyPipeline": 1,
  "name": "Invoice intake and GL coding",
  "description": "Extracts an incoming invoice, suggests GL codes for each line, and sends it to your AP tool after you check it.",
  "icon": "workflow",
  "color": "#16a34a",
  "repo": {
    "mode": "scratch"
  },
  "concurrency": 5,
  "variables": {
    "chartOfAccounts": "6100 Advertising\n6120 Software subscriptions\n6200 Contractors\n6300 Office supplies\n6400 Travel\n6500 Meals and entertainment\n6900 Other expenses",
    "approvalLimit": "2500",
    "apWebhookUrl": ""
  },
  "steps": [
    {
      "id": "extract",
      "name": "Extract and code",
      "type": "agent",
      "description": "Pulls vendor, dates, totals and line items out of the invoice and codes each line to one of your accounts.",
      "harnessId": "anthropic-api",
      "model": "claude-sonnet-5",
      "timeoutMinutes": 5,
      "retries": 1,
      "passPattern": "^\\s*\\{[\\s\\S]*\\}\\s*$",
      "failPattern": "```",
      "prompt": "Invoice {{issue.key}} ({{issue.title}}):\n\n{{issue.description | truncate:40000}}\n\nChart of accounts:\n{{vars.chartOfAccounts}}\n\nAnswer with one JSON object and nothing else (no code fences):\n{\n  \"vendor\": \"...\",\n  \"invoiceNumber\": \"...\",\n  \"invoiceDate\": \"YYYY-MM-DD\",\n  \"dueDate\": \"YYYY-MM-DD or null\",\n  \"currency\": \"USD\",\n  \"subtotal\": 0,\n  \"tax\": 0,\n  \"total\": 0,\n  \"lines\": [{\"description\": \"...\", \"amount\": 0, \"account\": \"number from the chart\", \"reason\": \"why this account\"}],\n  \"flags\": [\"anything a reviewer should check: totals that don't add up, a missing due date, an unusual amount, a possible duplicate\"]\n}\nCopy amounts exactly as written. Use only account numbers from the chart; if none fits, use the \"Other\" account and say so in flags."
    },
    {
      "id": "approve",
      "name": "Check coding",
      "type": "approval",
      "description": "Shows you the extracted invoice and coding. Reject with corrections and it is redone.",
      "dependsOn": [
        "extract"
      ],
      "loopBackTo": "extract",
      "maxLoops": 3,
      "approvalMessage": "Send this coded invoice to AP? Totals over {{vars.approvalLimit}} need a second look. Reject with corrections to have it redone.\n\n```json\n{{steps.extract.output}}\n```"
    },
    {
      "id": "send",
      "name": "Send to AP",
      "type": "shell",
      "description": "Sends the coded invoice to your accounting system through a webhook.",
      "dependsOn": [
        "approve"
      ],
      "timeoutMinutes": 2,
      "command": "printf '{\"invoice\":%s,\"coded\":%s}' {{issue.key | json}} {{steps.extract.output | trim}} | curl -fsS -X POST -H 'Content-Type: application/json' --data @- {{vars.apWebhookUrl}}"
    }
  ]
}