Policies & Approval
Policies control which requests are auto-approved and which require human approval. When approval is required, approvers can respond via Telegram (one-tap buttons) or passkey (Face ID, fingerprint, YubiKey). Policies are configured per-credential through the admin dashboard, API, or CLI.
Configuring Policies
Set a policy via the admin API:
curl -X PUT https://proxy.toolsec.org/admin/policies/slack \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"auto_approve_methods": ["GET", "HEAD"],
"require_approval_methods": ["POST", "PUT", "DELETE"],
"auto_approve_urls": ["/conversations.list", "/users.list"]
}'View the current policy for a credential:
curl https://proxy.toolsec.org/admin/policies/slack \
-H "Authorization: Bearer $SESSION_TOKEN"On managed hosting, the dashboard shows policy status at a glance for each credential.
Policy Evaluation Order
When a request arrives, the proxy evaluates policy rules in this order:
- URL patterns — if the target URL contains any
auto_approve_urlssubstring, auto-approve regardless of HTTP method - Method rules — if the HTTP method is in
auto_approve_methods, auto-approve. HEAD follows GET policy - Require approval — if the method is in
require_approval_methods, require human approval - Default — if the method isn’t in either list, require approval (fail closed)
For example, a policy for slack with auto_approve_methods: ["GET"], require_approval_methods: ["POST", "PUT", "DELETE"], and auto_approve_urls: ["/conversations.list", "/users.list"] means POST /conversations.list is auto-approved (URL pattern match), but POST /chat.postMessage requires approval (method rule).
No Policy = Fail Closed
If a credential has no policy configured, all requests require approval. This is intentional — you must explicitly opt in to auto-approval.
Approval Channels
When a request requires approval, the proxy routes it to the configured approval channel. The proxy blocks until an approver responds or the timeout expires (default 5 minutes, configurable via AGENTSEC_APPROVAL_TIMEOUT_SECS).
Telegram
The default approval channel. The proxy sends a message to your Telegram chat with:
- Agent name and credential being used
- HTTP method and target URL
- Request body preview
- Approve and Deny inline buttons
Passkey (WebAuthn)
For hardware-backed approval via Face ID, fingerprint, or YubiKey. When passkey approval is configured for a credential, the Telegram message includes a secure URL. The approver opens the link, authenticates with their passkey, and the request is approved.
Approvers register their own passkeys the first time they receive an approval request — no admin setup needed. Passkeys are persisted across restarts.
Long-Polling (Default)
The proxy polls Telegram’s getUpdates API with a 30-second server-side timeout. This works behind firewalls and NAT without exposing a public URL.
Webhook Mode
For production deployments with a public URL, you can configure Telegram webhooks via the Telegram Bot API. The proxy handles callbacks at POST /telegram/webhook.
Per-Credential Approval Routing
You can restrict who can approve requests and route approval messages to different Telegram chats per credential.
curl -X PUT https://proxy.toolsec.org/admin/policies/production-db \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"require_approval_methods": ["GET", "POST", "PUT", "DELETE"],
"allowed_approvers": ["123456789", "987654321"],
"telegram_chat_id": "-100999888777"
}'allowed_approvers
A list of Telegram user IDs. When set:
- Only listed users can tap Approve/Deny
- Other users who tap the buttons get an “unauthorized” alert
- Empty list (default) = anyone in the chat can approve
Per-credential chat_id
Overrides the global TELEGRAM_CHAT_ID for this credential’s approval messages. Useful for routing sensitive credentials to a restricted channel.
You can also configure notification channels per team via the admin API:
curl -X POST https://proxy.toolsec.org/admin/notification-channels \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"channel_type": "telegram", "name": "ops-alerts", "config": {"chat_id": "-100123456789"}}'Rate Limiting
Per-agent rate limiting is configured when creating an agent:
# Via admin API
curl -X POST https://proxy.toolsec.org/admin/agents \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "my-agent", "rate_limit_per_hour": 100}'
# Via CLI (self-hosted)
tap agent create --name my-agent --rate-limit 100 \
--db agentsec.db --encryption-key $AGENTSEC_ENCRYPTION_KEYWhen the limit is exceeded, the proxy returns 429 Too Many Requests. Rate limits reset on a rolling 1-hour window. Omit the rate limit for unlimited requests.