Action Validate

Action Validate

The action validation endpoint is a pre-execution safety check for agent frameworks. Before an AI agent runs an action — a shell command, file operation, or tool call — it sends the action here for policy evaluation and receives a risk level back. The agent decides what to do with the verdict.

This endpoint is designed for OpenHands and any agent framework that supports pluggable security analyzers. See Connecting OpenHands for the full integration guide.

Endpoint

POST /api/v1/action/validate

This endpoint is always available when the gateway is running in http or sse mode — no additional configuration is required. It uses the same CEL and AI policy engines as the MCP gateway.

Request Headers

HeaderRequiredDescription
Content-TypeYesMust be application/json
X-Maybe-Dont-Client-IDNoClient identifier for audit attribution (takes precedence over actor field)
X-Request-IDNoPer-request tracing ID (generated if missing)

Request Body

{
  "action_type": "tool_call",
  "target": "execute_bash",
  "parameters": {
    "command": "rm -rf /tmp/workspace"
  },
  "actor": "openhands-agent",
  "external_id": "42",
  "context": {
    "thought": "I need to clean up temporary files",
    "summary": "removing temporary files from workspace"
  }
}
FieldRequiredTypeDescription
targetYesstringName of the tool or action being evaluated (e.g., execute_bash, file_write, browser_action)
action_typeNostringAction category (e.g., tool_call). Informational only
parametersNoobjectStructured arguments passed to the policy engine
actorNostringAgent identity. Used as fallback client_id for audit when X-Maybe-Dont-Client-ID header is absent
external_idNostringCaller correlation ID (e.g., OpenHands action ID). Stored in the audit log
context.thoughtNostringAgent’s reasoning for the action. Injected into AI policy prompts
context.summaryNostringConcise action description. Injected into AI policy prompts

Response

The endpoint always returns HTTP 200, even when the action is denied. The allowed and risk_level fields carry the verdict.

{
  "request_id": "abc123def456",
  "allowed": false,
  "risk_level": "high",
  "message": "Action denied by policy",
  "server_version": "v1.0.0",
  "results": [
    {
      "policy_name": "no-destructive-ops",
      "policy_type": "ai",
      "action": "deny",
      "message": "Recursive rm operations are not permitted"
    }
  ]
}
FieldTypeDescription
request_idstringUnique request identifier for audit correlation
allowedbooleanWhether the action passed all policies
risk_levelstringRisk assessment: high, medium, low, or unknown
messagestringHuman-readable summary of the decision
server_versionstringGateway version
resultsarrayPer-policy evaluation results

Risk Levels

The risk_level field maps directly to OpenHands’ SecurityRisk enum:

Risk LevelConditionOpenHands Behavior
highAction denied by policyBlock the action
mediumAction would be denied, but policy is in audit-only modeWarn or prompt the user
lowAction allowed, at least one engine evaluatedProceed
unknownNo engines evaluated (no config, or all errored)OpenHands blocks by default (safe fallback)

Error Codes

CodeHTTP StatusDescription
invalid_request400Malformed request body
missing_target400Required target field is empty
invalid_content_type400Wrong Content-Type header

Error Response Format

{
  "error": "missing_target",
  "message": "Required field 'target' is empty"
}

Example: curl

curl -X POST http://localhost:8080/api/v1/action/validate \
  -H "Content-Type: application/json" \
  -d '{
    "target": "execute_bash",
    "parameters": {"command": "gh pr create --title \"Feature X\""},
    "actor": "openhands-agent",
    "context": {
      "thought": "Creating a pull request for the feature",
      "summary": "create pull request"
    }
  }'

How It Differs from MCP Validation

The MCP gateway intercepts and proxies MCP tool calls at execution time. This endpoint is different:

  • No proxying — it returns a verdict, and the caller decides what to do
  • All action types — not limited to MCP tools. Covers shell commands, file operations, browser actions, and anything else the agent can do
  • Agent context — the context.thought and context.summary fields give the AI policy engine visibility into the agent’s reasoning, not just the raw action

Audit Integration

Action validations appear in the audit log alongside MCP and CLI entries. Action entries use "source": "action" to distinguish them:

{
  "timestamp": "2025-02-04T10:30:00Z",
  "source": "action",
  "tool": {
    "name": "execute_bash",
    "arguments": {"command": "gh pr create --title \"Feature X\""}
  },
  "upstream_request": {
    "external_id": "42"
  },
  "decision": "allow",
  "duration_ms": 850
}

The external_id field correlates audit entries back to the originating agent action, making it easy to trace decisions in OpenHands’ logs.