Charter Schema Reference
A charter defines exactly what a worker can do, must ask about, and must never do. It is the core governance document for every Nooterra worker.Schema Version
Current schema version:"1.0"
Field Reference
Top-Level Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
schemaVersion | string | No | "1.0" | Charter schema version |
name | string | Yes | "" | Worker name. Validation fails if empty. |
purpose | string | Yes | "" | What this worker does (one sentence). Validation fails if empty. |
canDo | string[] | No | [] | Actions the worker can take autonomously |
askFirst | string[] | No | [] | Actions that require human approval before execution |
neverDo | string[] | No | [] | Hard restrictions — worker will refuse these |
budget | Budget | null | No | null | Spending limits |
schedule | Schedule | null | No | null | When the worker runs |
notifications | Notifications | No | See below | How to alert the human |
capabilities | Capability[] | Yes | [] | Tools/services the worker can use. Validation fails if empty. |
createdAt | string (ISO 8601) | No | Auto-generated | Creation timestamp |
updatedAt | string (ISO 8601) | No | Auto-generated | Last update timestamp |
Budget
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
amount | number | Yes | — | Maximum spend. Must be >= 0. |
currency | string | No | "USD" | Currency code |
period | string | No | "monthly" | Budget period ("monthly", "weekly", "daily", etc.) |
approvalThreshold | number | No | Same as amount | Single-spend amount above which approval is required |
Schedule
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
type | string | Yes | — | One of: "continuous", "interval", "cron", "trigger" |
value | string | null | Yes | — | Schedule value (see below) |
timezone | string | No | "UTC" | IANA timezone string |
| Type | Value | Meaning |
|---|---|---|
continuous | null | Runs 24/7 |
interval | "1h", "5m", etc. | Runs at fixed intervals |
cron | "0 9 * * *" | Standard cron expression |
trigger | "on_demand" | Runs only when triggered manually |
Notifications
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
channels | string[] | No | [] | Notification channel IDs |
events | string[] | No | ["approval_needed", "task_complete", "error"] | Events that trigger notifications |
Capability
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | Yes | — | Capability ID from the registry (e.g., "browser", "slack") |
name | string | Yes | — | Human-readable capability name |
config | object | No | {} | Capability-specific configuration |
summary | string | No | Auto-generated | Human-readable summary (generated by getCapabilitySummary) |
Validation Rules
ThevalidateCharter() function enforces:
namemust be a non-empty stringpurposemust be a non-empty stringcapabilitiesmust contain at least one entrybudget.amountmust not be negative (if budget is set)
{ valid: boolean, errors: string[] }.
Rule Inference
When you describe a task in natural language, Nooterra inferscanDo, askFirst, and neverDo rules from the task description and selected capabilities. This is done by inferCharterRules(taskDescription, capabilities).
Capability-Based Inference
Rules are inferred per capability:| Capability | canDo | askFirst | neverDo |
|---|---|---|---|
browser | Browse websites, search the web, extract content, use web_fetch and web_search tools | Fill forms or submit data | — |
slack | Read/send messages to allowed channels | Send direct messages | Post to channels not in allowed list |
email | Read emails matching criteria | Send emails (if description mentions send/reply/forward) | Delete emails permanently, share email content externally |
github | Read repo contents, create/update issues | Create pull requests, merge pull requests | Delete branches/repos, modify repo settings |
filesystem | Read files in allowed dirs; write files (if description mentions write/create/save) | — | Access outside allowed dirs, delete without instruction |
terminal | — | Execute shell commands | Execute destructive commands (rm -rf, drop), modify system config |
stripe | — | Process payments, issue refunds, modify subscriptions | Delete customer data |
postgres, sqlite | Execute read queries | Execute write queries (INSERT, UPDATE) | Execute destructive queries (DROP, TRUNCATE, DELETE without WHERE) |
calendar | Read calendar events | Create or modify events | Delete events without confirmation |
shopify | Read product/order info | Modify inventory, fulfill orders | Delete products |
webSearch | Search the web, use web_search tool | — | — |
requiresApproval: true in the registry automatically gets an askFirst rule.
Description-Based Inference
Additional rules are inferred from keywords in the task description:| Keywords | Inferred Rules |
|---|---|
monitor, watch, track, alert | canDo: Monitor data sources continuously, send alerts |
price, cost, budget, spend | askFirst: Make purchases above threshold; neverDo: Exceed budget limits |
automat, auto- | askFirst: Take actions with irreversible consequences |
Schedule Inference
TheinferSchedule(taskDescription) function infers schedule from description keywords:
| Keywords | Inferred Schedule |
|---|---|
continuous, always, 24/7, forever, constantly | { type: "continuous", value: null } |
every N hours | { type: "interval", value: "Nh" } |
every N minutes | { type: "interval", value: "Nm" } |
hourly, every hour | { type: "interval", value: "1h" } |
daily, every day, once a day | { type: "cron", value: "0 9 * * *" } |
weekly, every week, once a week | { type: "cron", value: "0 9 * * 1" } |
monitor, watch, track, alert, check, scan | { type: "interval", value: "1h" } |
morning, every morning | { type: "cron", value: "0 8 * * *" } |
when, if, trigger, on | { type: "trigger", value: "on_demand" } |
| (default) | { type: "trigger", value: "on_demand" } |
Charter Enforcement at Runtime
During execution, every tool call is classified against the charter byclassifyAction() in the worker daemon:
- Safe tools (
web_fetch,web_search,read_file,send_notification,__save_memory) are alwayscanDo— no approval needed. - neverDo rules are checked first (strictest). If all keywords in a rule appear in the action description, the action is blocked.
- askFirst rules are checked next. If matched, the action is paused pending approval.
- canDo rules are checked. If matched, the action proceeds.
- If the tool name contains a connected capability ID, it is treated as
canDo. - Default: if no rule matches, the action defaults to
askFirst(fail-safe).
"toolName argsJSON" for the rule to match.
Complete Example Charter
Serialization
serializeCharter(charter)— returns pretty-printed JSON stringparseCharter(json)— parses JSON, validates, returns{ success, charter?, errors? }