Issues Agent
This documents the legacy OpenAI issues agent, which remains the production default while the feature/issues-research-harness flag is OFF. For the native two-phase pipeline that replaces it, see Issue Research Pipeline.
The Issues Agent analyses news articles related to an organisation and generates clustered ESG issues. It identifies adverse environmental, social, and governance impacts, classifies the organisation's level of involvement, and creates structured issue records in the database.
Architecture
Agent Workflow
The agent processes articles through four sequential steps:
Step 1: Filter
Each article is evaluated for ESG relevance. The agent skips articles about general business news, earnings, product launches, executive appointments, or industry news without ESG concerns. Only articles describing adverse impacts related to a satellite mode proceed.
Step 2: Classify
For qualifying articles, the agent walks through a structured decision tree to determine the organisation's involvement type:
| Involvement | Meaning |
|---|---|
| CAUSED_BY | The organisation's own activities are sufficient to produce the adverse impact |
| CONTRIBUTED_TO | The organisation's activities increase the risk, but a third party must also act for the impact to occur |
| DIRECTLY_LINKED_TO | The organisation benefits commercially from a relationship where the impact occurs, without increasing the risk itself |
The classification follows the OECD Guidelines for Multinational Enterprises and the UN Guiding Principles on Business and Human Rights. See the full Involvement Definitions for the complete framework, decision tree, and examples.
Step 3: Match
The agent compares each article against existing issues for the organisation. An article matches an existing issue if it covers the same incident, provides updates on it, or references the same event from a different source.
Step 4: Create or Update
- Matched articles are connected to existing issues via the
updateIssuetool - Unmatched articles are grouped into new issue clusters and created via the
createIssuetool
When creating issues, the agent generates a title, a self-contained summary, assigns satellite modes, classifies involvement, and estimates a sentiment score.
Satellite Modes
Issues are tagged with one or more satellite modes that categorise the type of ESG concern:
| Mode | Covers |
|---|---|
| MODERN_SLAVERY | Labour exploitation, forced work, human trafficking, child labour, debt bondage, sweatshops, wage theft |
| EMISSIONS | Carbon/greenhouse gas emissions, pollution, toxic releases, environmental violations, waste dumping, chemical spills |
| BIODIVERSITY | Deforestation, habitat destruction, wildlife trafficking, illegal logging, ecosystem damage, land clearing |
Data Sources
Articles are loaded in parallel from three providers, each of which calls Diffbot's Article Extract API per URL to enrich the extracted content (title, body text, sentiment, language, site name, author, images):
| Provider | Method | Scope |
|---|---|---|
| Tavily | Web search API | Three separate searches by mode: modern slavery accusations, carbon emissions accusations, biodiversity accusations |
| SerpAPI | Google search | Three separate searches by mode (same modes as Tavily) |
| OpenAI | Hosted research agent | Single agent run that returns cited URLs across all modes |
All loaded articles are persisted via ArticleRepository before the agent processes them.
Outputs
The agent produces structured issue records stored in Neo4j:
| Output | Description |
|---|---|
| Issue | Title, summary text, date, sentiment score, involvement classification |
| Organisation-Issue link | Connects the issue to the organisation, tagged with satellite mode(s) |
| Article-Issue link | Connects supporting articles to the issue as references |
Sentiment Scoring
Issues are assigned a sentiment score based on severity:
| Score | Severity |
|---|---|
| -1.0 | Very negative (confirmed violations, legal action, deaths/injuries) |
| -0.7 | Negative (ongoing investigations, significant concerns, repeated incidents) |
| -0.5 | Moderately negative (allegations, potential violations) |
| -0.3 | Slightly negative (minor issues, early-stage concerns, isolated incidents) |
Trigger Points
The agent can be triggered from three locations:
| Trigger | Mechanism |
|---|---|
| Admin UI | generateIssuesAction server action on the organisation admin page |
| Background enrichment | Fanned out from enrich.ts (organisation.generate.issues) during search-select / upload enrichment |
| Spotlight / Analyst action | Invoked by the organisation.ensure-enriched orchestrator to refresh issues when a user runs a spotlight or analyst (ADR-0006) |
The Inngest function organisation-generate-issues runs with a concurrency limit of 20 (and 1 per organisation). It does not use an Inngest rate limit; instead it self-gates on enrichment freshness via enrichmentNeeds — skipped when issues are fresh within the 24h window (if-stale regime) or the profile is LOW-confidence, while a deliberate spotlight/analyst (always regime) bypasses the window to refresh. See ADR-0006.
Key Files
| File | Purpose |
|---|---|
packages/core/src/application/ai/agents/issues-agent.ts | Agent definition and system prompt |
packages/core/src/application/ai/agents/tools/create-issue.ts | Tool for creating new issues |
packages/core/src/application/ai/agents/tools/update-issue.ts | Tool for updating existing issues |
packages/core/src/application/use-cases/issue/generate-organisation-issues.ts | Use case orchestrating article loading and agent invocation |
packages/core/src/application/jobs/organisation/generate-issues.ts | Inngest function for background execution |
packages/core/src/infrastructure/repositories/issue-repository.ts | Issue data access |
packages/core/src/infrastructure/repositories/article-repository.ts | Article data access |