Contrary

Prediction markets tell you what the crowd believes. Contrary tells you where the crowd might be wrong.

Inspiration

Prediction markets usually give you one number. We kept wanting the next sentence: why might that number be wrong?

We also noticed that a lot of AI forecasting tools are basically chatbots. You open them, type a prompt, and hope the model gives you something useful.

We wanted something that felt more like a real product. It should already know what you care about, show you the forecast right away, and let you understand how it got there.

That is what led us to build Contrary.

The problem

If a prediction market says something has a 72% chance of happening, that still leaves a lot of questions.

Is that number based on a deep and stable market, or did it move quickly on low volume? Is the crowd actually thinking about the resolution criteria, or just reacting to a headline?

There is also a discovery problem. If you mainly care about AI or tech, you should not have to scroll through a feed full of sports and politics just to find relevant markets.

Platforms like Polymarket and Kalshi do a great job of showing what the market believes.

Contrary is focused on a different question: Where could the market be wrong?

Current market

Prediction markets have grown a lot, with billions of dollars now moving through platforms like Kalshi and Polymarket.

But most products still stop at the market price.

  • Polymarket and Kalshi show the current probability.
  • Metaculus and similar platforms are built around human forecasting communities.
  • AI forecasting tools often give you a chat box and a model-generated number.

We wanted to build something in between. Contrary gives you an independent forecast next to the market, then shows you why the two disagree.

What it does

Contrary is a forecasting dashboard. There is no chat box.

You browse real-world questions and see:

  • Market consensus vs Contrary's probability
  • The gap between the two
  • Five specialist agents: Base Rate, News, Contrarian, Market Analyst, and Skeptic
  • A disagreement engine showing what pushed the forecast up or down
  • Scenarios you can toggle
  • A Time Machine that only uses information available on a selected past date
  • Sources tagged as Primary, Reliable secondary, Unverified, or Duplicate

There is also Your Lens, which personalizes the experience.

You choose the topics you care about and can give extra weight to one of the agents. That creates a second forecast called Your reading.

The evidence stays the same, but the weights change based on how you want to look at the market.

Your Lens is also connected to Backboard memory, so the system can remember your preferences during future live runs.

Contrary does four things differently:

  1. It shows an independent forecast next to the market.
    You can immediately see where Contrary disagrees with consensus.

  2. Four of the five agents do not see the market price.
    We found that models anchor heavily on the market once they see it.

  3. The final probability is calculated by us.
    Each agent returns a probability and confidence score. We combine those numbers ourselves instead of asking a model to invent the final figure.

  4. Personalization is based on memory, not chat history.
    Your Lens becomes reusable context for future forecasts.

How we built it

We built Contrary using Next.js 16, TypeScript, and Tailwind CSS in one application.

The five agents

Each agent is a separate Backboard call and returns its own probability, confidence score, and short evidence summary.

  • Base Rate Agent asks how often events like this actually happen. It focuses on historical frequency rather than recent headlines and does not see the market price.
  • News Agent looks at what has recently changed that could genuinely move the forecast. It tries to separate new signal from repeated reporting and does not see the market price.
  • Contrarian Agent stress-tests consensus by looking for assumptions that may not hold or cases where the crowd may be answering a looser question than the actual resolution criteria. It does not see the market price.
  • Market Analyst Agent is the only agent that sees the market price. It analyzes what the price implies, how it has moved, and whether that move appears deep or thin.
  • Skeptic Agent audits the evidence. Duplicate reporting, weak sources, unverified claims, and recency bias are down-weighted. It does not see the market price.

Backboard as the AI layer

Backboard is a big part of how Contrary works. We are not using it as a simple chatbot wrapper.

Our five specialist agents each make their own separate POST /threads/messages call. Four of those agents never receive the current market price.

Each agent returns:

  • a probability
  • a confidence score
  • reasoning from its own point of view

We then calculate the final Contrary probability using those five outputs and their weights.

The important part is that we do not ask a model for the final headline number. (more info below)

The final number comes from our own calculation. The aggregator model is only used to explain the result in a readable way.

Backboard Assistants + Memory

Backboard memory is also what powers Your Lens.

When a user saves a lens, we create or reuse a Backboard assistant and write the lens into its memory using memory: "Auto".

During future live runs, we reuse the same assistant_id with memory: "Readonly".

This means the system can remember who the forecast is being shown to without making the user explain their preferences every time.

For us, this was a much more interesting use of Backboard than just putting a chat interface in front of it.

Working with the Backboard API

Backboard has its own API structure, so we built one wrapper around it in:

src/lib/backboard.ts

That handles the thread calls, assistants, responses, and memory in one place.

Lens memory sync goes through /api/memory, which keeps it separate from the /lens page.

How we get the final number

Each agent has a role weight and its own confidence score. We combine them directly in code:

$$ weight_i = agent_weight_i \times confidence_i $$

The final Contrary probability is:

$$ P_{Contrary} = \frac{\sum (probability_i \times weight_i)} {\sum weight_i} $$

We then round the result to get the final percentage shown on screen. If the five agents disagree heavily with one another, the stated confidence of the combined forecast also drops. That value is computed rather than generated by an LLM.

The aggregator model only writes the explanation and uncertainties. It cannot change the headline percentage. That means the number shown on screen can be traced directly back to the five agent forecasts rather than being another LLM-generated guess.

Challenges we ran into

One of the biggest problems was anchoring. At first, every agent could see the market price.

We quickly noticed that their predictions started clustering around consensus. In one test, a question that should have been around 18 percentage points away from the market ended up only about 3 points away.

So we changed the setup. Four of the five agents are now completely blind to the market price. We ran into the same problem with the final aggregation step. If we asked a model to choose the final probability, it would often pull the result back toward consensus.

So we stopped letting the model choose the number. Now the headline probability is calculated directly from the five agent outputs, which also makes it much easier to check.

Another challenge was personalization without forcing users to make an account. The browser keeps the lens locally, while Backboard keeps the memory. If Backboard is unavailable, the lens still works on that device.

Accomplishments that we're proud of

One thing we are especially proud of is that the reasoning in Contrary actually connects back to the numbers.

The disagreement engine is not just there for display. The signal contributions add up to the gap between Contrary and the market.

Our Time Machine also avoids hindsight. If you go back to an earlier date, later sources disappear and the chart stops at that point.

We are also proud of how we used Backboard.

It powers five separate agents, persistent assistants, memory, and personalized live runs. It is part of the actual architecture instead of being added as a chat feature at the end.

And because the final probability comes from the five visible agent outputs, users can actually see where the number came from.

What we learned

The biggest thing we learned was that you cannot just tell a model not to anchor.

If you show it 72%, that number is already influencing the answer.

We also learned that memory only becomes useful when you keep the same identity. Reusing the same assistant_id gives the system continuity. Creating a new assistant every time basically gives it an empty memory.

More generally, we learned that forecasting feels much more useful when the product explains why it disagrees instead of just giving another confident-looking number.

What's next for Contrary

Next, we want to:

  • Connect live Polymarket prices
  • Turn on Backboard web_search for the News and Contrarian agents
  • Score forecasts after markets resolve using Brier scores and calibration
  • Build a proper track record for Contrary
  • Keep per-user forecasting history in memory
  • Add accounts so Your Lens can follow users across devices

The goal is simple:

Do not just show people what the crowd thinks. Show them where the crowd might be wrong.

Run it

npm install
cp .env.example .env.local
npm run dev

Built With

Share this project:

Updates

Submission history