Skip to main content

Contextual Security Policies (CSP)

Contextual Security Policies (CSP) are Zihin's policy engine for AI agents — the layer that provides runtime governance over what an agent is allowed to do. A CSP is a named, versioned policy resource, scoped and inherited across tenant → team → agent → user, that the runtime applies on every execution.

CSPs act through two distinct mechanisms:

  • Runtime enforcement — behavior guardrails such as a tool blocklist (must_not_tools), iteration and token caps, and human approval gates are enforced in the agent loop itself, not merely suggested to the model.
  • Contextual injection — schedule, data, and origin rules are injected into the prompt-building process so the agent operates within them.

Policy Types​

TypeDescription
scheduleTime-based restrictions (allowed hours, days)
behaviorAgent behavior rules (tone, must_do, must_not)
dataData access restrictions (sensitive fields, entities)
originRequest origin restrictions (IPs, domains)
customCustom rules (flexible JSON)

Scopes​

Policies are inherited from broader to narrower scope. More specific scopes override broader ones.

tenant → team → agent → user
ScopeDescription
tenantApplies to entire tenant
teamApplies to a specific team
agentApplies to a specific agent
userApplies to a specific user

Authentication​

MethodAccess
JWT (Authorization: Bearer <jwt> + x-tenant-id)RBAC by user role
API Key (X-Api-Key: YOUR_API_KEY)RBAC by API key role
RBAC Enforcement

Both JWT and API Key are subject to the same role-based permission check. The role determines which operations are allowed (e.g., editor can read and create but cannot delete CSPs). See API Keys - Role System for the full permission matrix.


GET /api/csp​

List all CSPs for the tenant.

Query Parameters:

ParamTypeDescription
scopestringFilter by scope
policy_typestringFilter by type
is_activebooleanFilter active only
scope_target_idUUIDFilter by target ID

Response:

{
"data": [
{
"id": "uuid",
"name": "Business Hours Only",
"policy_type": "schedule",
"scope": "tenant",
"rules": {
"allowed_hours": { "start": "08:00", "end": "18:00" }
},
"is_active": true,
"priority": 10
}
],
"total": 5
}

GET /api/csp/effective​

Get effective CSPs for a context, resolving the inheritance hierarchy.

Query Parameters:

ParamTypeDescription
team_idUUIDTeam context
agent_idUUIDAgent context
user_idUUIDUser context

Response:

{
"data": [
{ "id": "uuid", "name": "Tenant Rules", "policy_type": "behavior", "scope": "tenant" },
{ "id": "uuid", "name": "Agent Rules", "policy_type": "data", "scope": "agent" }
],
"resolution_chain": ["tenant", "agent"]
}

GET /api/csp/:id​

Get CSP by ID.

POST /api/csp​

Create a new CSP.

Request Body:

{
"name": "Business Hours Only",
"policy_type": "schedule",
"scope": "tenant",
"rules": {
"allowed_hours": { "start": "08:00", "end": "18:00" },
"allowed_days": ["monday", "tuesday", "wednesday", "thursday", "friday"],
"timezone": "America/Sao_Paulo"
},
"is_active": true,
"priority": 10
}

PUT /api/csp/:id​

Update a CSP (partial update).

PATCH /api/csp/:id/toggle​

Toggle CSP active status.

DELETE /api/csp/:id​

Delete a CSP.


Policy Rule Examples​

Schedule Policy​

{
"policy_type": "schedule",
"rules": {
"allowed_hours": { "start": "08:00", "end": "18:00" },
"allowed_days": ["monday", "tuesday", "wednesday", "thursday", "friday"],
"timezone": "America/Sao_Paulo"
}
}

Behavior Policy​

{
"policy_type": "behavior",
"rules": {
"tone": "professional",
"language": "pt-BR",
"must_do": ["greet_user", "confirm_before_delete", "provide_sources"],
"must_not": ["share_competitor_data", "execute_without_confirmation"],
"max_iterations": 10,
"must_not_tools": ["dangerous_tool"],
"max_tokens_per_request": 4096
}
}

Behavior Guardrails (runtime enforcement)​

The following behavior rules are runtime-enforced — applied in the agent loop itself, not just injected into the prompt. must_not_tools acts as a tool blocklist, preventing named tools from ever being called even if the model plans to use them (mitigating tool injection via a compromised plan):

FieldEffect
max_iterationsLimits the number of agent loop iterations
must_not_toolsTool blocklist — blocks specific tools from being called by the agent
max_tokens_per_requestLimits max tokens per LLM request

These guardrails are extracted from the behavior policy and propagated to the agent loop configuration.

Data Policy​

{
"policy_type": "data",
"rules": {
"sensitive_fields": ["cpf", "cnpj", "password"],
"mask_pattern": "[REDACTED]",
"never_expose": ["api_key", "secret_token"],
"restricted_entities": ["Competitor Inc"],
"restriction_message": "You don't have access to this data."
}
}

Origin Policy​

{
"policy_type": "origin",
"rules": {
"allowed_origins": ["https://app.zihin.ai", "https://*.zihin.ai"],
"blocked_origins": ["http://*"],
"allowed_ips": ["192.168.1.0/24"],
"reason": "Only HTTPS origins allowed"
}
}

Action Approvals​

Action approvals elevate human-in-the-loop from a static per-tool flag to a governance rule plus approval by another user, mediated by the agent inside the conversation. When a sensitive action is triggered, the agent pauses and asks a designated approver to sign off before the action runs.

Native chat only

Action approvals apply only in the native chat (chat.zihin.ai). For the operator-facing walkthrough of the approval flow, see Agents → Action Approvals.

Configuration has two parts: a trigger in the behavior policy that declares which tools need approval, and an approval policy that declares who approves.

Trigger: require_approval_for​

Add require_approval_for inside the behavior policy. It is an array whose items are either a plain tool name (string) or an object selecting a group of tools. Any tool that matches requires approval before it runs.

{
"policy_type": "behavior",
"rules": {
"behavior": {
"require_approval_for": [
"create_deal",
{ "tool_name": "send_invoice" },
{ "mcp_server_id": "erp-protheus" },
{ "source": "db" }
],
"approval_policy_id": "b1a2c3d4-..."
}
}
}
Item formMatches
"create_deal" (string)The tool with that exact name
{ "tool_name": "..." }The named tool
{ "mcp_server_id": "..." }All tools exposed by that MCP server (precise)
{ "source": "mcp" }All MCP tools (precise)
{ "source": "api" | "db" }The underlying schema tools for that source
Fail-safe matching

source: mcp matches precisely. For source: api and source: db, matching resolves to the underlying schema tools and errs toward over-approving — if in doubt, it will ask for approval rather than skip it.

Link one approval policy per scope with approval_policy_id (referencing an approval policy described below).

Approval policies​

An approval policy is a tenant-owned resource that decides who approves. A policy has stages, and each stage lists approvers.

{
"name": "Finance sign-off",
"stages": [
{
"type": "approval",
"approvers": [
{ "type": "user", "id": "b1a2c3d4-..." },
{ "type": "role", "role": "admin" }
]
}
]
}
Approver formResolves to
{ "type": "user", "id": "<uuid>" }That specific user
{ "type": "role", "role": "<role>" }Every tenant user with that role
Supported today

Configure a single stage (its type must be "approval") with any-one-approver semantics — when any listed approver decides, the decision applies. Multi-stage approvals, requiring more than one approval (min_approvals > 1), and timeouts are reserved in the schema for the future and are not active yet.

The member → member flow​

  1. A user chats with an agent and triggers a matching (sensitive) action.
  2. The agent pauses and delivers an approval card to the approver's own chat session, with a push notification. The approver may be a different user (e.g. a manager).
  3. The approver approves or declines in their chat.
  4. On approval, the action runs outside the agent loop with its arguments frozen; the result flows back to the original requester (receipt + push).

Safe by default​

  • A policy with no valid approver blocks the action with a clear message — never a zombie card that nobody can resolve.
  • Sensitive argument keys are redacted in the card.
  • The pending-approvals list is scoped by role: a regular member sees only their own; admin/owner see all.
  • Decisions are atomic — the first decision wins.

Endpoints​

EndpointMethodPermissionDescription
GET /api/v1/approvalsGETsessions:approve-actionPending-approvals list (kanban). Scoped by role — member sees only their own. Optional status filter: awaiting_user (default), approved, rejected, expired, or all
GET /api/v1/approval-policiesGETcsp:readList approval policies
POST /api/v1/approval-policiesPOSTcsp:createCreate an approval policy
PUT /api/v1/approval-policies/:idPUTcsp:updateUpdate an approval policy

All endpoints accept hybrid authentication (JWT or API Key).