Developer guide
Write and validate an agent mandate
A mandate expresses a boundary only through valid enforcement fields; an invalid mandate makes every action check answer error.
Start from a template
This exact file sandbox entry comes from the templates embedded in public/try.1.js. Its first clause denies the sensitive prefixes, its second clause permits file reads and writes under one workspace prefix, and its default denies anything unmatched.
{
"name": "file-sandbox",
"title": "File sandbox",
"description": "Deny sensitive directories and permit reads and writes under one bounded directory.",
"mandate": {
"schema_version": "0.2-draft",
"mandate_id": "template-file-sandbox",
"purpose": "Confine file reads and writes to one working directory.",
"default": "deny",
"clauses": [
{ "id": "deny-sensitive", "effect": "deny", "match": { "kind": ["file"], "target_prefix": ["~/.ssh/", "/etc/"] } },
{ "id": "permit-workspace", "effect": "permit", "match": { "kind": ["file"], "verb": ["read", "write"], "target_prefix": ["/workspace/project/"] } }
]
},
"action": {
"schema_version": "0.1-draft",
"requested_by": { "agent": "template-agent" },
"operation": { "kind": "file", "verb": "write", "target": "/workspace/project/report.txt" },
"justification": "Write the report inside the bounded workspace."
},
"outcome": "permit"
},
Change the mandate identifier for tracking and change the enforcement fields to match the authority you intend. Purpose, note, and justification are prose and never restrict an action. Only clause match fields, not_valid_after, requires_human, and default do. Put narrower denials before broader permits because the first matching clause decides. Do not put secrets, personal data, or confidential policies in the mandate.
Validate the mandate
The form uses this exact validation flow from public/try.1.js. It initializes MCP, calls validate_mandate, and accepts structured content or the text fallback.
export async function validateMandate(mandateText, fetchImpl = fetch) {
const mandate = parseDocument(mandateText, "mandate");
const initialized = await postJson(MCP_URL, {
jsonrpc: "2.0",
id: 1,
method: "initialize",
params: {
protocolVersion: "2025-11-25",
capabilities: {},
clientInfo: { name: "hanria.ai-try-it", version: "1" }
}
}, fetchImpl);
if (initialized.error) throw new Error(initialized.error.message || "initialize failed", { cause: "response" });
const called = await postJson(MCP_URL, {
jsonrpc: "2.0",
id: 2,
method: "tools/call",
params: { name: "validate_mandate", arguments: { mandate } }
}, fetchImpl);
if (called.error) throw new Error(called.error.message || "validate_mandate failed", { cause: "response" });
const structured = called.result?.structuredContent;
if (structured && typeof structured === "object") return structured;
const text = called.result?.content?.find((item) => item.type === "text")?.text;
if (typeof text === "string") {
try {
return JSON.parse(text);
} catch {
throw new Error("invalid validate_mandate result", { cause: "response" });
}
}
throw new Error("missing validate_mandate result", { cause: "response" });
}
Run it
Open the form
Go to the try-it form and select File sandbox.
Edit the mandate
Replace the example identifiers and boundaries with the structured limits you intend.
Validate only
Select Validate mandate only. A result with
valid: truemeans the validator accepted the document. A result withvalid: falsenames the validation problem. Fix it before using the mandate.Check an action
Use the mandate with a representative action and inspect the outcome, governing clause, and signed receipt.
Handle every outcome
The action check returns permit, deny, or escalate with the governing clause and a signed receipt. The check is advisory, and your integration is what refuses the action. The hosted check evaluates the request in memory and keeps no request content.
- permit: one clause permits this single proposed action. Your integration may continue according to its own permission flow.
- deny: do not perform the action and do not try another path.
- escalate: stop and ask the operator for a decision outside the integration.
- error: treat it as deny, report the reason, and do not retry blindly.
An invalid mandate makes every action check return error, which your integration must treat as deny; it does not express a boundary. Validation does not convert the mandate into an enforcement boundary.
References
Try the check · Verify signed receipts · OpenAPI document · Agent-facing summary