Skip to content

Agent self-provisioning

Let an agent request new capabilities it wasn't granted, and have a human approve the grant. It's a closed, audited loop — the agent asks, a person decides.

Cardinal rule: agents may request, never grant. There is no path for an agent to approve its own request — approval requires a human token, regardless of where the request comes from.

This is the grant-time companion to invoke-time capability policy: self-provisioning gates getting a capability; policy gates using a risky one. A self-granted tool still passes the invoke-time gate every call.

How it works

agent → request_capability(type, name, [collection], reason)
          → pending approval case (nothing granted yet)
human → approves in the queue (or `martha approvals approve`)
          → grant materializes; the tool is available next turn

Both legs are recorded in an immutable agent_privilege_audit trail (requested, approved, rejected, revoked).

Enabling it (per-agent policy)

Self-provisioning is off by default. A human turns it on per agent and bounds what's requestable. Configure it on the agent's Self-provisioning tab in the admin UI, or from the CLI:

bash
# Turn it on, set the ceiling, and allow-list what can be requested
martha agents self-grant support-bot \
  --enable \
  --scope read_only \
  --allow function:read_document \
  --allow mcp:acme/research

# Bound which collections a collection-scoped function may target
martha agents self-grant support-bot --collection-root <collection-id>

# Inspect the current policy (no flags = read)
martha agents self-grant support-bot --json
SettingMeaning
--enable / --disableMaster switch (off by default).
--scope none|read_only|read_writeRisk ceiling for what's requestable (see below).
--allow / --remove <ref>Allow-list of requestable refs: function:NAME or mcp:integration/name. Empty = nothing requestable (fail-closed).
--collection-root <id>Collection subtrees a collection-scoped function may be granted into. Empty = no collection-scoped self-grant.
--max-pending NCap on concurrently-pending requests.

Scope ceiling

The scope is checked against each capability's risk metadata:

  • read_only — only capabilities with no write-ish risk tags and non-high risk level.
  • read_write — write-ish capabilities allowed, except arbitrary_code and payment, which are never self-grantable at any scope.
  • An MCP connection with no catalog risk classification (custom/self-hosted) is treated as unclassifiable and requires read_write.

Only functions and MCP connections are self-grantable. Workflows and agent-to-agent grants are not.

Approving a request

Requests land in the standard approval queue. Each capability request shows the capability, its risk tags, the requesting AI Agent, and the agent's stated reason (rendered as unverified — judge on the metadata, not the prose).

bash
martha approvals list --status pending
martha approvals get <case-id>
martha approvals approve <case-id>      # materializes the grant
martha approvals reject  <case-id>

Approval re-validates the full policy at approve time — if the agent was disabled, the allow-list shrank, the target was deleted, or the request expired, the approval is refused and the case stays pending. Nothing is granted on a stale request.

Revoking

Revoke through the normal agent-access controls (martha agents remove-function / the MCP access controls). Revocation is next-turn (in-flight executions finish with the tools they started with) and writes a revoked audit row.

Security model

  • Principal-gated, not transport-gated. Approval requires a human token (require_human_user) on the resolve route — an agent/service-account token is rejected no matter how the request arrives.
  • Fail-closed throughout. Off by default; allow-list (not block-list); scope ceiling; arbitrary_code/payment never grantable; approve-time re-validation is the real boundary.
  • Two surfaces stay separate. A self-granted agent function does not authorize a client's workflow function-node, and vice-versa.
  • Immutable audit. Every request, approval, rejection, and revocation is recorded and cannot be edited or deleted.

Martha is built by aiaiai-pt.