AutomationFlowsAI & RAG › Send Daily World Cup 2026 Briefings to Slack with Openai Gpt-5 Mini

Send Daily World Cup 2026 Briefings to Slack with Openai Gpt-5 Mini

ByRedowan Ahmed Farhan @redowanfarhan on n8n.io

This workflow runs every morning in Asia/Dhaka, pulls FIFA World Cup 2026 fixtures, standings, teams, and stadium data from worldcup26.ir, uses OpenAI to generate a compact next-day briefing with Bangladesh-local kickoff times, and posts the report to a Slack channel. Runs daily…

Cron / scheduled trigger★★★★☆ complexityAI-powered15 nodesHTTP RequestAgentSlackOpenAI Chat
AI & RAG Trigger: Cron / scheduled Nodes: 15 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #16429 — we link there as the canonical source.

This workflow follows the Agent → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "2wGEVnV2X8031sB8",
  "name": "World Cup 2026 \u2014 Daily Briefing",
  "tags": [],
  "nodes": [
    {
      "id": "8bab0119-cd4b-4817-8f4f-03909d82e7ea",
      "name": "Main Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -208,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 1156,
        "content": "## \ud83c\udfc6 World Cup 2026 Daily Briefing\n\nEvery morning this workflow pulls live FIFA World Cup 2026 data, converts all kickoff times to Bangladesh time, asks an AI analyst to write a compact, phone friendly preview of the next day, and posts it straight to Slack.\n\n**Perfect for:** football communities, sports Slack channels, and fan group admins who want an automated daily matchday digest in local time.\n\n***\n\n## How it works\n\n1. **Every Day 07:00 (Asia/Dhaka):** Schedule trigger that fires once daily at 7am Bangladesh time.\n2. **Set Date (BD):** Computes today, yesterday, tomorrow, and a human readable tomorrow date in the Asia/Dhaka timezone.\n3. **Get Games:** Fetches the full match schedule from the worldcup26.ir feed.\n4. **Get Groups:** Fetches group standings tables from the same feed.\n5. **Get Teams:** Fetches the team list with names and FIFA codes.\n6. **Get Stadiums:** Fetches venue and host city details.\n7. **Build Context + Prompt:** Joins all four feeds, converts US venue kickoffs to Bangladesh time, selects tomorrow's fixtures plus recent results, and builds the mobile first AI prompt.\n8. **OpenAI Chat Model1:** GPT 5 Mini model that powers the agent.\n9. **AI Agent:** Generates the formatted matchday briefing (fixtures, win estimates, key players, standings) from the prompt.\n10. **Extract Report Text:** Normalizes the AI output into clean Slack ready text, with a fallback warning if nothing was generated.\n11. **Send to Slack:** Posts the final briefing to your chosen Slack channel as mrkdwn.\n\n***\n\n## Setup (~10 minutes)\n\n1. **OpenAI API:** Add your credential in the *OpenAI Chat Model1* node (model is set to GPT 5 Mini).\n2. **Slack OAuth2:** Connect your Slack account in the *Send to Slack* node and pick the target channel.\n3. **Schedule:** Adjust the cron in *Every Day 07:00 (Asia/Dhaka)* if you want a different delivery time.\n> The match feeds come from the public worldcup26.ir endpoints, so no API key is needed for data. Always run the full workflow from the trigger, because *Build Context + Prompt* reads from every upstream fetch node."
      },
      "typeVersion": 1
    },
    {
      "id": "c0bdaa10-2529-4760-8c21-ae4a6d98bcd2",
      "name": "Section 1 - Trigger & Intake",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        112
      ],
      "parameters": {
        "color": 5,
        "width": 1400,
        "height": 348,
        "content": "## 1\ufe0f\u20e3 Trigger & Data Intake\n\nThe **Every Day 07:00 (Asia/Dhaka)** schedule trigger starts the run each morning, and **Set Date (BD)** calculates the relevant dates in Bangladesh time. The workflow then fetches all live tournament data in sequence through **Get Games**, **Get Groups**, **Get Teams**, and **Get Stadiums**, pulling fixtures, standings, team names, and venue details from the worldcup26.ir feeds."
      },
      "typeVersion": 1
    },
    {
      "id": "43192b08-ce07-437c-bef5-79bbba560faf",
      "name": "Section 2 - AI Core",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        896,
        480
      ],
      "parameters": {
        "color": 3,
        "width": 540,
        "height": 696,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## 2\ufe0f\u20e3 Prompt Building & AI Analysis\n\n**Build Context + Prompt** merges the four feeds, converts each US venue kickoff into Bangladesh time, and assembles a compact, mobile first prompt covering tomorrow's fixtures, recent results, and standings. The **AI Agent**, powered by the **OpenAI Chat Model1** (GPT 5 Mini), turns that prompt into a skimmable briefing with fixtures, win percentage estimates, key players, and group tables."
      },
      "typeVersion": 1
    },
    {
      "id": "e31b6855-3108-4eb5-972a-ee96b5e0a5e3",
      "name": "Section 3 - Output",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        480
      ],
      "parameters": {
        "color": 6,
        "width": 568,
        "height": 392,
        "content": "\n\n\n\n\n\n\n\n\n\n## 3\ufe0f\u20e3 Format & Deliver\n\n**Extract Report Text** normalizes the AI Agent output into clean, Slack ready text and adds a fallback message if no briefing was produced. **Send to Slack** then posts the finished daily digest to your chosen channel using Slack mrkdwn formatting."
      },
      "typeVersion": 1
    },
    {
      "id": "f1013ec4-268e-4e16-9200-efc8dd1cb37f",
      "name": "Every Day 07:00 (Asia/Dhaka)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        528,
        288
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 7 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "cf0d57db-f0c3-44d6-acb0-bf1d09dfc22c",
      "name": "Set Date (BD)",
      "type": "n8n-nodes-base.set",
      "position": [
        752,
        288
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "date",
              "type": "string",
              "value": "={{ $now.setZone('Asia/Dhaka').toFormat('yyyy-LL-dd') }}"
            },
            {
              "id": "a2",
              "name": "yesterday",
              "type": "string",
              "value": "={{ $now.setZone('Asia/Dhaka').minus({ days: 1 }).toFormat('yyyy-LL-dd') }}"
            },
            {
              "id": "a3",
              "name": "tomorrow",
              "type": "string",
              "value": "={{ $now.setZone('Asia/Dhaka').plus({ days: 1 }).toFormat('yyyy-LL-dd') }}"
            },
            {
              "id": "a4",
              "name": "tomorrowHuman",
              "type": "string",
              "value": "={{ $now.setZone('Asia/Dhaka').plus({ days: 1 }).toFormat('cccc, dd LLLL yyyy') }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c45e517c-d1cf-4f89-b8f3-6a8a0bcbb5ff",
      "name": "Get Games",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        976,
        288
      ],
      "parameters": {
        "url": "https://worldcup26.ir/get/games",
        "options": {}
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "1a772049-7002-48f7-8f8f-250365eb6234",
      "name": "Get Groups",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1168,
        288
      ],
      "parameters": {
        "url": "https://worldcup26.ir/get/groups",
        "options": {}
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "e1cdd438-5954-4610-be50-d4c44a8e73c4",
      "name": "Get Teams",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1376,
        288
      ],
      "parameters": {
        "url": "https://worldcup26.ir/get/teams",
        "options": {}
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "ccb48fed-e5ea-4a75-9a7f-0e197b2ff9d0",
      "name": "Get Stadiums",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1568,
        288
      ],
      "parameters": {
        "url": "https://worldcup26.ir/get/stadiums",
        "options": {}
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "9d7322df-5b6e-4a87-bb72-c4ae2983b088",
      "name": "Build Context + Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        976,
        528
      ],
      "parameters": {
        "jsCode": "// Build Context + Prompt \u2014 join worldcup26.ir feeds, convert kickoffs (US venue time) to Bangladesh time, build a COMPACT MOBILE-FIRST next-day prompt.\n// Suffix-proof: auto-resolves duplicated node names (Get Teams, Get Teams1, Get Teams2 ...).\nfunction pickNode(base){\n  for (let s = 0; s <= 5; s++){\n    const nm = s === 0 ? base : base + s;\n    let raw;\n    try { raw = $(nm).all(); } catch (e) { continue; }\n    if (raw && raw.length) return raw.map(i => i.json);\n  }\n  throw new Error('No executed node found for \"' + base + '\". Run the FULL workflow from the trigger (Test workflow), not a single step.');\n}\nfunction unwrap(items){\n  if (items.length === 1){\n    const j = items[0] || {};\n    if (Array.isArray(j)) return j;\n    for (const k of ['data','teams','games','groups','stadiums','result','results']){\n      if (Array.isArray(j[k])) return j[k];\n    }\n  }\n  return items;\n}\n\nlet dWrap;\nfor (let s = 0; s <= 5; s++){\n  const nm = s === 0 ? 'Set Date (BD)' : 'Set Date (BD)' + s;\n  try { const v = $(nm).first(); if (v){ dWrap = v.json; break; } } catch (e) {}\n}\nif (!dWrap) throw new Error('Set Date (BD) node not found/executed. Run the full workflow from the trigger.');\nconst yest = dWrap.yesterday;\nconst schedDate = dWrap.tomorrow;        // preview the NEXT day\nconst schedHuman = dWrap.tomorrowHuman;\n\nconst teams = unwrap(pickNode('Get Teams'));\nconst games = unwrap(pickNode('Get Games'));\nconst groups = unwrap(pickNode('Get Groups'));\nconst stadiums = unwrap(pickNode('Get Stadiums'));\n\nconst teamMap = {};\nfor (const t of teams){ teamMap[String(t.id)] = t; }\nconst stadMap = {};\nfor (const s of stadiums){ stadMap[String(s.id)] = s; }\n\nfunction teamName(id){ const t = teamMap[String(id)]; return t ? (t.name_en || t.name || ('Team '+id)) : ('Team '+id); }\nfunction teamCode(id){ return (teamMap[String(id)] || {}).fifa_code; }\n\n// Host-city -> IANA timezone (16 WC2026 venues across USA / Mexico / Canada)\nfunction tzForCity(city){\n  const c = String(city||'').toLowerCase();\n  if (/inglewood|los angeles|santa clara|san francisco|bay area|seattle/.test(c)) return 'America/Los_Angeles';\n  if (/arlington|dallas|houston|kansas/.test(c)) return 'America/Chicago';\n  if (/atlanta|foxborough|boston|miami|rutherford|new jersey|new york|philadelphia|toronto/.test(c)) return 'America/New_York';\n  if (/monterrey/.test(c)) return 'America/Monterrey';\n  if (/guadalajara|mexico/.test(c)) return 'America/Mexico_City';\n  if (/vancouver/.test(c)) return 'America/Vancouver';\n  return 'America/New_York';\n}\n\nconst enriched = games.map(g => {\n  const st = stadMap[String(g.stadium_id)] || {};\n  const city = st.city_en || st.city || '';\n  const tz = tzForCity(city);\n  const dt = DateTime.fromFormat(String(g.local_date || ''), 'MM/dd/yyyy HH:mm', { zone: tz });\n  const bd = dt.isValid ? dt.setZone('Asia/Dhaka') : null;\n  return {\n    id: g.id,\n    home: g.home_team_name_en || teamName(g.home_team_id),\n    away: g.away_team_name_en || teamName(g.away_team_id),\n    home_code: teamCode(g.home_team_id),\n    away_code: teamCode(g.away_team_id),\n    group: g.group,\n    stage: g.type,\n    venue: st.name_en || ('Stadium ' + g.stadium_id),\n    city: city,\n    bd_time: bd ? bd.toFormat('h:mm a') : null,\n    kickoff_bd: bd ? (bd.toFormat('ccc dd LLL, h:mm a') + ' BDT') : null,\n    kickoff_us_local: dt.isValid ? dt.toFormat('ccc h:mm a ZZZZ') : g.local_date,\n    kickoff_bd_date: bd ? bd.toFormat('yyyy-LL-dd') : null,\n    finished: String(g.finished).toUpperCase() === 'TRUE',\n    score: (g.home_score != null && g.away_score != null) ? (g.home_score + '-' + g.away_score) : null\n  };\n});\n\nconst matches = enriched.filter(g => g.kickoff_bd_date === schedDate);\nconst recentResults = enriched.filter(g => g.kickoff_bd_date === yest && g.finished);\nconst upcomingMatches = enriched\n  .filter(g => g.kickoff_bd_date && g.kickoff_bd_date > schedDate && !g.finished)\n  .sort((a,b) => (a.kickoff_bd_date + a.bd_time).localeCompare(b.kickoff_bd_date + b.bd_time))\n  .slice(0, 8);\n\nconst standings = groups.map(gr => {\n  const rows = (gr.teams || gr.table || []).map(t => {\n    const gf = Number(t.gf), ga = Number(t.ga);\n    return {\n      team: teamName(t.team_id || t.id),\n      P: t.mp, W: t.w, D: t.d, L: t.l,\n      GD: (Number.isFinite(gf) && Number.isFinite(ga)) ? (gf - ga) : t.gd,\n      Pts: t.pts != null ? t.pts : t.points\n    };\n  }).sort((a,b) => {\n    const pa = Number(a.Pts)||0, pb = Number(b.Pts)||0; if (pb !== pa) return pb - pa;\n    return (Number(b.GD)||0) - (Number(a.GD)||0);\n  });\n  return { group: gr.name, table: rows };\n});\n\nconst context = { scheduleDate: schedDate, scheduleHuman: schedHuman, matchCount: matches.length, timezone: 'Asia/Dhaka', matches, recentResults, upcomingMatches, standings };\n\nconst prompt = [\n  'You are a professional football analyst producing a COMPACT, MOBILE-FIRST daily FIFA World Cup 2026 briefing for Slack.',\n  'The reader is in Bangladesh (Asia/Dhaka, UTC+6); the tournament is hosted in the USA, Canada and Mexico. This briefing PREVIEWS the schedule for ' + schedHuman + ' (' + schedDate + ').',\n  '',\n  'CORRECTNESS: the DATA block is LIVE official data (schedule, teams, standings, venues, scores) \u2014 treat it as GROUND TRUTH, never contradict or invent it. bd_time, kickoff_bd and kickoff_us_local are pre-computed \u2014 use them verbatim. Squads, player clubs and win probabilities are YOUR analysis (label win % as estimates); only name players/clubs you are confident about for the 2025/26 season.',\n  '',\n  'MOBILE FORMAT (CRITICAL): most readers use Slack on a PHONE. Do NOT use triple-backtick code blocks, tables, or pipe (|) alignment \u2014 they get cut off and wrap badly on small screens. Use ONLY short bullet lines. Slack mrkdwn: *bold*, _italic_, bullet \"\u2022\". Keep every line short.',\n  '',\n  'Produce these sections IN THIS ORDER, nothing extra:',\n  '1) Bold title line: \ud83c\udfc6 WC2026 \u2014 <schedule weekday + short date e.g. Mon 15 Jun> \u2022 <matchCount> matches \u2022 times BDT',\n  '2) If recentResults is non-empty, ONE italic line: _Last: CODE x-y CODE \u2022 CODE x-y CODE_ (FIFA codes + score).',\n  '3) *\u26bd Fixtures* then, per match in matches, TWO short lines: line one \"\u2022 <bd_time> \u2014 <HOME_CODE> v <AWAY_CODE> (<Grp>)\"; line two indented \"    <stadium>, <city> \u2022 <kickoff_us_local>\". Use FIFA codes. If matches is empty, write \"\u2022 No matches \u2014 next up:\" then the next few upcomingMatches the same way.',\n  '4) *\ud83d\udd2e Win % (H/D/A est.)* then ONE line per match: \"\u2022 <HOME_CODE> v <AWAY_CODE> \u2014 H/D/A\" as plain numbers, e.g. \"\u2022 NED v JPN \u2014 55/25/20\" (each set sums about 100).',\n  '5) *\u2b50 Key players* then ONE line per team in matches: \"\u2022 CODE: Player (Club), Player (Club)\" \u2014 max 2 stars each, only when confident; skip a team if unsure.',\n  '6) *\ud83d\udcca Standings (P/GD/Pts)* then, for each group appearing in matches: a \"*Group X*\" line, then one line per team \"\u2022 Team \u2014 P/GD/Pts\" sorted as given. If matches is empty, show all 12 groups this way.',\n  '7) Final italic line: _Have a great matchday!_ \u26bd',\n  '',\n  'Keep the whole message tight and skimmable on a phone. Absolutely no code blocks, no tables, no pipe alignment.',\n  '',\n  'DATA:',\n  JSON.stringify(context)\n].join('\\n');\n\nreturn [{ json: { scheduleDate: schedDate, scheduleHuman: schedHuman, prompt, context } }];\n"
      },
      "executeOnce": true,
      "typeVersion": 2
    },
    {
      "id": "ef873e21-d4d0-4924-8a13-102e4ee9bc09",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1232,
        528
      ],
      "parameters": {
        "text": "={{ $json.prompt }}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "263afb6d-aa6f-4f88-9214-0f2b7f4ebba0",
      "name": "Extract Report Text",
      "type": "n8n-nodes-base.code",
      "position": [
        1520,
        528
      ],
      "parameters": {
        "jsCode": "// Normalize the report text from an AI Agent node (output) OR the Claude Messages API (content[]).\nconst data = $input.first().json || {};\nlet report = '';\nif (typeof data.output === 'string') {\n  report = data.output.trim();                       // n8n AI Agent / LangChain node\n} else if (typeof data.text === 'string') {\n  report = data.text.trim();                          // Basic LLM Chain node\n} else if (Array.isArray(data.content)) {\n  report = data.content.filter(b => b.type === 'text').map(b => b.text).join('\\n').trim(); // raw Claude API\n} else if (data.message && typeof data.message.content === 'string') {\n  report = data.message.content.trim();\n}\nif (!report) {\n  report = '\u26a0\ufe0f No World Cup briefing was generated today. Check the AI Agent output and upstream feeds.';\n}\nreturn [{ json: { report } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "844b7830-d1b6-4444-9400-c1a59a151a4b",
      "name": "Send to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        1712,
        528
      ],
      "parameters": {
        "text": "={{ $json.report }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0BAJGKUQ04",
          "cachedResultName": "worldcup-2026"
        },
        "otherOptions": {
          "mrkdwn": true
        },
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "80dc115e-429c-4ca5-8fc7-9d8f3de23f0c",
      "name": "OpenAI Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1248,
        752
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "2dfefc21-1e18-4e49-94b1-efbbebf184a5",
  "nodeGroups": [],
  "connections": {
    "AI Agent": {
      "main": [
        [
          {
            "node": "Extract Report Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Games": {
      "main": [
        [
          {
            "node": "Get Groups",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Teams": {
      "main": [
        [
          {
            "node": "Get Stadiums",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Groups": {
      "main": [
        [
          {
            "node": "Get Teams",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Stadiums": {
      "main": [
        [
          {
            "node": "Build Context + Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Date (BD)": {
      "main": [
        [
          {
            "node": "Get Games",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Extract Report Text": {
      "main": [
        [
          {
            "node": "Send to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Context + Prompt": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every Day 07:00 (Asia/Dhaka)": {
      "main": [
        [
          {
            "node": "Set Date (BD)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow runs every morning in Asia/Dhaka, pulls FIFA World Cup 2026 fixtures, standings, teams, and stadium data from worldcup26.ir, uses OpenAI to generate a compact next-day briefing with Bangladesh-local kickoff times, and posts the report to a Slack channel. Runs daily…

Source: https://n8n.io/workflows/16429/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Created by: Peyton Leveillee Last updated: October 2025

OpenAI Chat, Google Sheets, HTTP Request +5
AI & RAG

Runs automatically every Monday morning at 8 AM Collects your Google Search Console from the last month and the month before that for a given url (date range is configurable) Formats the data, aggrega

N8N Nodes Pdforge, HTTP Request, OpenAI Chat +2
AI & RAG

This workflow automates end-to-end sustainability lifecycle management for corporate sustainability teams, ESG governance officers, and circular economy programme leads. It addresses the challenge of

Form Trigger, Agent, OpenAI Chat +11
AI & RAG

Marketing, content, and enablement teams that need a quick, human-readable summary of every new video published by the YouTube channels they care about—without leaving Slack.

HTTP Request, Google Sheets, XML +7
AI & RAG

This workflow automates end-to-end ESG (Environmental, Social, and Governance) sustainability reporting for enterprise sustainability teams, compliance officers, and green governance leads. It solves

Agent, OpenAI Chat, Output Parser Structured +12