Skip to content
All articles
  • AI
  • Architecture
  • Backend

Four content types, one answer: designing a multimodal disinformation detector

Design principles for a system that analyzes text, images, video and audio under a latency budget: contracts, parallelism, evidence and human review.

AL

By

3 min read

Read in Português
A presentation slide asking whether a video of two uniformed men is real or fake
Cover: Deepfake, Ministerie van Buitenlandse Zaken, CC BY-SA 2.0, via Wikimedia Commons

Why this is an architecture problem

When people hear "AI against disinformation" they think of models. In practice, most of the hard decisions in a system like GuaIA were about everything around the models: how formats are routed, how long each step may take, how results are combined and what a person sees at the end.

This article is a set of design principles, not a description of GuaIA's internals. They are the ones I reach for after working on the system as a co-architect, where the constraints were four content types (text, images, video and audio), a response in under four seconds, and Python and NestJS services that had to behave as one product.

1. Put every content type behind the same contract

Each modality needs its own analysis, but the rest of the system should not care. If the API layer has to know how a video is analyzed, every new capability becomes a change in five places.

A small, explicit contract keeps that boundary clean:

type Evidence = {
  signal: string // e.g. "manipulated-audio", "known-false-claim"
  confidence: number // 0..1
  detail?: string // human-readable explanation
}
 
type AnalysisResult = {
  modality: 'text' | 'image' | 'video' | 'audio'
  status: 'ok' | 'timeout' | 'error'
  evidence: Evidence[]
}
 
interface Analyzer {
  readonly modality: AnalysisResult['modality']
  analyze(content: Buffer, signal: AbortSignal): Promise<AnalysisResult>
}

This snippet is illustrative, not production code. The point is the shape: every analyzer returns evidence with a confidence, and failure is a value (timeout, error), not an exception that takes the whole request down.

2. Treat latency as a budget you spend

"Under four seconds" is only achievable if you decide in advance who gets how much of it. I think about it as a budget: a slice for ingestion, a slice for the slowest analyzer, a slice for combining results.

Two consequences follow. Independent analyzers should run in parallel, and each one needs its own deadline, so one slow path cannot consume the budget of the others:

const withDeadline = (analyzer: Analyzer, content: Buffer, ms: number) =>
  analyzer.analyze(content, AbortSignal.timeout(ms)).catch(
    (): AnalysisResult => ({ modality: analyzer.modality, status: 'timeout', evidence: [] })
  )
 
const results = await Promise.all(analyzers.map(a => withDeadline(a, content, 2500)))

A partial answer that arrives on time is usually more useful than a complete one that does not.

3. Return evidence, not verdicts

For a system that touches public debate, a bare "fake" or "real" label is the wrong output. What helps a reviewer is the evidence: which signals fired, how confident each one is and what is missing because an analyzer timed out.

That also keeps the system honest about uncertainty. A result with low-confidence evidence from two modalities should read differently from one with high-confidence evidence from a single modality, and your response format should make that visible.

4. Keep a human at the end of the loop

GuaIA is designed as a support tool: the final decision on any measure belongs to a person. That principle has engineering consequences. You need stable identifiers for every analysis, an audit trail of what the system said and when, and an interface that supports review rather than automating a conclusion.

5. Separate the data you store from the data you analyze

A detector ends up touching several databases: reference material, past analyses, operational metadata. I prefer to hide each of them behind the service that owns it, so the analysis path can be tested without the whole data estate and each store can change on its own schedule.

Takeaways

  • One contract for every modality keeps the system extensible.
  • Latency is a budget: parallelize, set deadlines per analyzer, accept partial results.
  • Return evidence and confidence, never a bare verdict.
  • Design the human review step first. The automation fits around it.

References

Share
AL

Written by Adriano Leão

I'm a software engineer in Goiânia, Brazil, building backend and AI systems. These notes come from the systems I've shipped: co-architecting GuaIA, scaling Como Votam and taking MusicPlayce Hub from zero to real users.

Work with me

The project behind this article

GuaIA

Keep reading

Mascot of the Brazilian electronic voting machine next to a ballot box and a projected slide
AIDisinformationArchitecture

GuaIA: how a multimodal AI took on electoral disinformation in Brazil

How GuaIA, the TRE-GO and UFG platform that won 1st place at the CNJ's FastLabs 2025, analyzes text, images, video and audio in under 4 seconds.

2 min read