> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mavera.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Industry News → Persona-Analyzed Digest

> Pull today's top headlines for your industry, then run each story through Mavera Speak sessions with distinct executive personas for multi-perspective analysis

### Scenario

Your leadership team sees the same industry headlines but interprets them differently — your CMO cares about brand impact, your CTO cares about technology shifts, your CFO worries about market risk. This job pulls today's top headlines for your industry, then runs each story through Mavera Speak sessions with distinct executive personas. The output is a single digest where every story carries three different lenses of analysis.

**Flow:** NewsAPI `GET /top-headlines` → Mavera `POST /personas` → `POST /speak` per story → Multi-perspective digest

### Code

<CodeGroup>
  ```python Python theme={"dark"}
  import os, requests, time, json

  NA_KEY = os.environ["NEWSAPI_KEY"]
  NA_BASE = "https://newsapi.org/v2"
  NA_H = {"X-Api-Key": NA_KEY}
  MV = os.environ["MAVERA_API_KEY"]
  MV_BASE = "https://app.mavera.io/api/v1"
  MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}

  INDUSTRY = "technology"
  COUNTRY = "us"

  # 1. Fetch top headlines
  r = requests.get(f"{NA_BASE}/top-headlines", headers=NA_H, params={
      "category": INDUSTRY, "country": COUNTRY, "pageSize": 10,
  })
  r.raise_for_status()
  articles = r.json().get("articles", [])
  print(f"Fetched {len(articles)} headlines for {INDUSTRY}/{COUNTRY}")

  # 2. Create executive personas
  EXECS = [
      {"name": "CMO Lens", "desc": "Chief Marketing Officer. Evaluates news for brand impact, competitive positioning, consumer sentiment shifts, and content opportunities."},
      {"name": "CTO Lens", "desc": "Chief Technology Officer. Evaluates news for technology disruption, infrastructure implications, build-vs-buy decisions, and engineering talent market."},
      {"name": "CFO Lens", "desc": "Chief Financial Officer. Evaluates news for market risk, revenue impact, cost implications, investor sentiment, and regulatory exposure."},
  ]
  persona_ids = []
  for ex in EXECS:
      p = requests.post(f"{MV_BASE}/personas", headers=MV_H, json={
          "name": f"News Digest: {ex['name']}",
          "description": ex["desc"],
      }).json()
      persona_ids.append({"id": p["id"], "name": ex["name"]})
      time.sleep(0.3)

  # 3. Run each story through each persona via Speak
  digest = []
  for article in articles[:7]:
      story_block = f"**{article['title']}**\n{article.get('description','')}\nSource: {article.get('source',{}).get('name','')}"
      perspectives = {}

      for persona in persona_ids:
          speak = requests.post(f"{MV_BASE}/speak", headers=MV_H, json={
              "persona_id": persona["id"],
              "input": [
                  {"role": "system", "content": f"You are a {persona['name']}. Analyze this news story in 2-3 sentences from your executive perspective. Focus on actionable implications."},
                  {"role": "user", "content": story_block},
              ],
              "mode": "interview",
          }).json()
          answer = ""
          for ex in speak.get("exchanges", speak.get("messages", [])):
              if ex.get("role") == "assistant":
                  answer = ex["content"]
          perspectives[persona["name"]] = answer[:300]
          time.sleep(0.3)

      digest.append({"title": article["title"], "source": article.get("source",{}).get("name",""),
                     "perspectives": perspectives})

  # 4. Print digest
  for i, story in enumerate(digest, 1):
      print(f"\n{'='*60}\n{i}. {story['title']} ({story['source']})\n{'='*60}")
      for lens, analysis in story["perspectives"].items():
          print(f"\n  [{lens}]\n  {analysis}")
  ```

  ```javascript JavaScript theme={"dark"}
  const NA_KEY = process.env.NEWSAPI_KEY;
  const NA_BASE = "https://newsapi.org/v2";
  const NA_H = { "X-Api-Key": NA_KEY };
  const MV = process.env.MAVERA_API_KEY;
  const MV_BASE = "https://app.mavera.io/api/v1";
  const MV_H = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };

  const INDUSTRY = "technology";
  const COUNTRY = "us";

  // 1. Headlines
  const articles = (await (await fetch(
    `${NA_BASE}/top-headlines?category=${INDUSTRY}&country=${COUNTRY}&pageSize=10`,
    { headers: NA_H })).json()).articles || [];
  console.log(`Fetched ${articles.length} headlines for ${INDUSTRY}/${COUNTRY}`);

  // 2. Executive personas
  const EXECS = [
    { name: "CMO Lens", desc: "Evaluates for brand impact, positioning, sentiment shifts, content opportunities." },
    { name: "CTO Lens", desc: "Evaluates for tech disruption, infrastructure, build-vs-buy, talent market." },
    { name: "CFO Lens", desc: "Evaluates for market risk, revenue impact, cost, investor sentiment, regulation." },
  ];
  const personaIds = [];
  for (const ex of EXECS) {
    const p = await fetch(`${MV_BASE}/personas`, { method: "POST", headers: MV_H,
      body: JSON.stringify({ name: `News Digest: ${ex.name}`, description: ex.desc }),
    }).then(r => r.json());
    personaIds.push({ id: p.id, name: ex.name });
    await new Promise(r => setTimeout(r, 300));
  }

  // 3. Speak per story × persona
  const digest = [];
  for (const article of articles.slice(0, 7)) {
    const storyBlock = `**${article.title}**\n${article.description || ""}\nSource: ${article.source?.name || ""}`;
    const perspectives = {};

    for (const persona of personaIds) {
      const speak = await fetch(`${MV_BASE}/speak`, { method: "POST", headers: MV_H,
        body: JSON.stringify({ persona_id: persona.id, mode: "interview",
          input: [
            { role: "system", content: `You are a ${persona.name}. Analyze in 2-3 sentences. Actionable implications.` },
            { role: "user", content: storyBlock },
          ],
        }),
      }).then(r => r.json());
      const answer = (speak.exchanges || speak.messages || [])
        .filter(e => e.role === "assistant").map(e => e.content).join(" ");
      perspectives[persona.name] = answer.slice(0, 300);
      await new Promise(r => setTimeout(r, 300));
    }
    digest.push({ title: article.title, source: article.source?.name || "", perspectives });
  }

  // 4. Print
  for (const [i, story] of digest.entries()) {
    console.log(`\n${"=".repeat(60)}\n${i + 1}. ${story.title} (${story.source})\n${"=".repeat(60)}`);
    for (const [lens, analysis] of Object.entries(story.perspectives))
      console.log(`\n  [${lens}]\n  ${analysis}`);
  }
  ```
</CodeGroup>

### Example Output

```text theme={"dark"}
Fetched 10 headlines for technology/us

============================================================
1. Apple Announces New AI Chip for Consumer Devices (TechCrunch)
============================================================

  [CMO Lens]
  Messaging window opens — "AI-powered" positioning hits mainstream. Refresh
  product copy to lead with on-device intelligence before competitors adopt
  the same language. Content opportunity: comparison guide.

  [CTO Lens]
  On-device inference shifts build calculus. Evaluate whether our cloud-first
  ML pipeline should add edge deployment. Talent implication: need engineers
  with NPU experience within 12 months.

  [CFO Lens]
  Apple's capex signals hardware margin compression. Our cloud API costs may
  decrease as inference moves client-side. Watch for licensing model changes
  that affect our COGS.
```

### Error Handling

<AccordionGroup>
  <Accordion title="Truncated content">Free-tier articles return only 200 chars of content. Use `description` field as primary input, or upgrade to Business for full `content`.</Accordion>
  <Accordion title="Rate limits">Free tier: 100 req/day. This job uses 1 (headlines) + N×3 (Speak) calls to Mavera. Cache NewsAPI responses to avoid redundant calls on re-runs.</Accordion>
  <Accordion title="Category filtering">Valid categories: `business`, `entertainment`, `general`, `health`, `science`, `sports`, `technology`. Use `/everything` with `q` param for custom topics.</Accordion>
</AccordionGroup>
