Entities (the data model)
- Policy Event
PolicyEvent - One government/news action about pharma trade — a tariff change, an export restriction, a regulatory probe. Extracted by the Policy Agent from a raw government notice or news item, filtered for actual pharma relevance (most raw pulls are noise and get discarded). Has a country, policy type, affected product, date, severity, and a source citation. e.g. a Federal Register notice cutting US tariffs on EU-origin generic drugs
- Filing Mention
FilingMention - One disclosed dependency from a company's own SEC 10-K — "we manufacture in Ireland," "we depend on China-based API suppliers." Extracted by the Filing Agent from cached filing excerpts, filtered to exclude generic boilerplate and incidental country mentions (e.g. "we sell our drug in Japan" does NOT count — that's a market, not a sourcing/manufacturing dependency). e.g. AbbVie's 10-K listing manufacturing sites in Ireland
- Graph Link
GraphLink -
A confirmed connection between one Policy Event and one Filing Mention, found because they share
a country (and optionally a commodity). This is the actual cross-referencing step — checking
whether a policy notice and a company's own words are talking about the same place. Plain country
string matching, done in
src/graph.py, no LLM call. - Alert Card
- The final, human-readable output for one Graph Link: a title, a severity, and a plain-English explanation that must cite both the policy source and the filing source. One more LLM call per link, given only the specific policy snippet and filing excerpt (grounding both facts and, per the prompt, forbidding invented specifics not in that text).
Gap vs. Opportunity
Neither side of a Graph Link is "more correct" than the other — a link needs BOTH a matching Policy Event AND a matching Filing Mention. Either side can be the one that's missing:
- Gap
- A Filing Mention with no matching Policy Event. A company disclosed a real dependency in its own 10-K, but nothing on the policy side confirms or contextualizes it yet. e.g. Eli Lilly's 10-K states it depends on China-based API suppliers, but this run's policy data pull has no China-specific tariff notice to link it to
- Opportunity
- A Policy Event with no matching Filing Mention. A real policy action happened, but no covered company's filing has been tied to it yet — worth a closer read of that company's filing, or it may mean none of the companies tracked in this segment are actually exposed. e.g. a US-Switzerland tariff notice exists, but no tracked company's filing names Switzerland as a manufacturing/sourcing location this run
Graph terms
- Catalyst
-
The graph's leftmost node — a Policy Event's short, human-readable
headline(e.g. "US-EU Framework Tariff Cut on Generic Drugs"), generated by the Policy Agent specifically so a reader isn't stuck decoding a rawcountry / policy_typepair. - Shared country / EU bloc matching
-
The country a Policy Event and a Filing Mention have in common — the actual condition
src/graph.pychecks to form a link. Some government notices describe an EU-wide action ("products of the European Union") without naming one specific member state; those are recorded as country"European Union"and matched against a Filing Mention naming any EU member (seeEU_MEMBERSinsrc/graph.py), with the link's displayed "shared country" resolved to that specific member state, not the literal bloc name. - hop_count / confidence
-
hop_count: 1(confidence 0.9) means the Policy Event and Filing Mention share both country AND commodity.hop_count: 2(confidence 0.6) means they share only the country. Commodity-only matches (same product, different country) are deliberately excluded from the graph entirely — too weak a signal at this scope. - Detailed vs. Simplified view
- Detailed shows all four columns: Catalyst → Policy Scope (the event's raw country/commodity) → Shared Country → Company. Simplified collapses the middle two into one hop: Catalyst → Country → Company.
Pipeline / evaluation terms
- Baseline
-
A single direct LLM prompt over the same raw cached text (no graph, no forced citations, no
structure) — the comparison point the two-agent pipeline has to beat. Generated once
(
data/baseline_output.json) and frozen; never regenerated after the Phase 6 evaluation runs against it, so the comparison stays reproducible. - Trajectory
-
A saved log of one real agent call: the exact system prompt, user prompt, raw model response, and
parsed output, written to
trajectories/during the actual pipeline run — not reconstructed afterward. - Golden case
-
One hand-labeled test case in
eval/golden_events_pharma.yaml— a specific company/country pair with a known correct answer (should the pipeline find a link, or correctly not find one), written from manually reviewing the cached raw data.