ModLens Output Schema (v2)
August 14, 2026 · View on GitHub
English | 中文
The CLI prints one JSON object to stdout:
{
"image": "/abs/path/or/url",
"provider": "antigravity-cli",
"result": { "...": "see below" },
"meta": {
"generatedAt": "2026-08-01T12:00:00.000Z",
"model": "gemini-3.6-flash-low",
"conversationId": "string|null",
"durationSeconds": 25.4,
"usage": {},
"attempts": [{ "provider": "antigravity-cli", "ok": true, "durationSeconds": 25.4 }],
"warnings": []
}
}
meta.attempts lists every provider the failover chain tried this run, in order, with an error string on failures. meta.warnings carries routing notices: failovers, an ignored extraBody, and whose quota an auto-mode read spent.
result is enforced by JSON schema where the provider supports it (agent CLIs via --json-schema, API providers via response-schema fields or a filled-in template), and the CLI verifies the shape itself before returning, so a structurally broken result fails over instead of reaching you:
{
"summary": "string",
"ocr": {
"full_text": "string",
"lines": [
{ "text": "string", "language": "string (optional)" }
]
},
"layout": {
"regions": [
{
"type": "string (a short kind: title, paragraph, list, table, chart, form, code, image, icon, link, nav, ...)",
"reading_order": 1,
"text": "string"
}
]
},
"semantics": {
"scene": "string",
"intent": "string (optional)",
"entities": [
{ "name": "string", "type": "string", "evidence": "string (optional)" }
],
"relations": [
{ "subject": "string", "predicate": "string", "object": "string" }
]
},
"visual": {
"dominant_colors": ["string"],
"style": "string",
"notes": ["string"]
},
"uncertainty": ["string"]
}
Required fields: summary, ocr, layout, semantics, visual, uncertainty — every top-level field, visual included. (Earlier docs called visual optional; the enforced schema has always required it, so build to the schema.)
Optional fields: ocr.lines[].language, semantics.intent, semantics.entities[].evidence, semantics.relations, visual.dominant_colors, visual.style, visual.notes. Each is either absent or holds its declared type. Never null: a model with nothing to say there often writes one, and modlens drops the key before the result reaches you, so reading an optional field means checking whether it is there, not whether it is null.
layout.regions[].type is a free string, not a closed list. Region kinds are an open set: a fixed enum rejected link on any web screenshot and search on a portal, and a rejected result fails the whole read over a descriptive label. The field's schema description names the common vocabulary as guidance, which reaches every provider that enforces this schema server-side, so an unlisted kind costs nothing.
Changes from v1: pixel bbox coordinates and numeric confidence scores were removed. Vision models fabricate both, so v2 stops pretending to provide them.