{
  "jimothyPipeline": 1,
  "name": "Call notes → CRM and follow-up",
  "description": "Extracts deal fields from a call transcript, drafts the follow-up email, and sends both to your CRM after you approve.",
  "icon": "rocket",
  "color": "#0ea5e9",
  "repo": {
    "mode": "scratch"
  },
  "concurrency": 3,
  "variables": {
    "stages": "Discovery, Evaluation, Proposal, Negotiation, Closed won, Closed lost",
    "signature": "Sam at Acme",
    "crmWebhookUrl": ""
  },
  "steps": [
    {
      "id": "extract",
      "name": "Extract deal fields",
      "type": "agent",
      "description": "Pulls stage, pains, budget, decision makers, timeline and next steps out of the transcript as strict JSON.",
      "harnessId": "anthropic-api",
      "model": "claude-sonnet-5",
      "timeoutMinutes": 5,
      "retries": 1,
      "passPattern": "^\\s*\\{[\\s\\S]*\\}\\s*$",
      "failPattern": "```",
      "prompt": "Transcript of \"{{issue.title}}\":\n\n{{issue.description | truncate:60000}}\n\nExtract what was actually said. Answer with one JSON object and nothing else (no code fences):\n{\n  \"summary\": \"three sentences\",\n  \"stage\": \"one of: {{vars.stages}}\",\n  \"painPoints\": [\"...\"],\n  \"budget\": \"what was said, or null\",\n  \"decisionMakers\": [\"name and role\"],\n  \"timeline\": \"what was said, or null\",\n  \"competitors\": [\"...\"],\n  \"objections\": [\"...\"],\n  \"nextSteps\": [{\"owner\": \"us or them, with name\", \"action\": \"...\", \"due\": \"date or null\"}]\n}\nUse null or [] for anything not discussed. Don't infer budget or timeline from tone."
    },
    {
      "id": "email",
      "name": "Draft follow-up",
      "type": "agent",
      "description": "Drafts the follow-up email with the recap and next steps.",
      "harnessId": "anthropic-api",
      "model": "claude-sonnet-5",
      "dependsOn": [
        "extract"
      ],
      "timeoutMinutes": 5,
      "prompt": "Call fields:\n{{steps.extract.output}}\n\nWrite the follow-up email to {{issue.raw.contactName | default:\"the prospect\"}}. Thank them in one line, recap what we heard in their words (two or three bullets), list the next steps with owners and dates, and confirm the next meeting if one was agreed. Plain text, under 180 words, no subject line, signed \"{{vars.signature}}\".{{#if steps.approve.output}}\n\nYour previous draft was rejected with this feedback. Rewrite it:\n{{steps.approve.output}}{{/if}}"
    },
    {
      "id": "approve",
      "name": "Review follow-up",
      "type": "approval",
      "description": "Shows you the fields and the email. Reject with a comment and the email is rewritten.",
      "dependsOn": [
        "email"
      ],
      "loopBackTo": "email",
      "maxLoops": 3,
      "approvalMessage": "Update the CRM and send this follow-up for **{{issue.title}}**?\n\n```json\n{{steps.extract.output}}\n```\n\n---\n\n{{steps.email.output}}"
    },
    {
      "id": "send",
      "name": "Update CRM",
      "type": "shell",
      "description": "Sends the fields and the email to your CRM through a webhook.",
      "dependsOn": [
        "approve"
      ],
      "timeoutMinutes": 2,
      "command": "printf '{\"call\":%s,\"dealId\":%s,\"contactEmail\":%s,\"fields\":%s,\"email\":%s}' {{issue.key | json}} {{issue.raw.dealId | default:\"\" | json}} {{issue.raw.contactEmail | default:\"\" | json}} {{steps.extract.output | trim}} {{steps.email.output | json}} | curl -fsS -X POST -H 'Content-Type: application/json' --data @- {{vars.crmWebhookUrl}}"
    }
  ]
}