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

# Schemas

> Tell the AI what to extract from your documents

A schema is a set of instructions for extracting structured data from documents. You describe what you want in plain English, the AI applies it consistently across hundreds or thousands of items.

Schemas bridge natural language and structured data. You express your framework in plain English, and get back consistent, well-defined results ready for analysis, data management and export.

## What You Get

<Card title="Output from a schema analysing EU Parliament speeches on migration">
  <Frame>
    <img src="https://mintcdn.com/openpolitics/ROUsCWRLaAxCeMdD/images/result-speeches-light.png?fit=max&auto=format&n=ROUsCWRLaAxCeMdD&q=85&s=f92915983f633d107772819b21fcde28" alt="Schema results showing extracted fields from parliamentary speeches" className="block dark:hidden" width="684" height="674" data-path="images/result-speeches-light.png" />

    <img src="https://mintcdn.com/openpolitics/ROUsCWRLaAxCeMdD/images/result-speeches-dark.png?fit=max&auto=format&n=ROUsCWRLaAxCeMdD&q=85&s=6163063d085f1138d0bc217bba06f543" alt="Schema results showing extracted fields from parliamentary speeches" className="hidden dark:block" width="666" height="336" data-path="images/result-speeches-dark.png" />
  </Frame>
</Card>

Each speech gets analysed for the same fields: position summary, security stance (1-10), location mentions, talking point topics, migration attitude, governance focus, rhetoric style. The schema defines what to extract - the AI does the extraction.

With structured output, you can filter, compare, and visualise. Which speakers emphasise humanitarian concerns vs. security? How does rhetoric differ by country? That's the point.

<Card title="The schema that was used to extract the data">
  <img className="hidden dark:block" src="https://mintcdn.com/openpolitics/8cGtUBrqnMmvhvjY/images/schema-pretty-speeches-dark.png?fit=max&auto=format&n=8cGtUBrqnMmvhvjY&q=85&s=ceac9e76ea5e828f2287b80759c709b6" alt="Schema" width="100%" data-path="images/schema-pretty-speeches-dark.png" />

  <img className="block dark:hidden" src="https://mintcdn.com/openpolitics/8cGtUBrqnMmvhvjY/images/schema-pretty-speeches-light.png?fit=max&auto=format&n=8cGtUBrqnMmvhvjY&q=85&s=7d5ce6df6abef1a61076ea207fd42d5d" alt="Schema" width="100%" data-path="images/schema-pretty-speeches-light.png" />
</Card>

## Building a Schema

Start with your actual questions. What do you want to know about your documents?

* What positions are being taken?
* How is the issue framed?
* Who's mentioned, and in what context?
* What's the emotional temperature?

Then turn each question into an extraction field.

### Good Instructions vs. Vague Instructions

The difference between useful output and noise is specificity.

<Tabs>
  <Tab title="✓ This works">
    <CardGroup cols={2}>
      <Card title="security_stance" icon="shield">
        **Type:** Number (1-10)\
        **Extract:** Position on border security. 1 = open borders, 10 = strict enforcement
      </Card>

      <Card title="talking_point_topics" icon="list">
        **Type:** List\
        **Extract:** Main topics discussed - migration policy, demographic change, EU solidarity, public services, etc.
      </Card>
    </CardGroup>

    *Clear scales, concrete categories, examples of valid values.*
  </Tab>

  <Tab title="✗ This doesn't">
    <Card title="position" icon="question">
      **Type:** Text\
      **Extract:** What is their position on the issue?
    </Card>

    *Too vague. Which issue? What aspects of their position? The AI will guess, and guesses vary.*
  </Tab>
</Tabs>

### Field Types

| Type       | Use for                                       | Example                                  |
| ---------- | --------------------------------------------- | ---------------------------------------- |
| **String** | Freeform text, summaries, answers, categories | `summary: "Speaker argues for..."`       |
| **Number** | Ratings, scales, counts, amounts              | `security_stance: 7`                     |
| **List**   | Multiple values, tags, topics                 | `topics: ["migration", "EU solidarity"]` |

<Note>**Binary fields for filtering:** It's often useful to include 0/1 or yes/no fields for filtering results. Something like `is_spam: 0` or `is_relevant: 1` lets you quickly filter out noise in dashboards.</Note>

### Special Field Names

Certain field names unlock specific features when you view results:

| Field name  | What it enables                                                            | How to prompt                                                           |
| ----------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `location`  | Geographic maps - locations get geocoded and plotted                       | Ask for single most relevant location or region relevant                |
| `timestamp` | Time series charts - combine with number fields to track changes over time | Ask for a ISO timestamp of the article's main event or publication date |
| `summary`   | Highlighted in result views as the main description                        | Ask for a summary with your preferred style and length                  |
| `tags`      | Counted and aggregated across results                                      | Either freeform or just from a few given tags                           |

<Note>It is always good to provide a fallback choice like "None" or "Unapplicable".</Note>

Other list fields also get counted automatically. If you extract `talking_point_topics` as a list, you'll see frequency distributions in dashboards.

Numbers with defined scales (1-10, 1-5) work well for comparative analysis - they enable meaningful aggregation and time series when combined with timestamps.

***

## Tips

**Include examples in your instructions.** "Source type: government, activist, expert, journalist, or anonymous" gives the AI a bounded set to work with.

**Use scales for subjective measures.** "Emotional intensity (1-10)" is more useful than "how emotional is it?" because you can aggregate and compare.

**Start simple, then add.** Begin with basic extraction (who, what, where), confirm it works, then layer in analysis fields (sentiment, framing, stance).

**Look at failures.** When extraction is wrong or inconsistent, the instructions usually need tightening. What did the AI misunderstand?

***

## Sharing Schemas

Schemas can be uploaded to the library for others to use. They can see your methodology, critique it, replicate it, build on it. Transparency about how analysis is done matters - it's what separates systematic research from vibes.

***

## Related pages

<CardGroup cols={2}>
  <Card title="Running Analysis" icon="play" href="/pages/concepts/running-analysis">
    Apply schemas to your documents
  </Card>

  <Card title="Curating Fragments" icon="star" href="/pages/concepts/curating-fragments">
    Promote extractions to persistent metadata
  </Card>

  <Card title="Assets & Bundles" icon="folder" href="/pages/app/assets">
    Upload and organise documents for analysis
  </Card>

  <Card title="Dashboards" icon="chart-line" href="/pages/app/dashboards">
    Visualise results with charts and tables
  </Card>
</CardGroup>
