Overview
Awarranty.md file is a signed, operator-defined policy that tells Sigil Sign what your agent is and isn’t allowed to do. It is the contract between you and your agent’s execution layer.
Sigil Sign evaluates every agent intent against this file before allowing any action to proceed. If the action violates policy, it is denied before it executes, not audited after.
Generate Your Policy
Use Sigil Warrant at sigilcore.com/tools/warrant to generate, sign, and download yourwarranty.md. Two paths are available:
- Warrant Builder: guided step-by-step flow. No policy syntax required. Recommended for first-time operators.
- Manual Warrant: choose the structured Form for common policies or Advanced Mode to edit the complete
warranty.mdsource. Advanced Mode validates, signs, downloads, re-imports, and deploys the exact policy bytes.
warranty.md with the same schema and signature-envelope contract. Its policy content reflects the controls you author.
Current authoring contract.
@sigilcore/warrant-core@0.4.0 is the shared parser, canonicalizer, signer-envelope validator, and authoring-capability source for Policy 2.3. Manual Advanced covers every field that the deployed Sign contract accepts. Manual Form and Warrant Builder expose their supported subsets and route unsupported fields to Advanced Mode or reject them before changing policy state. See the current generated capability matrix.File Format
warranty.md uses a plain-text, typed-block format. Blocks are defined by ## headers. A 1.x policy requires an enforceable EVM, tool-call, custom, or model-budget rule. A 2.0 or profileless 2.1 policy may also consist of enforced ## soft_limits. A 2.1 resource profile adds a trusted execution-shim boundary only when the policy declares one of the resource-profile blocks. Policy 2.2 adds exact inbound MCP result coverage. Policy 2.3 adds local redaction, operator scanner evidence, and time-bounded observation. Neither extends result coverage to ## tool_calls.
Policy format 2.0.0: 1.x policies keep their existing semantics. New 2.0 syntax is opt-in through the version line and requires a Sign build that supports the field. Policy format 2.0 adds typed HTTP intents, allow-rule operators, enforced named caps, MCP-native actions, approval patterns, and provenance gates. Existing signed 1.x files remain unchanged.For a controlled upgrade, follow the 1.x to 2.0 migration guide. The guide includes the re-sign, rollback, and conformance-vector checks required before activation.
mcp.response.* mapping,
it also makes no inbound result-inspection claim.
Policy Sections
## evm
Controls EVM transaction execution, including spend limits, allowed chains, allowed actions, and consensus hold thresholds.
Token semantics: an intent carrying
token is governed only by the matching token.<SYM>.* rule. max_transaction_eth and consensus_threshold_eth are ETH-denominated and never apply to token amounts. A token intent with no matching rule, including a policy with no token rules at all, is DENIED fail-closed with SIGIL_POLICY_VIOLATION_TOKEN_NOT_ALLOWED. Symbols match case-insensitively; address-form intents match only pinned addresses. When a rule pins addresses, the intent’s targetAddress must be one of them. An ERC-20 transfer’s transaction target is the token contract, and this binding prevents a native ETH transfer labelled with a token symbol from skipping the ETH limit. Pinning addresses is strongly recommended; rules without them accept the declared symbol at face value. Amount comparisons are exact: all-digit amounts are base units compared via BigInt at the rule’s decimals, decimal amounts are scaled exactly via string math with no float rounding, and the limit itself is kept as the decimal string you wrote. A token intent whose amount is missing or unparseable is DENIED fail-closed with SIGIL_POLICY_VIOLATION_TOKEN_AMOUNT_INVALID.
## tool_calls
Controls non-EVM agent tool execution.
Recipient semantics:
email.send intents carry recipients in intent.to (string or array). Checks run in order: denylist, allowlist, approval hold. A blocked recipient is DENIED (SIGIL_POLICY_VIOLATION_BLOCKED_RECIPIENT) before any hold is created, and an off-allowlist recipient returns SIGIL_POLICY_VIOLATION_RECIPIENT_NOT_ALLOWED. Every recipient in an array must pass. A missing to while either list is declared is DENIED fail-closed. Each recipient list must contain at least one entry; empty recipient lists reject the policy. *@domain matches that exact domain only; subdomains do not match. Matching is case-insensitive.
## custom
Operator-defined rules evaluated before all other checks. Three rule types:
contains, starts_with, ends_with, equals, not_equals, matches (regex)
Allowlist semantics: allow_only is an affirmative allowlist. In 1.x it keeps exact, case-sensitive matching; in 2.0 it accepts equals (the default), starts_with/prefix, ends_with, contains, and matches operators. A missing or non-matching field is DENIED fail-closed with SIGIL_POLICY_VIOLATION_NOT_ON_ALLOWLIST. Regex patterns are capped at 256 characters; invalid patterns deny without throwing. Deny rules win: deny_if/deny_string are evaluated first, so a value matching both a deny rule and the allowlist is denied with the deny rule’s code.
An attested allowlist rule must target metadata.* and fails closed unless the request arrived through a trusted shim. require_shim: true is a block-level gate. Sign stamps provenance: agent or provenance: shim from the API-key record; the request body cannot self-assert either value. Generic require_approval patterns can appear in any policy block and match exact actions or one trailing * prefix wildcard. email.require_approval remains syntax sugar for the same durable hold class.
## mcp
MCP policy is deny-by-default unless this block exists. Sign dispatches on the mcp. action prefix and evaluates the trusted metadata values instead of splitting the action string.
allowed_tools, and mappings on ## tool_calls
are rejected. response.deny_string under ## custom is the response-specific
literal; bare deny_string continues to inspect outbound intent only. See
Policy 2.3 response controls.
## soft_limits
## soft_limits is version-gated. Under 1.x, its legacy fields remain informational metadata and do not change an authorization decision. Under 2.0, declared limits are enforced after the engine approves the matching action type or namespace, and an exceeded cap returns DENIED. Existing signed 1.x policies keep their original behavior until an operator explicitly upgrades and re-signs them. A cap on a namespace the current engine does not approve cannot make that namespace executable.
Policy format 2.0 supports legacy daily limits and named caps:
Named caps can target
mcp.* actions. The cap applies after the MCP block and base policy approve the call, and a denied or pending call does not consume aggregate budget.
The counter key combines the API key, cap name, group value, and window bucket. Sign increments counters only after the base policy approves the intent. Base-policy
DENIED and PENDING decisions do not consume aggregate budget. A missing or non-string amount_field value fails closed with SIGIL_AGGREGATE_FIELD_MISSING. Counter-store failure fails closed with SIGIL_LIMIT_STORE_UNAVAILABLE.
## execution_limits
Hard ceilings that stop runaway tool loops before the next tool executes.
Execution limits are hard denials, not soft caps. A ceiling breach returns
SIGIL_LOOP_LIMIT_EXCEEDED; if the counter store is unavailable, Sigil Sign fails closed with SIGIL_LIMIT_STORE_UNAVAILABLE. The per-task ceiling applies only when the request includes intent.task_id; the hourly ceiling applies per API key.
## signature
Ed25519 signature over all content above this block. Generated by Sigil Warrant. A missing or invalid signature causes Sigil Sign to reject the policy unconditionally at startup.
Deployment
Place your signedwarranty.md at config/warranty.md relative to process.cwd(), or set WARRANTY_PATH to its location:
Security
- The policy file is signed with your Ed25519 operator key
- The SHA-256 hash of the policy content is embedded in every Intent Attestation JWT (
policyHashclaim) - If the file is modified after signing, Sigil Sign detects it at next startup and refuses to start
- Never commit your live
warranty.mdto version control; it exposes your agent’s security policy and operational limits
config/warranty.md is gitignored by default in the sigil-sign repo.