Grounding AI agents in openOM
General-purpose AI extraction of an offering memorandum hallucinates - it will confidently invent an NOI, a cap rate, or a lease term that looks right and isn't. In CRE that is a liability, not a convenience. openOM removes the guess: for an openOM-enabled OM your agent reads a broker-asserted, hash-verified payload deterministically - no vision parse, no re-extraction, no hallucination.
The one thing to get right: it's an opinion, not a fact
An OM is an advertisement - the broker's opinion of value, agreed to by the seller
before publication. So openOM tells your agent who asserted a figure, that it is
unaltered, and as of when - never that it is true. Always carry the
noiType qualifier too (in-place vs pro-forma - a very different
claim). Ground the model on "the broker asserted in-place NOI = $115,625, unaltered, as of
2026-06-30", never "NOI is $115,625." Verified means provenance, not truth.
Underwriting still happens at the deal desk off the broker-of-record file.
Connect the deterministic MCP server
openOM ships a deterministic MCP
server, zero inference, no API key, no per-call cost. The free public grounding
endpoint (serverless Cloudflare Worker) exposes the two read-side tools - om_read
(read a verified payload from PDF bytes or an https URL) and om_validate. For the
full six-tool surface (om_inspect, om_extract_text,
om_extract_images, om_embed too), self-host:
// Public grounding endpoint (Streamable HTTP) - om_read + om_validate:
{ "mcpServers": { "openom": { "url": "https://mcp.openom.app/mcp" } } }
// Client without native Streamable-HTTP? bridge it over stdio:
{ "mcpServers": { "openom": { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.openom.app/mcp"] } } }
// Self-host the full six tools (stdio) - pip install openom-mcp:
{ "mcpServers": { "openom": { "command": "om-mcp" } } }
Rate limit: the public endpoint allows ~120 requests / 60s per client IP; over the
limit it returns HTTP 429 with a Retry-After header - pace a bulk
back-catalog read against it (or self-host for no limit).
Input shape: the public Worker's om_read takes flat
{ pdfBase64 } or { url } (exactly one); the self-hosted server takes a
pdf object - { path } (stdio) or { url }/{ blobId }
(hosted). Both return the same result shape.
Then the agent uses:
om_read- the broker-asserted payload +verification.hashValid(unaltered since embed). A hash-mismatched payload is returned as null - never trust it.om_validate- schema + internal-consistency (NOI÷price vs cap rate, rent-schedule math). Validity means well-formed and self-consistent, not that the opinion is right.om_inspect·om_extract_text·om_extract_images- classify, and pull text/images for the OMs that aren't openOM-enabled yet.
Which path: read vs. extract
A simple decision rule for your agent:
om_inspect(pdf)→ ifpayload.present, callom_read: deterministic, free, hash-verified. Prefer this.- else the OM is not openOM-enabled → run extraction (your own model) following the
extraction playbook, treat every field as an
unverified guess until a human asserts it, and (optionally)
om_embedit so the next read is deterministic.
Try it in one call
Point your agent at the downloadable sample OM and ask:
User: "What in-place NOI does this OM assert, and who asserted it, as of when?"
Agent → om_read({ "url": "https://openom.app/sample/openom-sample.pdf" })
Agent: "The broker (per assertedBy) asserts in-place NOI = $115,625, as of 2026-06-30 -
unaltered since embed (hashValid: true). This is the broker's opinion, not verified truth."
Tell your agent how to treat it (system-prompt snippet)
When an openOM payload is present, use it as the broker's ASSERTED OPINION, not fact.
- Attribute every figure: "<assertedBy> asserts <field> = <value>, as of <assertedDate>".
- If verification.hashValid is not true, do NOT use the payload - it may be altered.
- Never state an OM figure as verified truth; it is an advertisement / opinion of value.
- For OMs with no openOM payload, extraction is a guess - flag it as unverified.
Why this beats re-extraction
- No hallucination - the figure is transcribed once at the source and hash-locked.
- Defensible - provenance (who/unaltered/as-of-when) is exactly what credit committees and compliance need; "the AI guessed" is not.
- Free + instant - a deterministic read, not a per-document inference bill.
- Honest by design - the badge/labels never say "verified" to mean "true".
Cold-start reality: most OMs aren't openOM-enabled yet, so your agent still needs an extractor for those - treat that output as an unverified guess, and prefer openOM-enabled OMs as the trusted path. See the extraction playbook (how to turn a raw OM into a payload with your own model), the developer quick-start, and the verify tool.