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 turnBoth 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:
# 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| Setting | Meaning |
|---|---|
--enable / --disable | Master switch (off by default). |
--scope none|read_only|read_write | Risk 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 N | Cap 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, exceptarbitrary_codeandpayment, 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).
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/paymentnever 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.