Skip to main content
Glama
README.md
# ruleverdict

Ask a rule engine, not a guess. ruleverdict is a small
client for the ai-rete-rag service, which decides cases
with deterministic rules instead of free-form model
output: you pass structured facts and/or free text for a
domain, and the verdict comes from that domain's rule
set, explained with the documents the rules rest on.

Alongside deciding, it covers the full life of a domain:
see which facts the rules need, inspect the rules
themselves, pull them down as editable YAML, draft new
rules from a written policy (each draft cites the
sentence it encodes, and nothing is saved until you say
so), publish a replacement rule set, feed policy text
into the knowledge base, and watch the monthly decision
quota. Responses come back exactly as the service
returned them: nothing is trimmed, renamed or summarised
on the way through.

## Configuration

Two environment variables control the client:

- `AI_RETE_RAG_API_KEY` (optional) — when set, it is sent
  on every request as `Authorization: Bearer <key>`.
  Leaving it unset is not an error: shared demo domains
  work keyless, and enforcement problems such as a
  missing domain claim or an exhausted quota surface from
  the API as errors rather than failing locally.
- `AI_RETE_RAG_API_URL` (optional) — API base URL.
  Defaults to `https://ai-rete-rag.com` (see "Endpoint
  provenance" below).

## Tools

- `decide` — make a decision in a domain from structured
  `facts` and/or free `text`; the verdict comes from the
  rule engine, with a document-grounded explanation.
  Optional: `as_of` (a date the decision is evaluated
  at), `fact_sources` (where each fact came from), and
  the retrieval-mode flags `pattern_01` (Pattern 01:
  rules-scope retrieval) and `pattern_02` (Pattern 02:
  retrieval into working memory). Typical call:
  `decide(domain="loan", facts={...})`.
- `get_parameters` — the facts a domain's rules decide
  on, most decisive first: what to collect before
  calling `decide`.
- `list_rules` — inspect a domain's rules: conditions,
  verdicts, salience and overlaps.
- `get_rule_source` — fetch a domain's rule set as
  editable YAML.
- `import_policy_rules` — turn a written policy document
  into draft rules, each citing the sentence it encodes.
  Nothing is saved.
- `put_rules` — create or replace a domain's rule set
  from YAML; pass `dry_run` to validate without saving.
- `ingest_text` — add policy text to a domain's
  knowledge base, optionally with `effective_from` /
  `effective_until` dates or a `supersedes` pointer to
  the version it replaces.
- `list_documents` — browse a domain's ingested
  documents.
- `get_usage` — check your plan and remaining monthly
  decision quota.

Unset optional arguments are omitted from requests
entirely. An upstream non-2xx reply fails with
`ai-rete-rag error: HTTP <status>` and an unreachable API
with `ai-rete-rag unreachable`.

### Endpoint provenance

The original project's README pins the nine tools, the
worked `decide` example, the Pattern 01 / Pattern 02
modes, both environment variable names, the optional-key
behaviour, and the dry-run / nothing-saved workflow
semantics — but not the request paths. Those are
reconstructions, labelled as such:

- `POST <base>/api/decide` with the arguments as the JSON
  body (used by `decide`).
- `GET <base>/api/domains/{domain}/parameters` (used by
  `get_parameters`).
- `GET <base>/api/domains/{domain}/rules` (used by
  `list_rules`).
- `GET <base>/api/domains/{domain}/rules/source` (used
  by `get_rule_source`).
- `POST <base>/api/domains/{domain}/rules/import` with
  body `{"text": "..."}` (used by
  `import_policy_rules`).
- `PUT <base>/api/domains/{domain}/rules` with body
  `{"rules": "...", "dry_run": ...}` (used by
  `put_rules`).
- `POST <base>/api/domains/{domain}/documents` with body
  `{"text": "...", ...}` (used by `ingest_text`).
- `GET <base>/api/domains/{domain}/documents` (used by
  `list_documents`).
- `GET <base>/api/usage` (used by `get_usage`).

Domain path segments are URL-encoded.

## CLI

Each tool is a subcommand taking one JSON argument
string:

```bash
npx @reneturcios/ruleverdict decide '{"domain":"loan","facts":{"income":85000}}'
npx @reneturcios/ruleverdict get_parameters '{"domain":"loan"}'
npx @reneturcios/ruleverdict list_rules '{"domain":"loan"}'
npx @reneturcios/ruleverdict get_rule_source '{"domain":"loan"}'
npx @reneturcios/ruleverdict import_policy_rules '{"domain":"loan","text":"Loans need verified income."}'
npx @reneturcios/ruleverdict put_rules '{"domain":"loan","rules":"rules: []","dry_run":true}'
npx @reneturcios/ruleverdict ingest_text '{"domain":"loan","text":"Policy text"}'
npx @reneturcios/ruleverdict list_documents '{"domain":"loan"}'
npx @reneturcios/ruleverdict get_usage '{}'
npx @reneturcios/ruleverdict --version
```

Output is the tool's result text (the upstream body on
success). Exit codes: `0` on success, `1` on a runtime
error, `2` on a usage error.

## MCP server

```bash
npx -y @reneturcios/ruleverdict mcp
```

MCP client config (the key is optional; provide it
through the client's environment when you have one):

```json
{
  "mcpServers": {
    "ruleverdict": {
      "command": "npx",
      "args": ["-y", "@reneturcios/ruleverdict", "mcp"],
      "env": {
        "AI_RETE_RAG_API_KEY": "<your key>"
      }
    }
  }
}
```

## Docker

```bash
docker run -i ghcr.io/cloudcorprecords/ruleverdict
docker run --rm ghcr.io/cloudcorprecords/ruleverdict get_usage '{}'
```

## Development

```bash
npm install
npm run build   # tsc -> dist/
npm test        # tsx --test test/*.test.ts (fake fetch only, no network)
npm run dev     # run the CLI from source
```

## License

MIT — Copyright (c) 2026 Rene Turcios