Skip to main content
Glama

Check whether the citations in a draft actually verify

emem_guard_verdict
Read-onlyIdempotent

Check draft text against emem citation policy before sending or asserting it. Resolve every citation and return allow or deny with a machine-readable reason and fix.

Instructions

Run the emem-guard policy checks on text before you send it. The checks use this responder's corpus. The tool finds every emem: citation, resolves each one, and returns allow or deny with a reason that a machine can read: EMEM-GUARD DENY <CODE> token=<token|-> fix=<fix> leaf=<leaf|->. The codes are: PROV_SIG (the signature did not verify). PROV_BYTES (the citation resolved to different content). PROV_DRIFT (the reading moved past its band threshold). PROV_VALUE (a stated value does not agree with the cited fact). CLAIM_UNGROUNDED (a measurable claim has no citation; turn it on with claim_gating). fix tells you what to do: refresh_token, remove_reference, contact_admin, cite_observation, correct_value. Only a self-hosted guard returns GEO_ZONE and redact_and_retry. This tool is ADVISORY: it blocks nothing. A citation that this responder does not hold is never a denial, because it can be a citation from another responder. Memory algebra: the verify operation (https://emem.dev/docs/model.html).

When to use: Call it on your draft before you assert something, or on a tool result before you reason on it. Then you can fix a citation that does not resolve. With claim_gating: true, it also names measurable claims with no citation, and the band that answers each. For a payload from another framework (CloudEvent, OPA input, OpenAI moderations body, a tool call from another server), send it unchanged and name its shape. The default reader reads only texts, and a check that read nothing answers allow. To ENFORCE the policy, use emem_guard_selfhost. It returns the procedure for your own node.

Example arguments: {"texts":["Lusail ground sits at 2.6 m per emem:fact:defi.zb521.jawI.gOze:f3yr3urkrfwamlemwadulgth2qpw645vi6l6fhtuu4dy5o7onahq"]}

Input Schema

NameRequiredDescriptionDefault
agentNoOptional free-text label for who is asking. Advisory only, never a trust boundary.
shapeNoWhich envelope YOUR payload is in, so you never have to reshape it to ask the question: send the body your own framework produced and name its shape. native reads `texts`; `mcp` reads a JSON-RPC tools/call or tool result; `openai` reads a moderations (`input`) or chat-completions body; `cloudevent` reads a CloudEvents 1.0 structured event; `policy` reads {input}. It matters: a CloudEvent whose citation sits at data.text is invisible to the native reader, and a check that read nothing answers `allow`, so confirm `citations_found` matches what you sent. Unrecognised values fall back to native rather than erroring. This selects how the body is READ only — the verdict always comes back in this tool's declared output shape, because a tool that declares an outputSchema owes conforming structuredContent. To get the ANSWER translated into the same envelope too (an OPA `result:{allow,deny}`, an MCP CallToolResult to substitute on a deny), call POST /v1/guard/verdict?shape=… directly.native
textsNoFree text to check, and the only input this tool needs. Send just the pieces the question is about: a draft answer, a tool result, one turn. Do not send surrounding conversation, because nothing here reads it and a checker should ask for the smallest input that answers the question.
claim_gatingNoAlso flag measurable physical-world claims that carry NO citation (deny code CLAIM_UNGROUNDED, fix cite_observation). Off by default: it reports on the absence of a citation rather than on a failed check. The verdict names the sentence, the magnitude, and the emem band that would answer it.

Output Schema

NameRequiredDescriptionDefault
fixNoThe actionable half: what to change and retry.
codeNoPresent only on a deny.
claimNoOn CLAIM_UNGROUNDED: the sentence, magnitude, quantity, anchor, and source_band. source_band is a recallable band key, or null when this responder observes no band in that quantity.
actionYesNOT a clearance. `allow` means no rule fired, which on a transcript that cited nothing is silence rather than approval. Branch on citations_found and receipt.fact_cids.
checkedYesHow many were actually resolved, bounded by the verdict budget.
receiptYesed25519 receipt. `fact_cids` lists what actually resolved and is the field that separates a real citation from an invented one.
advisoryYesTrue on the hosted route, where nothing is blocked. Run your own node to enforce.
citationsNoEach citation and what it came to here: verified, signature_failed, byte_mismatch, not_held_here (minted elsewhere or nonexistent: resolve it where it was minted before relying on it), or drifted.
citations_foundYesHow many emem: tokens were found in the text. Compare with receipt.fact_cids: a well-formed token that resolved to nothing counts here and not there.
citations_verified_hereNoHow many of the citations this responder holds and verified.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed5 schema fields changedv2.4.4
    • removedInput schema / properties / messages
      Removed value: -{
      -  "description": "A chat-completions-shaped transcript, read for its text. Accepted so the same body works against a self-hosted emem-guard node and against any OpenAI-shaped client. Each item is {role, content} where content is a string or an array of blocks.",
      -  "items": {
      -    "properties": {
      -      "content": {
      -        "description": "A string, or an array of {type,text} blocks."
      -      },
      -      "role": {
      -        "type": "string"
      -      }
      -    },
      -    "type": "object"
      -  },
      -  "type": "array"
      -}
    • changedInput schema / properties / shape / description
      Previous value: -"Which envelope YOUR payload is in, so you never have to reshape it to ask the question: send the body your own framework produced and name its shape. native reads `texts`/`messages`; `mcp` reads a JSON-RPC tools/call or tool result; `openai` reads a moderations (`input`) or chat-completions body; `cloudevent` reads a CloudEvents 1.0 structured event; `policy` reads {input}. It matters: a CloudEvent whose citation sits at data.text is invisible to the native reader, and a check that read nothing answers `allow`, so confirm `citations_found` matches what you sent. Unrecognised values fall back to native rather than erroring. This selects how the body is READ only — the verdict always comes back in this tool's declared output shape, because a tool that declares an outputSchema owes conforming structuredContent. To get the ANSWER translated into the same envelope too (an OPA `result:{allow,deny}`, an MCP CallToolResult to substitute on a deny), call POST /v1/guard/verdict?shape=… directly."New value: +"Which envelope YOUR payload is in, so you never have to reshape it to ask the question: send the body your own framework produced and name its shape. native reads `texts`; `mcp` reads a JSON-RPC tools/call or tool result; `openai` reads a moderations (`input`) or chat-completions body; `cloudevent` reads a CloudEvents 1.0 structured event; `policy` reads {input}. It matters: a CloudEvent whose citation sits at data.text is invisible to the native reader, and a check that read nothing answers `allow`, so confirm `citations_found` matches what you sent. Unrecognised values fall back to native rather than erroring. This selects how the body is READ only — the verdict always comes back in this tool's declared output shape, because a tool that declares an outputSchema owes conforming structuredContent. To get the ANSWER translated into the same envelope too (an OPA `result:{allow,deny}`, an MCP CallToolResult to substitute on a deny), call POST /v1/guard/verdict?shape=… directly."
    • changedInput schema / properties / texts / description
      Previous value: -"Free text to check. Any number of pieces, in any order: a draft answer, a tool result, a whole turn."New value: +"Free text to check, and the only input this tool needs. Send just the pieces the question is about: a draft answer, a tool result, one turn. Do not send surrounding conversation, because nothing here reads it and a checker should ask for the smallest input that answers the question."
    • addedOutput schema / properties / citations
      Added value: +{
      +  "description": "Each citation and what it came to here: verified, signature_failed, byte_mismatch, not_held_here (minted elsewhere or nonexistent: resolve it where it was minted before relying on it), or drifted.",
      +  "items": {
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / citations_verified_here
      Added value: +{
      +  "description": "How many of the citations this responder holds and verified.",
      +  "type": "integer"
      +}
  2. Addedv1.3.9
  3. Removedv1.3.8
  4. Changed1 schema field changedv1.3.4
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "properties": {
      +    "action": {
      +      "description": "NOT a clearance. `allow` means no rule fired, which on a transcript that cited nothing is silence rather than approval. Branch on citations_found and receipt.fact_cids.",
      +      "enum": [
      +        "allow",
      +        "deny"
      +      ],
      +      "type": "string"
      +    },
      +    "advisory": {
      +      "description": "True on the hosted route, where nothing is blocked. Run your own node to enforce.",
      +      "type": "boolean"
      +    },
      +    "checked": {
      +      "description": "How many were actually resolved, bounded by the verdict budget.",
      +      "type": "integer"
      +    },
      +    "citations_found": {
      +      "description": "How many emem: tokens were found in the text. Compare with receipt.fact_cids: a well-formed token that resolved to nothing counts here and not there.",
      +      "type": "integer"
      +    },
      +    "claim": {
      +      "description": "On CLAIM_UNGROUNDED: the sentence, magnitude, quantity, anchor, and source_band. source_band is a recallable band key, or null when this responder observes no band in that quantity.",
      +      "type": "object"
      +    },
      +    "code": {
      +      "description": "Present only on a deny.",
      +      "enum": [
      +        "PROV_SIG",
      +        "PROV_BYTES",
      +        "PROV_DRIFT",
      +        "PROV_VALUE",
      +        "GEO_ZONE",
      +        "CLAIM_UNGROUNDED",
      +        "POLICY_MODULE"
      +      ],
      +      "type": "string"
      +    },
      +    "fix": {
      +      "description": "The actionable half: what to change and retry.",
      +      "enum": [
      +        "refresh_token",
      +        "remove_reference",
      +        "contact_admin",
      +        "redact_and_retry",
      +        "cite_observation",
      +        "correct_value"
      +      ],
      +      "type": "string"
      +    },
      +    "receipt": {
      +      "description": "ed25519 receipt. `fact_cids` lists what actually resolved and is the field that separates a real citation from an invented one.",
      +      "type": "object"
      +    }
      +  },
      +  "required": [
      +    "action",
      +    "advisory",
      +    "checked",
      +    "citations_found",
      +    "receipt"
      +  ],
      +  "type": "object"
      +}
  5. Addedv1.3.3

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, but the description adds substantial behavioral context: this is ADVISORY and blocks nothing, a citation the responder does not hold is never a denial, unrecognised shape values fall back to native rather than erroring, and GEO_ZONE/redact_and_retry appear only on a self-hosted guard. The enumerated deny codes and fix tokens go well beyond what any annotation conveys.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with what the tool does before the code glossary and usage rules, and most sentences carry operational payload (codes, fix tokens, the empty-read-answers-allow trap). It is nonetheless long, and a few points (the shape fallback, the read-only-texts caveat) echo the schema descriptions rather than adding new information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex, multi-mode policy checker with four optional parameters, an output schema, and full annotation coverage, the description is complete: it covers input shape selection, advisory semantics, the full deny-code vocabulary, and the escape hatch to the enforcing tool. An agent has everything needed to invoke it correctly and interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description earns above that by supplying worked example arguments, explaining that claim_gating names the sentence, magnitude, and band, and stressing that texts should carry only the smallest input the question needs. It adds real semantic color rather than repeating the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource chain — it finds every emem: citation, resolves each one, and returns allow/deny with a machine-readable reason — which is far more than a restatement of the name. It clearly differentiates itself from the enforcing counterpart (emem_guard_selfhost) and from raw API use, but it never distinguishes itself from the verification-flavored siblings actually in the list (emem_echo_verify, emem_verify_receipt), leaving that ambiguity open.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is an explicit 'When to use' clause (on a draft before you assert something, or on a tool result before you reason on it) plus a clear alternative and its selection condition ('To ENFORCE the policy, use emem_guard_selfhost'). It even supplies the negative guidance an agent needs — send an external payload unchanged and name its shape, and note that a check which read nothing answers allow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.