Recommended alignment · NIST AI RMF 1.0 · AI Risk Management Framework
Where 800-207 governs who can connect, the AI RMF governs what the AI may do. Its Core has four functions — Govern, Map, Measure, Manage — and nineteen categories. For each one, here's what it requires, the approach we recommend, the configuration that implements it, and how you confirm it's working. This is a recommended reference — the exact configs are finalized against your deployment.
Source: NIST AI Risk Management Framework (AI RMF 1.0) ↗ · category structure per the NIST AIRC Core reference ↗ · requirements paraphrased; read the original for the authoritative text.
Govern
The culture the other three functions run inside — policy, accountability, and the supply chain the AI is built from. 6 categories
# The policy file IS the enforcement — the document is generated from it policy: version: 1.4 owner: "COO" review_cycle: quarterly renders_to: /var/hermes/ai-policy.md # the readable version guardrails: mode: enforced # enforced | advisory approvals: sensitive # every | sensitive | none
$ hermes policy show policy v1.4 owner=COO next review 2026-10-01 document ..... generated from policy v1.4 drift ........ NONE # written policy == enforced policy
# Every role is owned by a person, and scopes what the AI may do roles: - name: legal-reader owner: "j.doe@firm.example" # accountable human may: [read_file, search_docs] - name: ops-editor owner: "m.ruiz@firm.example" may: [read_file, write_file] approvals: every # stricter than the default require_owner: true # unowned role = refuses to load
$ hermes roles list legal-reader owner=j.doe may=read_file,search_docs ops-editor owner=m.ruiz may=read_file,write_file approvals=every # adding a role with no owner: ERROR role 'temp-bot' has no owner — refused to load
$ hermes audit --decisions --last 30d --group-by reviewer j.doe 41 approvals 9 rejections m.ruiz 12 approvals 1 rejection # evidence of who reviews — the composition of that list is # your organization's call, not the appliance's
# Post-turn verification, surfaced to the user — not silently logged guardrails: reality_check: true surface_warnings: user # user | log-only feedback: flag_action: enabled # one keystroke files an incident incidents: /var/hermes/incidents/
REALITY-CHECK WARNING the assistant reported writing /matters/acme/summary.md — no such write occurred on disk. [f] flag this # → incidents/2026-07-30-0004.md, with the transcript
$ hermes incidents --since 2026-04-01
2026-05-14 reality-check warning resolved: prompt scope narrowed
2026-06-02 refused: out-of-scope resolved: no action needed
2026-07-30 reality-check warning open
# three items to walk through — the walking through is yours
# Local model, pinned by digest; no external inference path at all model: source: local name: qwen3-35b digest: sha256:9f2c4b… # pinned — a change needs approval network: egress: deny # default-deny, not default-allow allow: [] # no model API, no telemetry endpoint
$ hermes supply-chain model ........ qwen3-35b sha256:9f2c4b… PINNED external inference endpoints ............. 0 $ curl -s https://api.example-llm.com/v1 # from the appliance curl: (7) egress denied by policy
Map
Knowing what you have actually deployed — its context, its category, its capabilities, and everything it touches. 5 categories
# Declared purpose, enforced as scope deployment: purpose: "Draft and review internal legal documents" setting: "12-person firm, on-premises, no client PII export" in_scope: [draft, summarize, search_internal] out_of_scope: [client_advice, external_publishing, hiring_decisions] on_out_of_scope: refuse_and_log
2026-07-30 11:04:12 identity=jdoe action=draft target=hiring/candidate-rank.md decision=REFUSE policy=out-of-scope # the refusal is recorded, so scope is auditable — not just intended
# Generated from live config — cannot drift from what is running
system_card:
task: "retrieval-grounded drafting and summarization"
method: "local LLM + local document index; no fine-tuning on client data"
knowledge_cutoff: "2025-10"
cannot: ["access the internet",
"act without an approval for file changes",
"see documents outside the granted role scope"]
$ hermes system-card task ............ retrieval-grounded drafting and summarization model ........... qwen3-35b (local) cutoff 2025-10 cannot .......... internet · unapproved writes · out-of-role documents generated from .. live config (policy v1.4)
# Capability = allow-list. Absent means unavailable, not merely discouraged. tools: read_file: {benefit: "find precedent fast", roles: [legal-reader, ops-editor]} search_docs: {benefit: "answer from our own files", roles: [legal-reader, ops-editor]} write_file: {benefit: "produce the first draft", roles: [ops-editor], approval: required} default: deny
$ hermes tools --role legal-reader read_file granted search_docs granted write_file not granted # not "asks first" — unavailable
# Every reachable component carries a risk note and an owner components: - service: private-ai risk: "generates text that may be wrong or over-confident" control: reality_check + approvals owner: "COO" - service: docs-index risk: "contains client-confidential matter files" control: role scope + Ziti dial policy owner: "Managing Partner" - service: tool-runner risk: "performs actions with side effects" control: approval gate (every) owner: "COO" inventory_check: strict # unmapped service = reported gap
$ hermes inventory --cross-check ziti services ..... 3 mapped components ..... 3 unmapped .......... 0 # add a service without a risk note and this reads: unmapped 1 (gap)
$ hermes data-classes --reachable client-confidential reachable by: legal-reader, ops-editor internal-general reachable by: all roles regulated-PII reachable by: none # excluded from the index # who is affected, and how much it matters, is your assessment
Measure
Numbers you can actually compute on your own box — and evaluation that runs before a change ships, not after it breaks. 4 categories
# Metrics computed locally from the audit log — nothing leaves the box metrics: - {id: refusal_rate, source: audit, window: 30d} - {id: approval_hit_rate, source: audit, window: 30d} - {id: reality_check_rate, source: audit, window: 30d} - {id: grounded_rate, source: audit, window: 30d} report_to: /var/hermes/metrics/ # local file, not a cloud endpoint
$ hermes metrics --last 30d refusal_rate ......... 3.1% (41 of 1,320 requests) approval_hit_rate .... 12.4% (164 pauses for a human yes/no) reality_check_rate ... 0.5% (7 false claims caught) grounded_rate ........ 94.2% (answers citing a retrieved document)
# Evaluation gates the change — it does not merely describe it eval: suite: /var/hermes/eval/firm-cases.yaml # your documents, your tasks run_on: [model_change, guardrail_change, index_rebuild] thresholds: grounded_rate: ">= 0.90" unsafe_refusal: ">= 0.98" # refuses what it should refuse regression_vs_last: "<= 0.02" on_fail: block_rollout
$ hermes eval run --candidate qwen3-35b-v2 grounded_rate ....... 0.87 threshold 0.90 FAIL unsafe_refusal ...... 0.99 threshold 0.98 PASS rollout ............. BLOCKED # the old model stays in service
# Each risk names the metric that watches it and the level that trips
risks:
- id: R1
desc: "AI states something it did not do"
watched_by: reality_check_rate
trips_above: 0.01
owner: COO
- id: R2
desc: "answers not grounded in our documents"
watched_by: grounded_rate
trips_below: 0.90
owner: COO
- id: R3
desc: "scope creep into out-of-scope tasks"
watched_by: refusal_rate
trips_above: 0.10
owner: "Managing Partner"
$ hermes risk status R1 reality_check_rate 0.5% trips >1.0% OK trend ↘ R2 grounded_rate 94.2% trips <90% OK trend → R3 refusal_rate 3.1% trips >10% OK trend ↗ (watch)
$ hermes metrics --history --by-quarter
Q1 Q2 Q3
reality_check 0.9% 0.7% 0.5%
incidents filed 4 3 3
# the metric improved while incidents held flat —
# exactly the discrepancy this review exists to notice
Manage
Acting on what you measured — prioritized responses, safe failure, governed third-party change, and a record of it all. 4 categories
# Severity chooses the control strength — high risk gets a hard stop responses: - {risk: R1, severity: high, action: block} # refuse to return the turn - {risk: R2, severity: medium, action: approve} # pause for a human - {risk: R3, severity: low, action: warn} # advisory only unhandled_risk: block # a risk with no response fails closed
2026-07-30 15:41:02 identity=mruiz action=write_file target=/matters/acme/summary.md decision=BLOCK policy=R1-high # the claim failed the reality-check, so the turn was refused — # not returned with a warning attached
# Ungoverned operation is not a degraded mode — it is a stopped one failure: mode: closed # no guardrails => no service on_config_unreadable: refuse_all kill_switch: command: "hermes stop --hard" # drops Ziti bind + unloads model decommission: index: wipe audit_log: "retain 7y" model: remove
$ mv /etc/hermes/guardrails.yaml /tmp && hermes doctor guardrails ......... NOT FOUND service ............ REFUSING ALL REQUESTS (fail-closed) # it will not answer at all rather than answer ungoverned
# A model change is a governed change — never a silent one supply_chain: pin: strict # digest must match the manifest allow_unsigned: false change_requires: [approval, eval_pass] manifest: /etc/hermes/manifest.lock
$ hermes model use ./mistral-new.gguf digest sha256:41ab… not in manifest.lock ..... BLOCKED required: approval by an owner + eval suite pass # the running model is unchanged
# Monthly report generated on the box, from the record itself reporting: cadence: monthly path: /var/hermes/reports/ includes: [metrics, risk_status, incidents, approvals, config_changes] distribute_to: ["COO", "Managing Partner"] # the comms plan audit: enabled: true path: /var/hermes/audit.log # stays on the appliance
$ hermes report --month 2026-07
risks tracked 3 · treatments fired 164 · incidents 3 (2 closed)
config changes 1 ... policy v1.3 → v1.4 approved by COO 2026-07-11
written to /var/hermes/reports/2026-07.md local only
All nineteen categories of the NIST AI RMF Core — Govern, Map, Measure, Manage — each with the requirement, the approach we recommend, the configuration that implements it, and how you confirm it's working. Four are marked as organizational practice, where no configuration can honestly make the claim. This is standard 2 of the alignment set; standard 1 is NIST SP 800-207, Zero Trust.
The free Readiness Check tells you which of these you already meet and which need work — then the build puts the recommended configuration in place.
Start the free Readiness Check →