Use evaluate-action when your agent has its own HTTP client and you want Sentrail to make the policy decision, but you handle the actual API call yourself. This is useful for custom pipelines, internal APIs, or tools not yet natively proxied.
Base URL: https://<project-ref>.supabase.co/functions/v1/evaluate-action
Required scope: evaluate
Request
POST /functions/v1/evaluate-action
Authorization: Bearer agk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
Body
| Field | Type | Required | Description |
|---|
tool | string | Yes | One of: github, linear, slack, notion, internal_api, mcp |
action | string | Yes | Action string, e.g. pull_request.create |
riskLevel | string | Yes | low, medium, high, or critical |
agentId | string | No | Agent identifier |
agentName | string | No | Human-readable agent name |
resourceType | string | No | Resource type, e.g. pull_request |
resourceId | string | No | Resource identifier, e.g. owner/repo#42 |
payload | object | No | Action payload (truncated in audit log) |
requestedBy | string | No | Who initiated the action |
curl -X POST \
"https://<project-ref>.supabase.co/functions/v1/evaluate-action" \
-H "Authorization: Bearer agk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"tool": "github",
"action": "pull_request.create",
"riskLevel": "high",
"agentId": "my-coding-agent",
"resourceType": "pull_request",
"resourceId": "owner/repo",
"payload": {
"title": "Add feature X",
"head": "feature-x",
"base": "main"
}
}'
Response
// HTTP 200
{
"ok": true,
"decision": "require_approval",
"reason": "Policy 'Require approval for PRs' matched",
"matchedPolicyId": "b3c4d5e6-f7a8-9012-bcde-f01234567890",
"approvalRequestId": "550e8400-e29b-41d4-a716-446655440000",
"auditLogId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"risk_classification": "server_classified"
}
| Field | Type | Description |
|---|
ok | boolean | Always true on 200 |
decision | string | allow, block, or require_approval |
reason | string | Human-readable explanation |
matchedPolicyId | string | null | UUID of the matched policy |
approvalRequestId | string | null | Present when decision = require_approval |
auditLogId | string | UUID of the audit log entry |
correlationId | string | UUID linking this to the full request lifecycle |
risk_classification | string | server_classified or caller_supplied — see below |
risk_classification
For github and linear tools, the risk level is always classified server-side from the action string. The caller-supplied riskLevel value is overridden and risk_classification will be "server_classified".
For all other tools (mcp, slack, notion, internal_api), the caller-supplied riskLevel is accepted as-is and risk_classification will be "caller_supplied".
gateway-proxy always classifies server-side (from the HTTP method and path) and does not call evaluate-action. The risk_classification field is most relevant when integrating evaluate-action directly in a custom pipeline.
Error responses
// HTTP 400 — invalid tool
{ "ok": false, "error": "tool must be one of github, linear, slack, notion, internal_api, mcp" }
// HTTP 400 — invalid riskLevel
{ "ok": false, "error": "riskLevel must be one of low, medium, high, critical" }
// HTTP 400 — missing action
{ "ok": false, "error": "action must be a non-empty string" }
// HTTP 401 — bad key
{ "ok": false, "error": "Invalid or expired API key" }
Status codes
| Code | Meaning |
|---|
200 | Evaluation completed (check decision field) |
400 | Invalid request body |
401 | Invalid or expired API key, or missing evaluate scope |
405 | Method not allowed (only POST is accepted) |
500 | Unexpected server error |