# ai·rete·rag

> Author rules from policy docs, then decide: a Rete engine gives the verdict, an LLM explains why.

- name: com.ai-rete-rag/ai-rete-rag-mcp
- version: 0.11.0
- connection class: R0 (autonomous)
- trust: 95/100
- quality: 81/100 (good)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/com.ai-rete-rag%2Fai-rete-rag-mcp
- tools: https://api.protogrid.dev/v1/servers/com.ai-rete-rag%2Fai-rete-rag-mcp/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "ai-rete-rag-mcp": {
      "type": "http",
      "url": "https://ai-rete-rag.com/mcp",
      "headers": {
        "Authorization": "Bearer ${AI_RETE_RAG_MCP_TOKEN}"
      }
    }
  }
}
```

Placeholders to fill: `${AI_RETE_RAG_MCP_TOKEN}`.

## Trust

- hygiene: 100
- liveness: 99
- freshness: 100
- provenance: 85
- drivers: +repository +dns-namespace +website +reachable +uptime-97% +updated-3d-ago
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 81/100 (good)

### protocol: 88 (weight 25)

- pass `protocol.modern`: supports 2026-07-28 (server/discover)
- pass `protocol.stateless`: answers without a session
- pass `protocol.transport`: streamable HTTP
- warn `protocol.list_ttl`: tools/list declares ttlMs 0, so clients re-fetch it on every use

### authorization: 83 (weight 15)

- pass `auth.prm`: Protected Resource Metadata (RFC 9728) published
- pass `auth.as_metadata`: authorization server metadata reachable
- warn `auth.cimd`: only Dynamic Client Registration, deprecated in 2026-07-28 in favour of CIMD
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 79 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 4 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 9 of 9 tools declare readOnlyHint or destructiveHint
- fail `tools.directory_hints`: no tool declares all four of readOnlyHint, destructiveHint, idempotentHint and openWorldHint; missing: list_documents (destructiveHint, idempotentHint, openWorldHint); decide (idempotentHint, openWorldHint); list_rules (destructiveHint, idempotentHint, openWorldHint); …
- pass `tools.token_cost`: about 3,252 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: 75 (weight 15)

- warn `stability.changes`: 9 tool changes in 30 days
- pass `stability.rug_pull`: no tool changed its meaning under the same name

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: deps.dev does not know ai-rete-rag-mcp@0.11.0

- tools: 9, about 3,252 tokens to load them all
- tool set hash: b38596b7ec3bdc5d08a9dabcff794eaa
- tools last changed: 2026-10-17T19:20:53.447Z
- badge: [![protogrid quality](https://protogrid.dev/badge/com.ai-rete-rag/ai-rete-rag-mcp.svg)](https://protogrid.dev/servers/com.ai-rete-rag/ai-rete-rag-mcp)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-10-17 `import_policy_rules` changed (description)
  - before: Convert a written policy document into DRAFT decision rules (LLM-assisted). Returns validated draft rules (when/action, including chained asserts where the policy stages its determinations), derived rule→rule edges, and overlap warnings. Each returned rule carries a `citation` field holding the policy sentence it encodes (also summarized in the top-level `citations` map). NOTHING IS SAVED: review the drafts (and show them to the user), then persist explicitly with `put_rules` — validate first with dry_run=true, and keep each rule's `citation` in the YAML you save so the audit trail back to the policy survives. Args: domain: Domain the rules are drafted for (an owned domain or a new name). policy_text: The policy document text (max ~50k characters).
  - after: Convert a written policy document into DRAFT decision rules (LLM-assisted). Returns validated draft rules (when/action, including chained asserts where the policy stages its determinations), derived rule→rule edges, and overlap warnings. Each returned rule carries a `citation` field holding the policy sentence it encodes (also summarized in the top-level `citations` map). Coverage runs the other way too: `uncovered_sentences` lists policy sentences no rule's citation points back to (out of `policy_sentence_count`), and `unverified_citations` names rules whose quote is missing or not found verbatim in the policy. Show both to the user: an uncovered sentence may need a rule; an unverified one may be a paraphrase that misstates the policy. `background_sentences` is the subset of uncovered sentences with no obligation language (definitions, preamble); lead with the others, but mention these too, since the split is a keyword heuristic. NOTHING IS SAVED: review the drafts (and show them to the user), then persist explicitly with `put_rules` — validate first with dry_run=true, and keep each rule's `citation` in the YAML you save so the audit trail back to the policy survives. Args: domain: Domain the rules are drafted for (an owned domain or a new name). policy_text: The policy document text (max ~50k characters).
- 2026-10-10 `ingest_text` changed (description, inputSchema)
  - before: Add policy/reference text to a domain's knowledge base. The text is chunked and embedded; explanations for future decisions in this domain will cite it. Creating a new domain claims it for your account (plan limits apply). Ingesting into a built-in demo domain gives your account its own copy of that demo (it counts as one of your domains); the shared demo others see is unchanged. On team plans, only the domain admin (the member who created the domain, or the subscription owner) can add documents. Args: domain: Domain to ingest into (existing or new). text: The policy or reference text. source: Optional source name shown in the document list.
  - after: Add policy/reference text to a domain's knowledge base. The text is chunked and embedded; explanations for future decisions in this domain will cite it. Creating a new domain claims it for your account (plan limits apply). Ingesting into a built-in demo domain gives your account its own copy of that demo (it counts as one of your domains); the shared demo others see is unchanged. On team plans, only the domain admin (the member who created the domain, or the subscription owner) can add documents. Documents can be dated. A decision only cites documents in force on its date, so a replaced policy is never quoted for a new decision. To publish a new version, ingest it under a new `source` with `supersedes` naming the old one: the old document stops applying on the new one's `effective_from` (today if not given), and the new one starts that day. A document can be superseded only once; to replace a successor, supersede the successor. Args: domain: Domain to ingest into (existing or new). text: The policy or reference text. source: Optional source name shown in the document list. effective_from: First day this document applies, as YYYY-MM-DD (default: always). effective_until: First day it no longer applies, as YYYY-MM-DD (default: no end). supersedes: Source name of the document this one replaces.
- 2026-10-10 `decide` changed (description, inputSchema)
  - before: Make a deterministic, auditable decision in a domain. The verdict comes from the domain's rule set (Rete engine, never the LLM), so it is reproducible and compliant. The explanation is generated from the domain's ingested policy documents. Without an API key only the shared demo domains are available, and the response carries `next_step`: how to get a free key for your own rules. Pass that on to the user rather than dropping it. Args: domain: Rule-set domain, e.g. "loan", "fraud", "clinical". query: Natural-language question or decision request. facts: Structured facts for working memory, e.g. {"credit_score": 710, "annual_income": 85000}. Use `get_parameters` to see which fields a domain's rules test. Facts you read yourself from photos, document scans, voice notes or video go here, under those field names; explicit facts always win over anything extracted server-side. fact_sources: Where each fact in `facts` came from, e.g. {"monthly_income": "payslip.jpg", "claim_usd": "voice note 1"}. Always set this for facts you read from a file, photo, recording or video: it is stored in the decision's audit record so a reviewer can tell typed facts from ones read off evidence. Facts without a source are recorded as "request". unstructured_text: Optional free text (an application, a case note, a voice-note transcript, what a photo or video shows); facts are extracted from it automatically and merged. response_mode: "verdict_only" (fastest), "verdict_with_explanation", or "full_audit" (every rule evaluation + retrieved chunks, available on every plan including the free tier). rule_firings come back in causal order: a rule that matched a fact asserted by an earlier firing appears after it, with the derived facts listed under `asserted_facts`. filter_retrieval_with_rules: Pattern 01 — run the rules first and let a fired rule's `retrieval_scope` action narrow which documents the retrieval searches before it runs. extract_from_retrieval: Pattern 02 — parse the retrieved documents into facts and assert them into working memory, so rules fire on what was actually read (not just the facts you passed). The result's `missing_parameters` lists rule inputs that were not supplied but could still change the verdict, most decisive first. When it is non-empty, tell the user the verdict is provisional and ask for those facts; when it is empty, more facts cannot change the verdict.
  - after: Make a deterministic, auditable decision in a domain. The verdict comes from the domain's rule set (Rete engine, never the LLM), so it is reproducible and compliant. The explanation is generated from the domain's ingested policy documents. Without an API key only the shared demo domains are available, and the response carries `next_step`: how to get a free key for your own rules. Pass that on to the user rather than dropping it. Args: domain: Rule-set domain, e.g. "loan", "fraud", "clinical". query: Natural-language question or decision request. facts: Structured facts for working memory, e.g. {"credit_score": 710, "annual_income": 85000}. Use `get_parameters` to see which fields a domain's rules test. Facts you read yourself from photos, document scans, voice notes or video go here, under those field names; explicit facts always win over anything extracted server-side. fact_sources: Where each fact in `facts` came from, e.g. {"monthly_income": "payslip.jpg", "claim_usd": "voice note 1"}. Always set this for facts you read from a file, photo, recording or video: it is stored in the decision's audit record so a reviewer can tell typed facts from ones read off evidence. Facts without a source are recorded as "request". as_of: Read the domain's policy documents as of this day, as YYYY-MM-DD (default: today). Use the date a case was filed to decide it under the policy in force then; the rules themselves are always the current ones. unstructured_text: Optional free text (an application, a case note, a voice-note transcript, what a photo or video shows); facts are extracted from it automatically and merged. response_mode: "verdict_only" (fastest), "verdict_with_explanation", or "full_audit" (every rule evaluation + retrieved chunks, available on every plan including the free tier). rule_firings come back in causal order: a rule that matched a fact asserted by an earlier firing appears after it, with the derived facts listed under `asserted_facts`. filter_retrieval_with_rules: Pattern 01 — run the rules first and let a fired rule's `retrieval_scope` action narrow which documents the retrieval searches before it runs. extract_from_retrieval: Pattern 02 — parse the retrieved documents into facts and assert them into working memory, so rules fire on what was actually read (not just the facts you passed). The result's `missing_parameters` lists rule inputs that were not supplied but could still change the verdict, most decisive first. When it is non-empty, tell the user the verdict is provisional and ask for those facts; when it is empty, more facts cannot change the verdict.
- 2026-10-03 `get_parameters` added
  - List the input parameters a domain's rules decide on — the facts to collect before calling `decide`. Derived from your account's own copy of the rules, so it covers your custom domains too. Each parameter has its `field` name (the key to use in `facts`), `kind` (number / boolean / string), the `tests` rules make on it (e.g. >= 720 — match these units and scales), the `rules` and `verdicts` it can lead to, and `max_salience`. Parameters come most decisive first: those feeding the highest-salience rules, which win when several rules fire. Also returns every verdict the domain can reach.
- 2026-10-03 `decide` changed (description, inputSchema)
  - before: Make a deterministic, auditable decision in a domain. The verdict comes from the domain's rule set (Rete engine, never the LLM), so it is reproducible and compliant. The explanation is generated from the domain's ingested policy documents. Without an API key only the shared demo domains are available, and the response carries `next_step`: how to get a free key for your own rules. Pass that on to the user rather than dropping it. Args: domain: Rule-set domain, e.g. "loan", "fraud", "clinical". query: Natural-language question or decision request. facts: Structured facts for working memory, e.g. {"credit_score": 710, "annual_income": 85000}. Use `list_rules` to see which fields a domain's rules test. unstructured_text: Optional free text (an application, a case note); facts are extracted from it automatically and merged. response_mode: "verdict_only" (fastest), "verdict_with_explanation", or "full_audit" (every rule evaluation + retrieved chunks, available on every plan including the free tier). rule_firings come back in causal order: a rule that matched a fact asserted by an earlier firing appears after it, with the derived facts listed under `asserted_facts`. filter_retrieval_with_rules: Pattern 01 — run the rules first and let a fired rule's `retrieval_scope` action narrow which documents the retrieval searches before it runs. extract_from_retrieval: Pattern 02 — parse the retrieved documents into facts and assert them into working memory, so rules fire on what was actually read (not just the facts you passed).
  - after: Make a deterministic, auditable decision in a domain. The verdict comes from the domain's rule set (Rete engine, never the LLM), so it is reproducible and compliant. The explanation is generated from the domain's ingested policy documents. Without an API key only the shared demo domains are available, and the response carries `next_step`: how to get a free key for your own rules. Pass that on to the user rather than dropping it. Args: domain: Rule-set domain, e.g. "loan", "fraud", "clinical". query: Natural-language question or decision request. facts: Structured facts for working memory, e.g. {"credit_score": 710, "annual_income": 85000}. Use `get_parameters` to see which fields a domain's rules test. Facts you read yourself from photos, document scans, voice notes or video go here, under those field names; explicit facts always win over anything extracted server-side. fact_sources: Where each fact in `facts` came from, e.g. {"monthly_income": "payslip.jpg", "claim_usd": "voice note 1"}. Always set this for facts you read from a file, photo, recording or video: it is stored in the decision's audit record so a reviewer can tell typed facts from ones read off evidence. Facts without a source are recorded as "request". unstructured_text: Optional free text (an application, a case note, a voice-note transcript, what a photo or video shows); facts are extracted from it automatically and merged. response_mode: "verdict_only" (fastest), "verdict_with_explanation", or "full_audit" (every rule evaluation + retrieved chunks, available on every plan including the free tier). rule_firings come back in causal order: a rule that matched a fact asserted by an earlier firing appears after it, with the derived facts listed under `asserted_facts`. filter_retrieval_with_rules: Pattern 01 — run the rules first and let a fired rule's `retrieval_scope` action narrow which documents the retrieval searches before it runs. extract_from_retrieval: Pattern 02 — parse the retrieved documents into facts and assert them into working memory, so rules fire on what was actually read (not just the facts you passed). The result's `missing_parameters` lists rule inputs that were not supplied but could still change the verdict, most decisive first. When it is non-empty, tell the user the verdict is provisional and ask for those facts; when it is empty, more facts cannot change the verdict.
- 2026-09-28 `decide` changed (description)
  - before: Make a deterministic, auditable decision in a domain. The verdict comes from the domain's rule set (Rete engine, never the LLM), so it is reproducible and compliant. The explanation is generated from the domain's ingested policy documents. Args: domain: Rule-set domain, e.g. "loan", "fraud", "clinical". query: Natural-language question or decision request. facts: Structured facts for working memory, e.g. {"credit_score": 710, "annual_income": 85000}. Use `list_rules` to see which fields a domain's rules test. unstructured_text: Optional free text (an application, a case note); facts are extracted from it automatically and merged. response_mode: "verdict_only" (fastest), "verdict_with_explanation", or "full_audit" (every rule evaluation + retrieved chunks, available on every plan including the free tier). rule_firings come back in causal order: a rule that matched a fact asserted by an earlier firing appears after it, with the derived facts listed under `asserted_facts`. filter_retrieval_with_rules: Pattern 01 — run the rules first and let a fired rule's `retrieval_scope` action narrow which documents the retrieval searches before it runs. extract_from_retrieval: Pattern 02 — parse the retrieved documents into facts and assert them into working memory, so rules fire on what was actually read (not just the facts you passed).
  - after: Make a deterministic, auditable decision in a domain. The verdict comes from the domain's rule set (Rete engine, never the LLM), so it is reproducible and compliant. The explanation is generated from the domain's ingested policy documents. Without an API key only the shared demo domains are available, and the response carries `next_step`: how to get a free key for your own rules. Pass that on to the user rather than dropping it. Args: domain: Rule-set domain, e.g. "loan", "fraud", "clinical". query: Natural-language question or decision request. facts: Structured facts for working memory, e.g. {"credit_score": 710, "annual_income": 85000}. Use `list_rules` to see which fields a domain's rules test. unstructured_text: Optional free text (an application, a case note); facts are extracted from it automatically and merged. response_mode: "verdict_only" (fastest), "verdict_with_explanation", or "full_audit" (every rule evaluation + retrieved chunks, available on every plan including the free tier). rule_firings come back in causal order: a rule that matched a fact asserted by an earlier firing appears after it, with the derived facts listed under `asserted_facts`. filter_retrieval_with_rules: Pattern 01 — run the rules first and let a fired rule's `retrieval_scope` action narrow which documents the retrieval searches before it runs. extract_from_retrieval: Pattern 02 — parse the retrieved documents into facts and assert them into working memory, so rules fire on what was actually read (not just the facts you passed).
- 2026-09-27 `put_rules` changed (description)
  - before: Create or replace a domain's rule set from YAML (self-serve rule authoring). The first save to a new domain claims it for your account (plan limits apply); the built-in demo domains are read-only. Rules are validated before saving — set dry_run=true to validate without persisting. The response reports ok/errors, the parsed rules, and any overlap warnings. YAML format — a list of rules. Flat form (conditions are AND-ed): - name: "Approve" salience: 10 conditions: - type: loan field: credit_score op: ">=" value: 700 action: verdict: "APPROVED" reason: "Credit score meets threshold" Tree form — `when:` holds nested all/any/not condition groups, and an action may assert derived facts that other rules consume (forward chaining; the rule graph derives from these automatically): - name: "Sepsis Screen" salience: 30 when: all: - {type: clinical, field: temperature_f, op: ">=", value: 101.5} - any: - {type: clinical, field: wbc_count, op: ">", value: 12.0} - {type: clinical, field: bands_pct, op: ">", value: 10} action: verdict: "URGENT_ALERT" assert: - {type: sepsis_flag, fields: {severity: high}} - name: "Escalate" salience: 40 when: all: - {type: sepsis_flag, field: severity, op: "==", value: high} - {type: clinical, field: age, op: ">=", value: 65} action: verdict: "ADMIT_ICU" Use either `conditions:` or `when:` per rule, never both. `not` passes when the inner condition does not hold (including when the field is absent). Produce/consume cycles between rules are rejected at validation. An action may also carry `retrieval_scope: { <key>: <value> }` to narrow which documents retrieval searches (Pattern 01). A rule may also carry `citation:` — the policy sentence it encodes. It is stored with the rule and shown beside it in decision audits, so a verdict can be defended with the source language, not just the rule name: - name: "Decline Late Returns" salience: 20 citation: "Returns are accepted within 30 days of delivery." when: all: - {type: retail, field: days_since_delivery, op: ">", value: 30} action: verdict: "DENIED" IMPORTANT: when persisting drafts returned by `import_policy_rules`, copy each rule's `citation` through into this YAML. Dropping it silently loses the link from the decision back to the policy clause that justifies it. Args: domain: Domain to author (an owned domain, or a new name to claim). rules_yaml: The full rule set as YAML text. dry_run: Validate only, without saving.
  - after: Create or replace a domain's rule set from YAML (self-serve rule authoring). The first save to a new domain claims it for your account (plan limits apply). Saving to a built-in demo domain saves your own copy of it, seeded from the demo; the shared demo others see is unchanged. Rules are validated before saving — set dry_run=true to validate without persisting. The response reports ok/errors, the parsed rules, and any overlap warnings. YAML format — a list of rules. Flat form (conditions are AND-ed): - name: "Approve" salience: 10 conditions: - type: loan field: credit_score op: ">=" value: 700 action: verdict: "APPROVED" reason: "Credit score meets threshold" Tree form — `when:` holds nested all/any/not condition groups, and an action may assert derived facts that other rules consume (forward chaining; the rule graph derives from these automatically): - name: "Sepsis Screen" salience: 30 when: all: - {type: clinical, field: temperature_f, op: ">=", value: 101.5} - any: - {type: clinical, field: wbc_count, op: ">", value: 12.0} - {type: clinical, field: bands_pct, op: ">", value: 10} action: verdict: "URGENT_ALERT" assert: - {type: sepsis_flag, fields: {severity: high}} - name: "Escalate" salience: 40 when: all: - {type: sepsis_flag, field: severity, op: "==", value: high} - {type: clinical, field: age, op: ">=", value: 65} action: verdict: "ADMIT_ICU" Use either `conditions:` or `when:` per rule, never both. `not` passes when the inner condition does not hold (including when the field is absent). Produce/consume cycles between rules are rejected at validation. An action may also carry `retrieval_scope: { <key>: <value> }` to narrow which documents retrieval searches (Pattern 01). A rule may also carry `citation:` — the policy sentence it encodes. It is stored with the rule and shown beside it in decision audits, so a verdict can be defended with the source language, not just the rule name: - name: "Decline Late Returns" salience: 20 citation: "Returns are accepted within 30 days of delivery." when: all: - {type: retail, field: days_since_delivery, op: ">", value: 30} action: verdict: "DENIED" IMPORTANT: when persisting drafts returned by `import_policy_rules`, copy each rule's `citation` through into this YAML. Dropping it silently loses the link from the decision back to the policy clause that justifies it. Args: domain: Domain to author (an owned domain, or a new name to claim). rules_yaml: The full rule set as YAML text. dry_run: Validate only, without saving.
- 2026-09-27 `get_rule_source` changed (description)
  - before: Fetch a domain's rule set as editable YAML (plus the parsed rules and whether you may edit it). Use this before `put_rules` to see the current rules; the built-in demo domains are read-only.
  - after: Fetch a domain's rule set as editable YAML (plus the parsed rules and whether you may edit it). Use this before `put_rules` to see the current rules. For a built-in demo domain you get your own copy's rules once you have edited it, otherwise the shared demo's.
- 2026-09-27 `ingest_text` changed (description)
  - before: Add policy/reference text to a domain's knowledge base. The text is chunked and embedded; explanations for future decisions in this domain will cite it. Creating a new domain claims it for your account (plan limits apply). The built-in demo domains are read-only — ingest into your own domain instead. On team plans, only the domain admin (the member who created the domain, or the subscription owner) can add documents. Args: domain: Domain to ingest into (existing or new). text: The policy or reference text. source: Optional source name shown in the document list.
  - after: Add policy/reference text to a domain's knowledge base. The text is chunked and embedded; explanations for future decisions in this domain will cite it. Creating a new domain claims it for your account (plan limits apply). Ingesting into a built-in demo domain gives your account its own copy of that demo (it counts as one of your domains); the shared demo others see is unchanged. On team plans, only the domain admin (the member who created the domain, or the subscription owner) can add documents. Args: domain: Domain to ingest into (existing or new). text: The policy or reference text. source: Optional source name shown in the document list.

Full history: https://api.protogrid.dev/v1/servers/com.ai-rete-rag%2Fai-rete-rag-mcp/changes

## Dependencies

- pypi ai-rete-rag-mcp@0.11.0: unknown

Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0.

## Remotes

- https://ai-rete-rag.com/mcp (streamable-http, auth none, reachable true, uptime30d 0.974359)
- https://ai-rete-rag.com/mcp/auth (streamable-http, auth oauth2, reachable true, uptime30d 0.9745763)

## Packages

- pypi ai-rete-rag-mcp@0.11.0 secrets: AI_RETE_RAG_API_KEY

## Tools (9)

- `decide`: Make a deterministic, auditable decision in a domain.

The verdict comes from the domain's rule set (Rete engine, never the LLM),
so it is reproducible and compliant. The explanation is generated from the
domain's ingested policy documents.

Without an API key only the shared demo domains are available, and the
response carries `next_step`: how to get a free key for your own rules.
Pass that on to the user rather than dropping it.

Args:
    domain: Rule-set domain, e.g. "loan", "fraud", "clinical".
    query: Natural-language question or decision request.
    facts: Structured facts for working memory, e.g.
        {"credit_score": 710, "annual_income": 85000}. Use
        `get_parameters` to see which fields a domain's rules test.
        Facts you read yourself from photos, document scans, voice notes
        or video go here, under those field names; explicit facts always
        win over anything extracted server-side.
    fact_sources: Where each fact in `facts` came from, e.g.
        {"monthly_income": "payslip.jpg", "claim_usd": "voice note 1"}.
        Always set this for facts you read from a file, photo, recording
        or video: it is stored in the decision's audit record so a
        reviewer can tell typed facts from ones read off evidence. Facts
        without a source are recorded as "request".
    as_of: Read the domain's policy documents as of this day, as
        YYYY-MM-DD (default: today). Use the date a case was filed to
        decide it under the policy in force then; the rules themselves are
        always the current ones.
    unstructured_text: Optional free text (an application, a case note,
        a voice-note transcript, what a photo or video shows); facts are
        extracted from it automatically and merged.
    response_mode: "verdict_only" (fastest), "verdict_with_explanation",
        or "full_audit" (every rule evaluation + retrieved chunks, available
        on every plan including the free tier).
        rule_firings come back in causal order: a rule that matched a fact
        asserted by an earlier firing appears after it, with the derived
        facts listed under `asserted_facts`.
    filter_retrieval_with_rules: Pattern 01 — run the rules first and let a
        fired rule's `retrieval_scope` action narrow which documents the
        retrieval searches before it runs.
    extract_from_retrieval: Pattern 02 — parse the retrieved documents into
        facts and assert them into working memory, so rules fire on what was
        actually read (not just the facts you passed).

The result's `missing_parameters` lists rule inputs that were not
supplied but could still change the verdict, most decisive first. When it
is non-empty, tell the user the verdict is provisional and ask for those
facts; when it is empty, more facts cannot change the verdict.

- `get_parameters`: List the input parameters a domain's rules decide on — the facts to
collect before calling `decide`. Derived from your account's own copy of
the rules, so it covers your custom domains too.

Each parameter has its `field` name (the key to use in `facts`), `kind`
(number / boolean / string), the `tests` rules make on it (e.g. >= 720 —
match these units and scales), the `rules` and `verdicts` it can lead to,
and `max_salience`. Parameters come most decisive first: those feeding
the highest-salience rules, which win when several rules fire. Also
returns every verdict the domain can reach.

- `get_rule_source`: Fetch a domain's rule set as editable YAML (plus the parsed rules and
whether you may edit it). Use this before `put_rules` to see the current
rules. For a built-in demo domain you get your own copy's rules once you
have edited it, otherwise the shared demo's.

- `get_usage`: Show this account's decision usage, plan, and remaining monthly quota.
- `import_policy_rules`: Convert a written policy document into DRAFT decision rules (LLM-assisted).

Returns validated draft rules (when/action, including chained asserts where
the policy stages its determinations), derived rule→rule edges, and overlap
warnings. Each returned rule carries a `citation` field holding the policy
sentence it encodes (also summarized in the top-level `citations` map).
Coverage runs the other way too: `uncovered_sentences` lists policy
sentences no rule's citation points back to (out of
`policy_sentence_count`), and `unverified_citations` names rules whose
quote is missing or not found verbatim in the policy. Show both to the
user: an uncovered sentence may need a rule; an unverified one may be a
paraphrase that misstates the policy. `background_sentences` is the subset
of uncovered sentences with no obligation language (definitions,
preamble); lead with the others, but mention these too, since the split
is a keyword heuristic.
NOTHING IS SAVED: review the drafts (and show them to the user), then
persist explicitly with `put_rules` — validate first with dry_run=true,
and keep each rule's `citation` in the YAML you save so the audit trail
back to the policy survives.

Args:
    domain: Domain the rules are drafted for (an owned domain or a new name).
    policy_text: The policy document text (max ~50k characters).

- `ingest_text`: Add policy/reference text to a domain's knowledge base.

The text is chunked and embedded; explanations for future decisions in this
domain will cite it. Creating a new domain claims it for your account
(plan limits apply). Ingesting into a built-in demo domain gives your
account its own copy of that demo (it counts as one of your domains); the
shared demo others see is unchanged. On team plans, only the domain admin (the member
who created the domain, or the subscription owner) can add documents.

Documents can be dated. A decision only cites documents in force on its
date, so a replaced policy is never quoted for a new decision. To publish a
new version, ingest it under a new `source` with `supersedes` naming the old
one: the old document stops applying on the new one's `effective_from`
(today if not given), and the new one starts that day. A document can be
superseded only once; to replace a successor, supersede the successor.

Args:
    domain: Domain to ingest into (existing or new).
    text: The policy or reference text.
    source: Optional source name shown in the document list.
    effective_from: First day this document applies, as YYYY-MM-DD
        (default: always).
    effective_until: First day it no longer applies, as YYYY-MM-DD
        (default: no end).
    supersedes: Source name of the document this one replaces.

- `list_documents`: List the documents ingested into a domain's knowledge base.
- `list_rules`: List the decision rules for one domain (or all domains).

Returns each rule's conditions — either a flat AND list (field / operator /
value) or a `when` condition tree (nested all/any/not) — plus its verdict,
salience, and any asserted facts (`action.assert`, the facts a rule
produces for other rules to consume). `edges` lists the derived rule→rule
dependencies: src asserts a fact type that dst's conditions test (forward
chaining). Each rule may also carry `citation` — the policy sentence it
encodes — which is what lets a decision be traced back to the source
clause. Also includes overlap warnings. Use this to learn which fact
fields a domain expects before calling `decide`.

- `put_rules`: Create or replace a domain's rule set from YAML (self-serve rule authoring).

The first save to a new domain claims it for your account (plan limits
apply). Saving to a built-in demo domain saves your own copy of it, seeded
from the demo; the shared demo others see is unchanged. Rules are validated before
saving — set dry_run=true to validate without persisting. The response
reports ok/errors, the parsed rules, and any overlap warnings.

YAML format — a list of rules. Flat form (conditions are AND-ed):
    - name: "Approve"
      salience: 10
      conditions:
        - type: loan
          field: credit_score
          op: ">="
          value: 700
      action:
        verdict: "APPROVED"
        reason: "Credit score meets threshold"

Tree form — `when:` holds nested all/any/not condition groups, and an
action may assert derived facts that other rules consume (forward
chaining; the rule graph derives from these automatically):
    - name: "Sepsis Screen"
      salience: 30
      when:
        all:
          - {type: clinical, field: temperature_f, op: ">=", value: 101.5}
          - any:
              - {type: clinical, field: wbc_count, op: ">", value: 12.0}
              - {type: clinical, field: bands_pct, op: ">", value: 10}
      action:
        verdict: "URGENT_ALERT"
        assert:
          - {type: sepsis_flag, fields: {severity: high}}
    - name: "Escalate"
      salience: 40
      when:
        all:
          - {type: sepsis_flag, field: severity, op: "==", value: high}
          - {type: clinical, field: age, op: ">=", value: 65}
      action:
        verdict: "ADMIT_ICU"

Use either `conditions:` or `when:` per rule, never both. `not` passes
when the inner condition does not hold (including when the field is
absent). Produce/consume cycles between rules are rejected at validation.
An action may also carry `retrieval_scope: { <key>: <value> }` to narrow
which documents retrieval searches (Pattern 01).

A rule may also carry `citation:` — the policy sentence it encodes. It is
stored with the rule and shown beside it in decision audits, so a verdict
can be defended with the source language, not just the rule name:
    - name: "Decline Late Returns"
      salience: 20
      citation: "Returns are accepted within 30 days of delivery."
      when:
        all:
          - {type: retail, field: days_since_delivery, op: ">", value: 30}
      action:
        verdict: "DENIED"

IMPORTANT: when persisting drafts returned by `import_policy_rules`, copy
each rule's `citation` through into this YAML. Dropping it silently loses
the link from the decision back to the policy clause that justifies it.

Args:
    domain: Domain to author (an owned domain, or a new name to claim).
    rules_yaml: The full rule set as YAML text.
    dry_run: Validate only, without saving.

