Skip to content

Requests and policy ​

A request asks a person something: an approval (ask_approval) or an open question (ask_human). The policy decides which agent actions need one.

Requests ​

A request goes to the project's active channels, email or Telegram, or to the ones named in approvers. The person answers from the message or from a one-time link.

StatusMeaning
pendingNot answered yet
approvedApproved as asked
deniedRefused
modifiedThe person picked one of your options, in decision
needs_contextThe person wants more information; any note is in comment
answeredAn ask_human question was answered
expiredNo answer within expires_in (default 24h): treat it as not approved

The call waits up to wait_seconds (default 45, max 120) for the answer. After that it returns pending, and the answer arrives later in three ways:

  • request_status({request_id}), any time;
  • a request.resolved event in the inbox, with request_id, status, decision, comment and state_ref, unless the request has a callback_url;
  • a signed POST of that event to callback_url instead, if the request has one (create the signing secret first with POST /v1/request-callback-secret).

Put the id of your saved task state in state_ref: whoever handles the request.resolved event can resume the work with state_load. At most 50 requests can be pending in a project at once.

Channels ​

A channel is an email address or a Telegram chat. The owner's email is the first channel. channel_add adds another one; it needs the person to confirm it (the email link, or Start in the Telegram bot) and then the approval of the project's active channels. An agent cannot add a channel that answers its own requests.

Policy ​

The policy is a list of rules, checked from the top; the first rule whose conditions all hold decides.

json
{
  "rules": [
    { "id": "no-big-refunds", "match": { "action": "refund", "amount_gt": 500 }, "effect": "deny" },
    { "match": { "action": "refund", "amount_lte": 50 }, "effect": "auto_approve_notify" },
    { "match": { "tool": "email_send", "to_domain_not_in": ["acme.example"] }, "effect": "require_approval" }
  ]
}

Conditions, all optional: tool, action, risk, agent, platform (a value or a list), to_domain_in, to_domain_not_in (lists of domains), amount_lte, amount_gt. A condition on a value the call does not carry never holds.

EffectWhat happens
allowThe action goes ahead
denyemail_send and file_url fail with POLICY_DENIED; an ask_approval comes back denied
require_approvalA person decides; approvers picks the channels
auto_approveApproved without asking anyone
auto_approve_notifyApproved, and the channels are told; approvers picks who is told

The policy applies to ask_approval, email_send and file_url. With no matching rule, ask_approval goes to people (so does allow), and email_send and file_url go ahead. ask_human always goes to people.

policy_get reads the policy. policy_set proposes a new one: every active channel sees the whole document, and the policy changes only when a person approves. No rule can approve a policy change, so an agent cannot widen its own permissions. Up to 100 rules and 16 KB.

CLI and skill released under the MIT License.