{
  "_scaffold": "source-from-platform",
  "_description": "Source entities from a native app, normalize them, and upsert to KG with status:new. Pair with a downstream scoring workflow that reads status:new.",
  "name": "Source from Platform",
  "goal": "Source entities from a platform and write them to a Knowledge Graph list for downstream processing.",
  "status": "draft",
  "context": {
    "executionInputConfig": {
      "title": "Run Sourcing",
      "description": "Source entities and add them to the Knowledge Graph.",
      "runCTALabel": "Source",
      "fields": [
        { "name": "search_query", "label": "Search query", "type": "text", "required": true },
        { "name": "target_list_key", "label": "Target list key", "type": "text", "required": true, "defaultValue": "leads", "description": "Knowledge list key (e.g. \"leads\", \"startups\")." }
      ]
    }
  },
  "steps": [
    {
      "id": "start",
      "type": "trigger",
      "name": "Scheduled sourcing",
      "pipelineStepStartConditions": {
        "trigger": {
          "type": "schedule",
          "description": "Run weekly.",
          "config": { "frequency": "weekly", "dayOfWeek": "monday", "time": "08:00" }
        }
      },
      "next": { "stepId": "source-entities" }
    },
    {
      "id": "source-entities",
      "type": "appAction",
      "name": "Source entities",
      "_comment": "Replace the app with the source action. Run: agentled apps for-source <platform>",
      "app": { "id": "REPLACE_WITH_APP_ID", "actionId": "REPLACE_WITH_APP_ID.REPLACE_WITH_ACTION_ID", "source": "native" },
      "stepInputData": {
        "query": "{{input.search_query}}",
        "limit": "25"
      },
      "creditCost": 2,
      "next": { "stepId": "normalize-entities" }
    },
    {
      "id": "normalize-entities",
      "type": "aiAction",
      "name": "Normalize entities",
      "pipelineStepPrompt": {
        "template": "Extract real entities from the source output.\n\nSource output:\n{{steps.source-entities}}\n\nRules:\n- Keep only identifiable entities.\n- Use a stable userKey, preferably domain, profile URL, email, or canonical source URL.\n- Set rowData.status to \"new\".\n- Include source, source_url, sourced_at, and enough evidence for a downstream scoring workflow.\n- Do not score, find contacts, or draft outreach here.\n\nReturn JSON only.",
        "responseStructure": {
          "rows": "array of { userKey: string, rowData: object }",
          "count": "number"
        }
      },
      "creditCost": 5,
      "next": { "stepId": "save-entities" }
    },
    {
      "id": "save-entities",
      "type": "appAction",
      "name": "Save entities",
      "app": { "id": "kg", "actionId": "kg.upsert-rows", "source": "native" },
      "stepInputData": {
        "listKey": "{{input.target_list_key}}",
        "rows": "{{steps.normalize-entities.rows}}",
        "mergeStrategy": "merge",
        "status": "new"
      },
      "next": { "stepId": "done" }
    },
    {
      "id": "done",
      "type": "milestone",
      "name": "Sourcing complete"
    }
  ]
}
