12 min

Agent-First Entity Database: Schema, MCP Contract, and Benchmarks

AI Agents MCP DuckDB Data Architecture

EntityScope is a working, self-hosted entity knowledge base whose primary client is an agent. It uses DuckDB for storage, exposes four bounded MCP tools, tracks provenance at field level, and has no application UI.

The interesting decision was not “remove the dashboard.” It was to replace a forgiving human interface with a stricter machine contract. An agent needs explicit identifiers, bounded queries, freshness signals, provenance, and failure states. A blank cell and a stale fact cannot look the same.

What exists today

I inspected the repository and measured the current local database on 28 July 2026. These are implementation facts, not roadmap claims:

ArtifactObserved stateWhy it matters
Entity spine1,010 rowsOne stable record per resolved legal entity
Field provenance8,018 rowsSource, confidence, URL, and verification time can vary by field
Prospect profiles479 rowsCurated and imported commercial context remains separate from the legal spine
Berlin source rows1,000 rowsRaw source data is retained instead of being collapsed too early
MCP surface4 read toolsQuery, entity lookup, source inventory, and health
Automated suite130 pass; 1 stale fixture failsThe failure expects 100 prospect files although the corpus now has 479

That failed fixture is worth reporting. A test count is not evidence if the assertion has drifted away from production data. The correct repair is to test an invariant—such as “all valid files were ingested”—instead of hard-coding a historical corpus size.

The schema separates identity, claims, and evidence

entities
  hrb_id              stable legal identifier
  canonical_name      resolved legal name
  address_city        normalized location
  industry_label      normalized classification
  employee_count      latest known total
  employees_on_site   latest known local count
  revenue_estimate    latest estimate

entity_sources
  hrb_id + field_name + source_name
  confidence
  source_url
  last_verified

prospects
  slug                working identifier
  hrb_id              nullable link to legal entity
  funding_stage
  total_funding
  team_size
  tags
  enrichment_status

The key design choice is the composite provenance record. “Company X has 50 employees” is not stored as timeless truth. It is a claim about one field, from one source, observed at one time, with a confidence level. Conflicting claims can coexist until a resolution policy chooses what to present.

Why agents should not generate SQL

The query path translates intent into an allow-listed filter object. The database layer then builds parameterized predicates. The agent never receives database credentials and never emits executable SQL.

{
  "filters": {
    "city": "München",
    "employees_on_site_max": 10
  },
  "confidence": 0.8,
  "explanation": "location=München; max 10 on-site employees"
}

Common patterns use deterministic parsing first. A model is an optional fallback for unsupported language. This ordering reduces latency and cost, but more importantly it makes common queries testable. If translation confidence is zero, the system should return “unsupported,” not silently broaden the search.

The four-tool MCP contract

ToolResponsibilityRequired guardrail
entityscope_queryIntent to bounded entity listAllow-listed filters and maximum result limit
entityscope_get_entityOne profile by HRB ID, registration number, name, or slugReturn ambiguity rather than guessing between matches
entityscope_list_sourcesSource inventory and freshnessExpose missing verification timestamps
entityscope_healthCounts, enrichment progress, and stalenessHealth must describe data quality, not only process uptime

The current service is deliberately read-only at the agent boundary. Ingestion and enrichment happen through separate controlled jobs. That separation limits blast radius and makes the read contract easier to trust.

Measured query performance

I opened the 7 MB DuckDB file read-only, warmed the structured filter path 20 times, then ran the same Munich and small-team query 500 times through the production query function.

RunsRows returnedMedianp95Maximum
50011.972 ms2.329 ms2.709 ms

This is a local warm-cache measurement, not an end-to-end SLO. It excludes natural-language translation, MCP serialization, process startup, network transport, and model calls. The downloadable protocol records the corpus, filter, warm-up, sample count, and percentile calculation so the result can be rerun instead of repeated as folklore.

Freshness is part of the answer

EntityScope computes staleness from field-level verification timestamps. The current health policy warns when more than 30% of provenance rows are missing a recent verification. That is a useful start, but a production policy should vary by field:

  • legal identity may tolerate a longer refresh interval;
  • headcount and funding signals decay faster;
  • contact details should expire quickly;
  • a high-impact decision may require live reconciliation regardless of age.

An agent response should distinguish verified, stale, conflicting, and unknown. Returning a value without its evidence state invites confident misuse.

Entity resolution is the real hard problem

Storage is straightforward. Joining “Acme,” “Acme GmbH,” a website domain, and a registry number without merging two different companies is not. The resolution pipeline should be conservative:

  1. Match stable registry identifiers exactly when available.
  2. Normalize legal suffixes, Unicode, punctuation, and domains.
  3. Generate candidates using name and location.
  4. Score candidates using independent attributes.
  5. Auto-merge only above a calibrated threshold.
  6. Persist rejected and ambiguous candidates for review.

False merges are usually more expensive than duplicates because they contaminate every downstream fact. “No match” is a valid result.

When zero UI works—and when it does not

Zero UI works when the users are automated systems, the tool surface is small, the schema is stable, and operational state is observable elsewhere. It is a poor choice when humans must resolve conflicts, correct records, explore unfamiliar data, or approve consequential changes.

The next interface EntityScope needs is therefore not a general dashboard. It is a focused review surface for ambiguous matches, conflicting claims, and stale critical fields. Agent-first does not mean human-absent; it means human attention is reserved for decisions that automation cannot justify.

Reusable artifacts

Download the MCP contract