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

# News Agent: crypto headline and sentiment analysis

> Fetch recent crypto headlines from NewsData.io and classify overall market sentiment as bullish, bearish, or neutral using keyword-based scoring.

The News Agent retrieves crypto news headlines from NewsData.io and scores each one against lists of bullish and bearish keywords. It aggregates the per-headline scores into an overall market sentiment verdict alongside per-sentiment counts and the full classified headline list. Stage 4/6 of the Elyra pipeline calls this agent automatically; you can also invoke it directly.

## Requirements

You need a NewsData.io API key. Get one at [newsdata.io](https://newsdata.io) and set it in your environment:

```bash theme={null}
export NEWSDATA_API_KEY=your_key_here
```

You can also pass the key directly as the `api_key` parameter. If the key is absent, the underlying collector will fail and the agent will raise an exception — unless the full pipeline is running, which catches the error and substitutes neutral defaults automatically.

## CLI usage

```bash theme={null}
python3 agents/news_agent.py
```

The script reads `NEWSDATA_API_KEY` from the environment and prints the full sentiment result as JSON.

## Python usage

```python theme={null}
from agents.news_agent import get_news_sentiment

result = get_news_sentiment(limit=10, query="cryptocurrency")
```

## `get_news_sentiment()`

Fetches up to `limit` headlines matching `query` from NewsData.io, classifies each headline as `"bullish"`, `"bearish"`, or `"neutral"`, and returns an aggregate sentiment result.

**Signature**

```python theme={null}
def get_news_sentiment(
    limit: int = 10,
    query: str = "cryptocurrency",
    api_key: str | None = None,
) -> dict[str, Any]
```

### Parameters

<ParamField path="limit" type="number" default="10">
  Maximum number of headlines to fetch from NewsData.io.
</ParamField>

<ParamField path="query" type="string" default="cryptocurrency">
  Search query passed to the NewsData.io API. Change this to focus on a specific asset or topic (e.g. `"bitcoin"`, `"solana ETF"`).
</ParamField>

<ParamField path="api_key" type="string">
  NewsData.io API key. If omitted, the function reads `NEWSDATA_API_KEY` from the environment.
</ParamField>

### Sentiment classification

Each headline's title and description are combined, lowercased, and matched against two keyword lists:

* **Bullish keywords** include: `surge`, `rally`, `gain`, `bullish`, `breakout`, `all-time high`, `ath`, `adoption`, `etf`, `approval`, `record high`, and others.
* **Bearish keywords** include: `crash`, `plunge`, `drop`, `bearish`, `collapse`, `ban`, `crackdown`, `hack`, `exploit`, `liquidation`, and others.

A headline is classified as `"bullish"` if its bullish keyword count exceeds its bearish count, `"bearish"` if the reverse is true, and `"neutral"` if they are equal.

The overall `sentiment` field is set to whichever per-headline class has a strict majority. If no class has a strict majority, the overall sentiment is `"neutral"`.

### Return value

Returns `dict[str, Any]`.

<ResponseField name="sentiment" type="string" required>
  Aggregate market sentiment across all fetched headlines. One of `"bullish"`, `"bearish"`, or `"neutral"`.
</ResponseField>

<ResponseField name="bullish_count" type="number" required>
  Number of headlines classified as bullish.
</ResponseField>

<ResponseField name="bearish_count" type="number" required>
  Number of headlines classified as bearish.
</ResponseField>

<ResponseField name="neutral_count" type="number" required>
  Number of headlines classified as neutral.
</ResponseField>

<ResponseField name="headlines" type="object[]" required>
  List of classified headline objects, one per fetched article.

  <Expandable title="Headline object fields">
    <ResponseField name="title" type="string">
      The article headline text.
    </ResponseField>

    <ResponseField name="source" type="string">
      Publication name as returned by NewsData.io (`source_name` field).
    </ResponseField>

    <ResponseField name="sentiment" type="string">
      Per-headline classification: `"bullish"`, `"bearish"`, or `"neutral"`.
    </ResponseField>
  </Expandable>
</ResponseField>

### Example response

```json theme={null}
{
  "sentiment": "bullish",
  "bullish_count": 6,
  "bearish_count": 2,
  "neutral_count": 2,
  "headlines": [
    {
      "title": "Bitcoin surges past $70,000 as ETF inflows accelerate",
      "source": "CoinDesk",
      "sentiment": "bullish"
    },
    {
      "title": "Crypto regulation crackdown continues in Asia",
      "source": "Reuters",
      "sentiment": "bearish"
    }
  ]
}
```

## Graceful degradation

If `NEWSDATA_API_KEY` is not set and no `api_key` argument is provided, the full pipeline (`main.py`) catches the resulting error and substitutes these neutral defaults:

```json theme={null}
{
  "sentiment": "neutral",
  "bullish_count": 0,
  "bearish_count": 0,
  "note": "NewsData API not configured"
}
```

The pipeline continues through the remaining stages — only news-derived context will be absent from the final report.

<Note>
  Sentiment classification uses predefined keyword lists for bullish and bearish signals. The bullish list includes terms like `surge`, `rally`, `ath`, `etf`, and `adoption`. The bearish list includes terms like `crash`, `hack`, `exploit`, `ban`, and `liquidation`.
</Note>
