Skip to main content

Human-in-the-Loop Approvals

Agents operate autonomously, but some actions need human sign-off. 1claw's approval system lets agents request permission for sensitive operations while humans retain final control. Approvals work through the dashboard, API, or the mobile companion app.

How it works

Agent                           1claw                         Human
| | |
| POST /v1/approvals/request | |
| { action, summary, reason } | |
| ----------------------------> | |
| | Create pending approval |
| | Route to agent's creator |
| | --------------------------> |
| | |
| | Human reviews |
| | (dashboard, mobile, API) |
| | |
| | POST /v1/approvals/{id}/ |
| | decide |
| | <------------------------- |
| | |
| <-- approval result -------- | |
| (approved or denied) | |
  1. The agent creates an approval request, specifying the action, a summary, and a risk tier.
  2. 1claw routes the request to the human who registered the agent (agents.created_by).
  3. The human reviews and decides (approve or deny) through the dashboard, mobile app, or API.
  4. If the action is policy_change and the decision is approved, 1claw auto-executes the policy change.

Creating an approval request

curl -X POST https://api.1claw.xyz/v1/approvals/request \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"action": "policy_change",
"target_type": "agent",
"target_id": "'"$AGENT_ID"'",
"summary": "Request read access to secrets/production/*",
"reason": "Need production database credentials for migration task",
"risk_tier": 2
}'

Risk tiers

TierMeaningMobile app behavior
1InformationalSimple tap to approve
2Moderate riskBiometric verification required
3High riskTOTP code + countdown timer

Set the risk tier based on the sensitivity of the action. A request to read a test secret might be tier 1. A request to increase a daily spend limit should be tier 3.

Deciding an approval

# Approve
curl -X POST "https://api.1claw.xyz/v1/approvals/$APPROVAL_ID/decide" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"decision": "approved"}'

# Deny
curl -X POST "https://api.1claw.xyz/v1/approvals/$APPROVAL_ID/decide" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"decision": "denied"}'

Auto-execution on approval

When action is policy_change and the decision is approved, 1claw automatically executes the policy change described in the summary JSON. The human does not need to manually create the policy after approving.

Listing pending approvals

curl -s "https://api.1claw.xyz/v1/approvals?status=pending" \
-H "Authorization: Bearer $TOKEN" | jq '.approvals[] | {id, action, summary, risk_tier, created_at}'

Dashboard

The approval inbox is at /approvals in the dashboard. It shows:

  • Pending, approved, and denied requests
  • Risk tier badges (color-coded)
  • Agent name and the human who created the agent
  • Summary and reason text
  • Approve/Reject buttons

The sidebar shows a badge with the count of pending approvals.

Mobile companion app

The mobile app (iOS, TestFlight) provides push-notification-based approval. When an agent submits a request:

  1. The human receives a push notification
  2. Tapping opens the approval detail screen
  3. Risk tier determines the verification step:
    • Tier 1: tap "Approve"
    • Tier 2: Face ID / Touch ID
    • Tier 3: Enter TOTP code within countdown

Patterns

Agent requests access to new secrets

// Agent realizes it needs a secret it cannot access
try {
await agentClient.secrets.get(vaultId, "production/stripe-key");
} catch (err) {
if (err.status === 403) {
// Request access through the approval flow
await agentClient.approvals.request({
action: "policy_change",
target_type: "agent",
target_id: agentId,
summary: JSON.stringify({
vault_id: vaultId,
path_pattern: "production/stripe-key",
permissions: ["read"],
}),
reason: "Need Stripe key to process refunds",
risk_tier: 2,
});
}
}

Agent requests a higher spend limit

await agentClient.approvals.request({
action: "policy_change",
target_type: "agent",
target_id: agentId,
summary: JSON.stringify({
update_agent: {
tx_daily_limit_eth: "10.0",
},
}),
reason: "Portfolio rebalancing requires larger daily limit during high-volatility periods",
risk_tier: 3,
});

Gate high-value transactions on approval

For this pattern, the agent checks with its own logic before submitting a transaction:

const txValue = 5.0; // ETH
const APPROVAL_THRESHOLD = 1.0;

if (txValue > APPROVAL_THRESHOLD) {
const approval = await agentClient.approvals.request({
action: "transaction",
target_type: "transaction",
target_id: agentId,
summary: `Transfer ${txValue} ETH to 0xRecipient... on Ethereum`,
reason: "Large position exit required by strategy",
risk_tier: 3,
});

// Poll for decision (or set up a webhook)
// Only proceed if approved
}

// Submit the transaction
const tx = await agentClient.agents.submitTransaction(agentId, {
chain: "ethereum",
to: "0xRecipient...",
value: txValue.toString(),
});

Combine with treasury proposals

For multisig operations, use treasury proposals instead of approvals. Proposals collect EIP-712 signatures and auto-execute when the threshold is met. See Safe integration.

For non-multisig operations (policy changes, guardrail updates, access requests), use the approval system described here.

Webhooks

Set up a webhook to get notified when approvals are decided:

curl -X POST https://api.1claw.xyz/v1/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/1claw",
"events": ["policy.created", "policy.updated", "policy.deleted"],
"secret": "your-webhook-signing-secret"
}'

Further reading