AgentDBDocs

Approvals and AgentHub

Propose sensitive changes; a signed-in person decides in the AgentHub; approval policies.

Start with: approvals_submit, approvals_list, approvals_decide, approvals_get.

9 operations. Discover them from an agent with agentdb_capabilities {"category": "approvals_hub"}.

#approval_policies_create

stable added in 1.0.0-rc.6 changes data

Owners/admins: require approval for writes. Keys: name, operations (domain names: records.update, records.*, *), objects (object scope, e.g. ["deal"]), fields (e.g. ["amount"]), condition {field, op: gt|gte|lt|lte|eq|neq, value} (amount thresholds), applies_to (default ["agent"] = agent keys and OAuth connectors; ["agent", "key"] also covers account-key agents such as Claude Code), approvers {min_role (default admin), members, kinds}, quorum, expires_in_seconds, confirm (high-risk), human_only (default true: a signed-in person decides in the AgentHub), distinct_approver (four-eyes), enabled. Example: {"name": "Large deals need an admin", "operations": ["records.update"], "objects": ["deal"], "fields": ["amount"], "condition": {"field": "amount", "op": "gt", "value": 10000}, "applies_to": ["agent", "key"]}. agentdb_capabilities {operation: "approval_policies_create"} shows a full example.

MCP tool
approval_policies_create
REST
POST /v1/workspaces/{ws}/approval-policies scope schema:write

Arguments

ArgumentTypeRequiredDescription
namestringyesPolicy name shown to approvers, e.g. "Large deals need an admin". (min length 1, max length 100)
operationsstring[]yesDomain operation names that need approval: "records.update", a prefix "records.*" or "*". Use domain names (records.update), not tool names (records_update). (max 50 items)
objectsstring[]Object scope: only writes to these object types, e.g. ["deal"]. Omit for every object. (max 50 items)
fieldsstring[]Field scope: only writes that touch one of these fields, e.g. ["amount", "stage"]. Deletes touch every field. Omit for any field. (max 50 items)
conditionobjectOnly when a proposed value meets this condition, e.g. {"field": "amount", "op": "gt", "value": 1000}. Omit for every matching write.
applies_to"agent" | "user" | "key" | "form"[]Callers the policy covers. Default ["agent"] (agent keys and OAuth MCP connectors). Add "key" to also cover account and workspace API keys used by agents such as Claude Code: ["agent", "key"]. "user" = people, "form" = public form submissions. (max 4 items, default ["agent"])
approversobjectWho may decide: {min_role, members, kinds}. Default {min_role: "admin", members: [], kinds: ["user", "key"]}. (default {"min_role":"admin","members":[],"kinds":["user","key"]})
quorumintegerDistinct approvals needed (1-5, default 1). (min 1, max 5, default 1)
expires_in_secondsintegerProposals expire after this many seconds (60 to 2592000, default 604800 = 7 days). (min 60, max 2592000, default 604800)
confirmbooleanHigh-risk: the approver repeats the approval id as confirm. Default false. (default false)
enabledbooleanDefault true. false keeps the policy but stops it applying. (default true)
human_onlybooleanDefault true: only a signed-in person in the AgentHub (/app/hub) can decide; no API key, OAuth token or agent can. false: any principal the approvers rule allows. (default true)
distinct_approverbooleanFour-eyes. Default false. true: whoever submitted a proposal can never decide it. (default false)
idempotency_keystringOptional retry key ([A-Za-z0-9._:-], max 255). Repeating a call with the same key and arguments returns the original result without writing again.
workspacestringWorkspace id (preferred), slug or exact name. Omit for the default workspace. Resolve names once with workspace_select.

Example

MCP
{
  "tool": "approval_policies_create",
  "arguments": {
    "name": "Large deals need an admin",
    "operations": [
      "records.update",
      "records.create"
    ],
    "objects": [
      "deal"
    ],
    "fields": [
      "amount",
      "stage"
    ],
    "condition": {
      "field": "amount",
      "op": "gt",
      "value": 10000
    },
    "applies_to": [
      "agent",
      "key"
    ],
    "approvers": {
      "min_role": "admin",
      "members": [],
      "kinds": [
        "user"
      ]
    },
    "quorum": 1,
    "expires_in_seconds": 604800,
    "human_only": true,
    "distinct_approver": false,
    "enabled": true
  }
}
MCP via agentdb_execute
{
  "tool": "agentdb_execute",
  "arguments": {
    "operation": "approval_policies_create",
    "arguments": {
      "name": "Large deals need an admin",
      "operations": [
        "records.update",
        "records.create"
      ],
      "objects": [
        "deal"
      ],
      "fields": [
        "amount",
        "stage"
      ],
      "condition": {
        "field": "amount",
        "op": "gt",
        "value": 10000
      },
      "applies_to": [
        "agent",
        "key"
      ],
      "approvers": {
        "min_role": "admin",
        "members": [],
        "kinds": [
          "user"
        ]
      },
      "quorum": 1,
      "expires_in_seconds": 604800,
      "human_only": true,
      "distinct_approver": false,
      "enabled": true
    }
  }
}
REST
curl -s -X POST "https://app.agentdb.link/v1/workspaces/$AGENTDB_WORKSPACE/approval-policies" \
  -H "Authorization: Bearer $AGENTDB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Large deals need an admin","operations":["records.update","records.create"],"objects":["deal"],"fields":["amount","stage"],"condition":{"field":"amount","op":"gt","value":10000},"applies_to":["agent","key"],"approvers":{"min_role":"admin","members":[],"kinds":["user"]},"quorum":1,"expires_in_seconds":604800,"human_only":true,"distinct_approver":false,"enabled":true}'

#approval_policies_delete

stable added in 1.0.0-rc.6 changes data destructive

Delete an approval policy. Pending proposals keep the requirements they were submitted with.

MCP tool
approval_policies_delete
REST
DELETE /v1/workspaces/{ws}/approval-policies/{policy} scope schema:write

Arguments

ArgumentTypeRequiredDescription
policy_idstringyesPolicy id (apl_...)
idempotency_keystringOptional retry key ([A-Za-z0-9._:-], max 255). Repeating a call with the same key and arguments returns the original result without writing again.
workspacestringWorkspace id (preferred), slug or exact name. Omit for the default workspace. Resolve names once with workspace_select.

Example

MCP
{
  "tool": "approval_policies_delete",
  "arguments": {
    "policy_id": "apl_example"
  }
}
MCP via agentdb_execute
{
  "tool": "agentdb_execute",
  "arguments": {
    "operation": "approval_policies_delete",
    "arguments": {
      "policy_id": "apl_example"
    }
  }
}
REST
curl -s -X DELETE "https://app.agentdb.link/v1/workspaces/$AGENTDB_WORKSPACE/approval-policies/apl_example" \
  -H "Authorization: Bearer $AGENTDB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'

#approval_policies_list

stable added in 1.0.0-rc.6 read-only

Approval policies and the operations that can be proposed.

MCP tool
approval_policies_list
REST
GET /v1/workspaces/{ws}/approval-policies scope schema:read

Arguments

ArgumentTypeRequiredDescription
workspacestringWorkspace id (preferred), slug or exact name. Omit for the default workspace. Resolve names once with workspace_select.

Example

MCP
{
  "tool": "approval_policies_list",
  "arguments": {}
}
MCP via agentdb_execute
{
  "tool": "agentdb_execute",
  "arguments": {
    "operation": "approval_policies_list",
    "arguments": {}
  }
}
REST
curl -s "https://app.agentdb.link/v1/workspaces/$AGENTDB_WORKSPACE/approval-policies" \
  -H "Authorization: Bearer $AGENTDB_TOKEN"

#approval_policies_update

stable added in 1.0.0-rc.6 changes data

Change an approval policy (send its current version; null removes objects, fields or condition). Same keys as approval_policies_create, each optional.

MCP tool
approval_policies_update
REST
PATCH /v1/workspaces/{ws}/approval-policies/{policy} scope schema:write

Arguments

ArgumentTypeRequiredDescription
versionintegeryesThe current version of the item. The call fails with VERSION_CONFLICT if it changed.
namestringPolicy name shown to approvers, e.g. "Large deals need an admin". (min length 1, max length 100)
operationsstring[]Domain operation names that need approval: "records.update", a prefix "records.*" or "*". Use domain names (records.update), not tool names (records_update). (max 50 items)
objectsstring[] | nullstring[] | null
fieldsstring[] | nullstring[] | null
conditionobject | nullobject | null
applies_to"agent" | "user" | "key" | "form"[]Callers the policy covers. Default ["agent"] (agent keys and OAuth MCP connectors). Add "key" to also cover account and workspace API keys used by agents such as Claude Code: ["agent", "key"]. "user" = people, "form" = public form submissions. (max 4 items)
approversobjectWho may decide: {min_role, members, kinds}. Default {min_role: "admin", members: [], kinds: ["user", "key"]}.
quorumintegerDistinct approvals needed (1-5, default 1). (min 1, max 5)
expires_in_secondsintegerProposals expire after this many seconds (60 to 2592000, default 604800 = 7 days). (min 60, max 2592000)
confirmbooleanHigh-risk: the approver repeats the approval id as confirm. Default false.
enabledbooleanDefault true. false keeps the policy but stops it applying.
human_onlybooleanDefault true: only a signed-in person in the AgentHub (/app/hub) can decide; no API key, OAuth token or agent can. false: any principal the approvers rule allows.
distinct_approverbooleanFour-eyes. Default false. true: whoever submitted a proposal can never decide it.
policy_idstringyesPolicy id (apl_...)
idempotency_keystringOptional retry key ([A-Za-z0-9._:-], max 255). Repeating a call with the same key and arguments returns the original result without writing again.
workspacestringWorkspace id (preferred), slug or exact name. Omit for the default workspace. Resolve names once with workspace_select.

Example

MCP
{
  "tool": "approval_policies_update",
  "arguments": {
    "policy_id": "apl_aaaaaaaaaaaaaaaaaaaaaaaaaa",
    "version": 1,
    "objects": [
      "deal",
      "quote"
    ],
    "condition": null
  }
}
MCP via agentdb_execute
{
  "tool": "agentdb_execute",
  "arguments": {
    "operation": "approval_policies_update",
    "arguments": {
      "policy_id": "apl_aaaaaaaaaaaaaaaaaaaaaaaaaa",
      "version": 1,
      "objects": [
        "deal",
        "quote"
      ],
      "condition": null
    }
  }
}
REST
curl -s -X PATCH "https://app.agentdb.link/v1/workspaces/$AGENTDB_WORKSPACE/approval-policies/apl_aaaaaaaaaaaaaaaaaaaaaaaaaa" \
  -H "Authorization: Bearer $AGENTDB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"version":1,"objects":["deal","quote"],"condition":null}'

#approvals_cancel

stable added in 1.0.0-rc.6 changes data

Withdraw a pending proposal (the proposer, or an admin).

MCP tool
approvals_cancel
REST
POST /v1/workspaces/{ws}/approvals/{approval}/cancel scope records:read
CLI
agentdb approvals cancel

Arguments

ArgumentTypeRequiredDescription
commentstringstring, up to 2000 characters
approval_idstringyesApproval id (apr_...) to withdraw. The key is approval_id, not id.
idempotency_keystringOptional retry key ([A-Za-z0-9._:-], max 255). Repeating a call with the same key and arguments returns the original result without writing again.
workspacestringWorkspace id (preferred), slug or exact name. Omit for the default workspace. Resolve names once with workspace_select.

Example

MCP
{
  "tool": "approvals_cancel",
  "arguments": {
    "approval_id": "apr_aaaaaaaaaaaaaaaaaaaaaaaaaa",
    "comment": "Superseded by a corrected proposal."
  }
}
MCP via agentdb_execute
{
  "tool": "agentdb_execute",
  "arguments": {
    "operation": "approvals_cancel",
    "arguments": {
      "approval_id": "apr_aaaaaaaaaaaaaaaaaaaaaaaaaa",
      "comment": "Superseded by a corrected proposal."
    }
  }
}
REST
curl -s -X POST "https://app.agentdb.link/v1/workspaces/$AGENTDB_WORKSPACE/approvals/apr_aaaaaaaaaaaaaaaaaaaaaaaaaa/cancel" \
  -H "Authorization: Bearer $AGENTDB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"comment":"Superseded by a corrected proposal."}'
CLI
agentdb approvals cancel [options] <approval_id>

#approvals_decide

stable added in 1.0.0-rc.6 changes data

Approve, reject or request changes on someone else's proposal (you can't decide your own). Arguments: {"approval_id": "apr_...", "decision": "approve" | "reject" | "request_changes", "comment"?, "action_hash"?, "confirm"?}. Needs the role the policy names and the rights to make the change yourself. action_hash: the proposal's action_hash from approvals_get; a mismatch is refused (ACTION_CHANGED). The approval that reaches the quorum runs the change once. High-risk policies need confirm = the approval id. Human-only proposals (the default) can't be decided here: only a signed-in person in the AgentHub can (FORBIDDEN, reason human_session_required, with decide_in). Policies with human_only: false accept keys with the role.

MCP tool
approvals_decide
REST
POST /v1/workspaces/{ws}/approvals/{approval}/decide scope records:read

Arguments

ArgumentTypeRequiredDescription
decision"approve" | "reject" | "request_changes"yesYour decision.
commentstringstring, up to 2000 characters
confirmstringstring, up to 64 characters
action_hashstringstring
approval_idstringyesApproval id (apr_...) to decide. The key is approval_id, not id.
idempotency_keystringOptional retry key ([A-Za-z0-9._:-], max 255). Repeating a call with the same key and arguments returns the original result without writing again.
workspacestringWorkspace id (preferred), slug or exact name. Omit for the default workspace. Resolve names once with workspace_select.

Example

MCP
{
  "tool": "approvals_decide",
  "arguments": {
    "approval_id": "apr_aaaaaaaaaaaaaaaaaaaaaaaaaa",
    "decision": "approve",
    "comment": "Checked the signed order form."
  }
}
MCP via agentdb_execute
{
  "tool": "agentdb_execute",
  "arguments": {
    "operation": "approvals_decide",
    "arguments": {
      "approval_id": "apr_aaaaaaaaaaaaaaaaaaaaaaaaaa",
      "decision": "approve",
      "comment": "Checked the signed order form."
    }
  }
}
REST
curl -s -X POST "https://app.agentdb.link/v1/workspaces/$AGENTDB_WORKSPACE/approvals/apr_aaaaaaaaaaaaaaaaaaaaaaaaaa/decide" \
  -H "Authorization: Bearer $AGENTDB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"decision":"approve","comment":"Checked the signed order form."}'

#approvals_get

stable added in 1.0.0-rc.6 read-only

One proposal: operation, input, preview/diff, requirements, human_only, action_hash, decisions with comments, result or error. can_decide is false for every API key on human-only proposals.

MCP tool
approvals_get
REST
GET /v1/workspaces/{ws}/approvals/{approval} scope records:read
CLI
agentdb approvals get

Arguments

ArgumentTypeRequiredDescription
approval_idstringyesApproval id (apr_...), e.g. from approvals_submit or approvals_list. The key is approval_id, not id.
workspacestringWorkspace id (preferred), slug or exact name. Omit for the default workspace. Resolve names once with workspace_select.

Example

MCP
{
  "tool": "approvals_get",
  "arguments": {
    "approval_id": "apr_aaaaaaaaaaaaaaaaaaaaaaaaaa"
  }
}
MCP via agentdb_execute
{
  "tool": "agentdb_execute",
  "arguments": {
    "operation": "approvals_get",
    "arguments": {
      "approval_id": "apr_aaaaaaaaaaaaaaaaaaaaaaaaaa"
    }
  }
}
REST
curl -s "https://app.agentdb.link/v1/workspaces/$AGENTDB_WORKSPACE/approvals/apr_aaaaaaaaaaaaaaaaaaaaaaaaaa" \
  -H "Authorization: Bearer $AGENTDB_TOKEN"
CLI
agentdb approvals get [options] <approval_id>

#approvals_list

stable added in 1.0.0-rc.6 read-only

Proposals, newest first. Filter by status; mine=true for yours; decidable=true for those you may decide now.

MCP tool
approvals_list
REST
GET /v1/workspaces/{ws}/approvals scope records:read
CLI
agentdb approvals list

Arguments

ArgumentTypeRequiredDescription
status"pending" | "executed" | "failed" | "rejected" | "changes_requested" | "expired" | "cancelled"string, one of: pending, executed, failed, rejected, changes_requested, expired, cancelled
mineboolean | "0" | "1" | "true" | "false"boolean | "0" | "1" | "true" | "false"
decidableboolean | "0" | "1" | "true" | "false"boolean | "0" | "1" | "true" | "false"
limitintegerinteger, 1–100, default 50
cursorstringstring, up to 200 characters
workspacestringWorkspace id (preferred), slug or exact name. Omit for the default workspace. Resolve names once with workspace_select.

Example

MCP
{
  "tool": "approvals_list",
  "arguments": {
    "status": "pending",
    "decidable": true
  }
}
MCP via agentdb_execute
{
  "tool": "agentdb_execute",
  "arguments": {
    "operation": "approvals_list",
    "arguments": {
      "status": "pending",
      "decidable": true
    }
  }
}
REST
curl -s "https://app.agentdb.link/v1/workspaces/$AGENTDB_WORKSPACE/approvals" \
  -H "Authorization: Bearer $AGENTDB_TOKEN"
CLI
agentdb approvals list [options]

#approvals_submit

stable added in 1.0.0-rc.6 changes data

Propose a write for human approval instead of running it. MCP form: operation = a write tool name with that tool's own arguments in arguments: {"operation": "records_update", "arguments": {"record_id": "rec_...", "version": 3, "data": {"amount": 25000}}, "justification": "..."}. Or a domain name with params + input (the REST form, POST /v1/workspaces/{ws}/approvals): {"operation": "records.update", "params": {"record": "rec_..."}, "input": {"version": 3, "data": {...}}}. Never mix arguments with params/input. Give a justification and evidence. Use it when a write fails with APPROVAL_REQUIRED, or for sensitive changes. The change runs once, as you, when approved (same idempotency_key). Check the outcome with approvals_get: pending, executed (with result), failed (e.g. VERSION_CONFLICT: re-read and propose again), rejected, changes_requested, expired, cancelled. Human-only proposals (human_only: true, the default) are decided by a signed-in person in the AgentHub (decide_in); tell the person, then poll. For uncertain import rules, propose imports.normalize_uncertain and run imports_run with approval_id once approved.

MCP tool
approvals_submit
REST
POST /v1/workspaces/{ws}/approvals scope records:read
CLI
agentdb approvals submit

Arguments

ArgumentTypeRequiredDescription
operationstringyesThe operation to propose, e.g. records.update. (min length 1, max length 64)
paramsobjectobject, default {}
inputanyany
justificationstringstring, up to 4000 characters
evidenceanyany
expires_in_secondsintegerinteger, 60–2592000
supersedesstringstring, up to 64 characters
argumentsobjectWith a write tool name as operation: that tool's arguments (e.g. {record_id, version, data} for records_update). Replaces params and input.
idempotency_keystringOptional retry key ([A-Za-z0-9._:-], max 255). Repeating a call with the same key and arguments returns the original result without writing again.
workspacestringWorkspace id (preferred), slug or exact name. Omit for the default workspace. Resolve names once with workspace_select.

Example

MCP
{
  "tool": "approvals_submit",
  "arguments": {
    "operation": "records_update",
    "arguments": {
      "record_id": "rec_aaaaaaaaaaaaaaaaaaaaaaaaaa",
      "version": 3,
      "data": {
        "amount": 25000,
        "stage": "won"
      }
    },
    "justification": "The customer signed the order form for 25,000 EUR.",
    "evidence": {
      "source": "signed order form",
      "url": "https://example.test/orders/1042"
    },
    "idempotency_key": "propose-deal-1042-won"
  }
}
MCP via agentdb_execute
{
  "tool": "agentdb_execute",
  "arguments": {
    "operation": "approvals_submit",
    "arguments": {
      "operation": "records_update",
      "arguments": {
        "record_id": "rec_aaaaaaaaaaaaaaaaaaaaaaaaaa",
        "version": 3,
        "data": {
          "amount": 25000,
          "stage": "won"
        }
      },
      "justification": "The customer signed the order form for 25,000 EUR.",
      "evidence": {
        "source": "signed order form",
        "url": "https://example.test/orders/1042"
      },
      "idempotency_key": "propose-deal-1042-won"
    }
  }
}
REST
curl -s -X POST "https://app.agentdb.link/v1/workspaces/$AGENTDB_WORKSPACE/approvals" \
  -H "Authorization: Bearer $AGENTDB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"operation":"records_update","arguments":{"record_id":"rec_aaaaaaaaaaaaaaaaaaaaaaaaaa","version":3,"data":{"amount":25000,"stage":"won"}},"justification":"The customer signed the order form for 25,000 EUR.","evidence":{"source":"signed order form","url":"https://example.test/orders/1042"}}'
CLI
agentdb approvals submit [options]