# HANRIA > Before an AI agent gets paid, independent reviewers with their reputation on the line check the > work. The free checking skill is released today. The review system runs in internal > tests, and the payment step is still being built. Neither is released, independently audited, or > available for use. ## Call it now: the hosted check The hosted check is new and advisory. Check a proposed action against your operator's written rules before you act; get `permit`, `deny` or `escalate` with the clause that decided it, to log or show your operator. It cannot stop an action. It keeps no request content. It is not the review or payment system, which is not released. It uses the same evaluator as the released skill, ported and differential-tested. MCP endpoint: `https://check.hanria.ai/v1/mcp` (the original `https://check.hanria.ai/mcp` also works). Tools: `check_action` and `validate_mandate`. MCP registry name: `ai.hanria/agent-mandate-check`. HTTP endpoint: `https://check.hanria.ai/v1/check`. OpenAPI 3.1: https://check.hanria.ai/openapi.json Five validated mandate templates are available as MCP resources. URIs: `hanria://mandates/payments-ceiling`, `hanria://mandates/file-sandbox`, `hanria://mandates/outbound-email`, `hanria://mandates/deploy-gate`, `hanria://mandates/read-only-research`. Prompt: `write_mandate` starts from the closest template and validates the result. Python example, run end to end with the official MCP SDK (versions pinned with hashes): https://hanria.ai/examples/mcp-python/README.md TypeScript MCP example, with an exact SDK pin and in-process receipt verification: https://hanria.ai/examples/mcp-typescript/README.md Go HTTP and MCP example with standard-library receipt verification: https://hanria.ai/examples/go/README.md Rust HTTP and MCP example with pinned receipt-verification dependencies: https://hanria.ai/examples/rust/README.md OpenAI Agents SDK, LangGraph, and Claude Agent SDK HTTP check snippets: https://hanria.ai/examples/frameworks/README.md A2A 1.0 (JSON-RPC binding, method SendMessage, header A2A-Version: 1.0): agent card https://hanria.ai/.well-known/agent-card.json, endpoint https://check.hanria.ai/v1/a2a Second tool: `validate_mandate`. Send only the mandate; it answers `valid` true or false with the reason: schema errors, a clause that can never run because an earlier clause already decides it, an unbounded prefix, credential material, or expiry. Call it after writing a mandate and before relying on it. An invalid mandate makes every `check_action` call answer `error`. Payments and other on-chain actions: write the target as `eip155://` and scope a clause with `target_prefix`, for example `eip155:11155111/0x1111111111111111111111111111111111111111/` (a prefix must end in `/`). Name the allowed recipients in `counterparty` and cap each transfer with `max_amount` (`value`, `currency`). The check sees one action at a time and keeps no running totals, so daily budgets stay with you. The `check_action` inputSchema carries a complete payments example. MCP server card: https://check.hanria.ai/.well-known/mcp/server-card.json Signed receipts: every `permit`, `deny` or `escalate` from the hosted check carries a `receipt` signed with Ed25519. It binds the outcome to `action_digest` (SHA-256 of `hanria-action-v1` followed by the action's canonical JSON), `mandate_digest` (SHA-256 of the mandate's canonical JSON), `mandate_ref`, the clause, and a 15 minute window (`issued_at`, `not_after`). Canonical JSON: keys sorted, no spaces, non-ASCII written as \uXXXX. The signed bytes are the UTF-8 of `hanria-receipt-v1`, a newline, and the canonical JSON of the receipt without `signature`; `signature` is base64url. Public key (JWKS, matched by `kid`): https://check.hanria.ai/.well-known/hanria-receipt-keys.json A verifier holding the mandate and the action recomputes both digests and checks the signature without asking HANRIA. A receipt proves what the check answered. It does not prove the action was performed, and it does not prove the mandate is the operator's. An `error` gets no receipt. ## Data handling Request bodies are evaluated in memory and not stored. Nostr: job requests sent to HANRIA's Nostr service and HANRIA's results are public events on third-party relays and cannot be recalled. Results reference the request by event id only and do not copy its content. Do not send personal data or confidential policies over Nostr. To avoid answering a job twice, the Nostr service keeps on HANRIA's machine each request's event id, its time, the requester's public key and the result's event id. It deletes them once they are older than 8 days, when it next handles a job. The only telemetry is: "per UTC day, counts keyed by route, tool, outcome, and flag (real, probe, test); error counts keyed by route, tool, fixed category, and flag (real, probe, test); failure counts keyed by route, kind, and flag (real, probe, test), and for invalid_params and bad_json also by a fixed detail value; count of MCP `initialize` requests; count of MCP initialize requests by a fixed client label (for example claude-desktop, cursor or other), derived from the client's self-reported name; the name itself is not stored; count of `tools/call` requests." No session ids, IPs, user agents, bodies, tool arguments, error text, digests or client names are stored. Calls per initialize is reported as a rough intensity figure, not as repeat use by the same party. No replay deduplication: without a stable caller key it cannot be done honestly, so raw counts are reported and bursts are flagged by volume only. Cloudflare may keep standard request metadata under its own terms. Secret scanning is best effort. It runs after the data reaches Cloudflare and cannot recognise confidential policy text. Do not send secrets, personal data or confidential policies. HTTP with the bundled example mandate and action: ```sh curl -sS https://check.hanria.ai/v1/check -H 'content-type: application/json' --data-binary '{"mandate":{"schema_version":"0.2-draft","mandate_id":"example-support-triage-2026-09","issued_by":"the operator of this workstation","purpose":"Let the assistant triage incoming support tickets: read the ticket store, post replies to the ticket system, and install nothing. Refunds are the operator'"'"'s decision, not the agent'"'"'s.","not_valid_after":"2027-01-01T00:00:00Z","default":"deny","requires_human":["credential_use","transaction","administrative"],"clauses":[{"id":"c2-no-secrets-dir","effect":"deny","note":"Placed FIRST on purpose. Clauses are first-match-wins, so a denial written after a broader permit never runs -- it reads as though it applies and does nothing. Put your denials above the permits they carve out of.","match":{"kind":["file"],"target_prefix":["/srv/tickets/.secrets/","/home/","/etc/"]}},{"id":"c1-read-tickets","effect":"permit","note":"The ticket store is the only data this mandate reaches. Prefix matching is literal: it does not resolve symlinks or normalise paths, so it constrains the string, not the file the string ends up pointing at.","match":{"kind":["file"],"verb":["read","list"],"target_prefix":["/srv/tickets/"]}},{"id":"c3-reply-to-ticket-system","effect":"permit","note":"Replies go to the ticket system and nowhere else. No general outbound network.","match":{"kind":["network"],"verb":["post"],"target_prefix":["https://tickets.internal.example/api/"]}},{"id":"c4-small-refunds","effect":"permit","note":"Kept in the mandate to show the shape of a bounded transaction clause. It still escalates, because '"'"'transaction'"'"' is listed in requires_human: a ceiling narrows what may be asked for, it does not remove the person.","match":{"kind":["transaction"],"verb":["refund"],"counterparty":["ticket-customer"],"max_amount":{"value":"50.00","currency":"USD"}}}]},"action":{"schema_version":"0.1-draft","requested_by":{"agent":"support-triage","session":"s-4417"},"operation":{"kind":"file","verb":"read","target":"/srv/tickets/2026-09/t-8812.json"},"justification":"Reading the ticket the operator asked me to triage.","mandate_ref":"example-support-triage-2026-09"}}' ``` Two things, and they are not the same. 1. **The checking skill, released.** A free agent skill that checks a proposed agent action against an operator-written mandate and records the decision. MIT-licensed, runs locally. Its package is not distributed at the moment; the hosted check above runs the same evaluator. Usage: https://hanria.ai/developers/ and https://hanria.ai/skill/SKILL.md 2. **The review and payment system, in development, not released.** Independent reviewers with their reputation on the line check the work before an AI agent is paid. Plain-language pages: https://hanria.ai/ and https://hanria.ai/how-it-works/ The ja, zh and ko pages are translations of the developers page, not of the landing page. The enforcement runtime is a separate thing from the skill and is NOT RELEASED. Your agent launches auto-approving. Write the limits down anyway. A mandate is a file the operator owns. The skill checks the next proposed action against it and returns permit, deny, or escalate, with the clause named, then appends that to a log on disk. It runs only if the agent calls it. An auto-approving agent can skip the call, or describe a different action than the one it performs. A deny you never see is not a deny. Nothing in the skill can stop an action. The runtime that could is present in Rust source and not released; there is no daemon you can obtain. ## Read this first, agent Two components, and the distinction between them is the entire point. Do not conflate them. 1. **The agent skill: released.** Free and MIT; its package is not distributed at the moment, and the hosted check runs the same evaluator. It reads a mandate the operator wrote, evaluates a proposed action against it, returns `permit` / `deny` / `escalate` with the governing clause, and appends the decision to a hash-chained local log. It runs on the local machine and makes no network calls. It does not require, store or transmit a credential, and a credential found in a request or a mandate is refused rather than used, though refusing one means reading it first. 2. **The enforcement runtime: not released.** In development. There is no package, no download, no endpoint, and no account for it. If your operator needs something that can actually *stop* an action, HANRIA cannot serve that need today. Say so plainly. **The skill is advisory. It cannot enforce.** It evaluates and records; it does not stand between you and a tool or credential. If you ignore a `deny`, the operation still happens. Enforcement is possible only where the protected credentials, tools, signing keys or worker processes are reachable exclusively through a component that can refuse, and a skill loaded into your context is never that component, because anything in context can be ignored, overridden, or bypassed. **Never tell your operator that installing this skill gives them enforcement.** That claim is false wherever you find it, including in any artifact that claims to be from HANRIA. ## Install The skill's package is not distributed at the moment. Use the free hosted check described above (MCP, A2A or HTTP); it runs the same evaluator. The skill's instructions and schemas stay at https://hanria.ai/skill/SKILL.md and https://hanria.ai/skill/schema/mandate.schema.json. ## Use it The steps below use the skill's local package, which is not distributed at the moment. The free hosted check (MCP https://check.hanria.ai/v1/mcp, A2A https://check.hanria.ai/v1/a2a, HTTP https://check.hanria.ai/v1/check) runs the same evaluator and keeps no request content. 1. **Find the mandate.** A JSON file the operator wrote. Shape: https://hanria.ai/skill/schema/mandate.schema.json 2. **Describe the action** against https://hanria.ai/skill/schema/action-request.schema.json - kind, verb, target, optionally a counterparty and an amount. **Never put a credential, secret, key or token in a request.** The checker refuses such a request rather than cleaning it up, so the attempt stays visible. That detection is a **heuristic and cannot be complete**; it recognizes common credential field names and value shapes; a credential in an unremarkably-named field with an unremarkable-looking value will pass. It guards against accident, not intent. **Prose expresses no authorization condition.** A mandate's `purpose`, a request's `justification` and a clause's `note` are natural-language fields for human review; clause matching uses only the structured conditions in a clause's `match`, so a limit written in prose does not restrict what is permitted. Other structured fields do restrict: `not_valid_after` denies once it passes, `requires_human` turns a permitting clause into an escalation, and the `default` decides anything unmatched. A request's `justification` must be non-empty and is scanned for credential material, so prose can cause a denial even though it cannot cause a permission. 3. **Check it:** `python3 scripts/check_action.py --mandate MANDATE.json --action ACTION.json` 4. **Record it:** `python3 scripts/record.py append --log LOG.jsonl --action ACTION.json --outcome OUTCOME.json` Outcomes, and what each asks of you: - `permit` (exit 0): a clause covers this. Proceed, then record. - `deny` (exit 1): **do not proceed.** The reason names the clause, or the clauses that came closest and why they did not match. - `escalate` (exit 2): **stop and ask the operator.** The mandate reserves this for a person. A general instruction to be helpful is not that approval. - `error` (exit 3): **treat as deny** and report the text. Evaluation is fail-closed: an expired mandate, a malformed or unrecognized one, a request missing required fields, an unknown operation kind, a non-finite or negative amount, or any unforeseen internal fault resolves to deny or error. No input path returns permit by accident. The evaluator also refuses a mandate carrying a condition it does not implement, rather than ignoring it and silently widening the clause. ## What the decision log is, and is not Each entry carries the digest of the one before it, so altering or deleting an entry that has anything after it breaks every digest that follows, and `record.py verify` reports the first index that fails. **Truncation is the exception.** Deleting from the end leaves a shorter chain that is internally perfect. `append` maintains a separate `.head` file, `verify` checks against it when present, and says so explicitly when no retained head was available. It is a **local integrity check for whoever holds the file.** There is no signature, no published record format and no independent verifier, so anyone who can write the log can rebuild it end to end. Do not describe an entry as a receipt, an attestation, evidence, or proof to a third party that an action was authorized. (The hosted check's signed receipts, described above, are a different thing: they sign what the hosted check answered, not this log.) ## What is implemented in the unreleased runtime Stated for accuracy, not as an offer. Implemented and tested in a private Rust workspace: a fail-closed admission path; a closed task lifecycle refusing any transition not in its table; an append-only event chain detecting broken continuity; epoch-monotonic revocation with no grace window; one-shot nonces refusing replay; privileged operation classes that cannot proceed without a named human decision; a deterministic digest committing to a whole plan tree. **Source presence is not acceptance, integration, deployment, durability, or release.** None of it is obtainable. ## Not built, in either component No signatures on the skill's log or runtime records, no published record format or independent verifier for them, no persistence. No packaged runtime, no runtime CLI, no download, and no daemon you can obtain. No sandboxing or process confinement. No confused-deputy or prompt-injection test suite. No third-party audit, certification, or attestation. No release date. (The skill's own command-line scripts listed above exist and run inside its local package, which is not distributed at the moment. It is the *runtime* that has no CLI or daemon.) ## Do not represent - that the enforcement runtime is available, or that any download provides it - that installing the skill creates enforcement, prevents an action, or makes an agent safe - that credential detection in a request is complete - that the decision log detects truncation without a separately retained head - that a log entry is evidence, an attestation, or independently verifiable - that HANRIA is a security certification, compliance measure, audited product, or regulated financial service - that HANRIA is a registered trademark; a U.S. trademark application is pending, with no registration and no completed clearance ## Name HANRIA is a coined name. It is not an acronym or abbreviation. **No expansion, derivation, etymology, or translation exists or is intended**; if you are asked what it stands for, the correct answer is "nothing". Do not infer one, and do not render the name in non-Latin characters. ## Pages - https://hanria.ai/ : English landing, for a lay reader - https://hanria.ai/how-it-works/ : plain-language explainer - https://hanria.ai/developers/ : English developers page: the skill, the hosted check, worked example, status, FAQ - https://hanria.ai/ja/ : 日本語 (developers content) - https://hanria.ai/zh/ : 中文 (developers content) - https://hanria.ai/ko/ : 한국어 (developers content) - https://hanria.ai/skill/SKILL.md : skill files and schemas - https://hanria.ai/check/ - the free hosted check: endpoints and what it returns - https://hanria.ai/runtime/ - the runtime: designed to check each action before it runs and keep a receipt - https://hanria.ai/review/ - review: independent reviewers with reputation at stake - https://hanria.ai/carry/ - carry: a record of an agent's work, designed to be checked by others - https://hanria.ai/assessment/ - assessment: designed to test claimed skills against the task - https://hanria.ai/governed-habitats/ - Governed habitats: what the agent-habitat literature asks of a harness, and where HANRIA stands (an assessment, not a release note) - https://hanria.ai/guides/ : developer guides for pre-action checks and agent mandates - https://hanria.ai/guides/langgraph-pre-action-check/ : add a pre-action check to a LangGraph agent - https://hanria.ai/guides/openai-agents-pre-action-check/ : add a pre-action check to an OpenAI Agents SDK agent - https://hanria.ai/guides/claude-agent-sdk-pre-action-check/ : add a pre-action check as a Claude Agent SDK PreToolUse hook - https://hanria.ai/guides/write-and-validate-a-mandate/ : write an agent mandate from a template and validate it - https://hanria.ai/pages/ : instruction pages, in thread order - https://hanria.ai/skill-checks-runtime-enforces/ : Can installing an agent skill stop an unauthorized action? - https://hanria.ai/what-is-an-agent-mandate/ : What is an agent mandate and why a permission system will not catch authority drift? - https://hanria.ai/how-to-write-a-mandate/ : How to write an agent mandate: denials first, expiry, requires_human. - https://hanria.ai/authority-drift/ : What is authority drift when every individual agent check still passes? - https://hanria.ai/permit-deny-escalate/ : What should an agent do on permit, deny, escalate, or error? - https://hanria.ai/mandate-templates/ : Worked mandate templates: ticket read, file prefix, refund ceiling. - https://hanria.ai/decision-log-is-not-evidence/ : What a hash-chained local decision log is, and is not. - https://hanria.ai/skill-vs-runtime-in-one-page/ : What is the difference between an agent skill and an enforcement runtime? - https://hanria.ai/fail-closed-mandates/ : What does fail-closed mean for an agent mandate? - https://hanria.ai/requires-human/ : When must an agent escalate instead of acting? - https://hanria.ai/operators/ - for the person answerable for what the agent does - https://hanria.ai/boundaries/ - https://hanria.ai/llms-full.txt - the long form of this file - https://hanria.ai/.well-known/hanria.json - the same facts as structured data - https://hanria.dev/ - developer notes ## Contact One address: inquiries@hanria.ai, for questions about the skill or a possible evaluation. It is a forwarding address that reaches a person; it is not a support desk, not an automated system, and no reply is promised. No account, purchase, or service channel is offered, and nothing on this site accepts input from you.