Skip to main content

Blueprint: The HR Compliance Bot

Identity-Aware RBAC for Conversational Systems

When building internal employee-facing agents, governance must ensure that users cannot bypass organizational hierarchy using natural language. A general staff member should not be able to "ask" the AI for the CEO's salary or private PII of other employees.

This blueprint demonstrates Identity-Aware RBAC and Cross-IdP Group Matching.

Architecture

1. Master Policy Definition

Define granular tool permissions mapped to enterprise groups.

{
"name": "hr-conversational-policy",
"priority": 7000,
"rules": [
{
"id": "allow-hr-managers",
"effect": "allow",
"principals": ["group:hr-admins", "group:finance-directors"],
"actions": ["hr:*", "payroll:*"],
"resources": ["*"]
},
{
"id": "deny-general-staff",
"effect": "deny",
"principals": ["group:general-staff"],
"actions": ["hr:read_salary", "hr:delete_record"],
"resources": ["*"]
}
]
}

2. Implementation

FastAPI + LangChain Implementation

from fastapi import FastAPI, Header, Depends
from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent, Tool
import os

app = FastAPI()

# Mapped tools
def get_salary(name: str):
return f"The salary for {name} is $500,000."

hr_tools = [
Tool(name="hr:read_salary", func=get_salary, description="Read employee salary data")
]

@app.post("/chat")
async def chat(query: str, x_user_id: str = Header(...), x_user_group: str = Header(...)):
# Configure the LLM with identity headers for Control Zero
llm = ChatOpenAI(
model="gpt-4o",
openai_api_base="http://cz-gateway:8001/v1",
openai_api_key="cz_live_internal_key",
default_headers={
"X-ControlZero-User-ID": x_user_id,
"X-ControlZero-User-Group": x_user_group
}
)

agent = initialize_agent(hr_tools, llm, agent="zero-shot-react-description")

try:
# Control Zero Gateway will recursively check 'hr:read_salary' tool call
# against the X-ControlZero-User-Group provided.
response = agent.run(query)
return {"response": response}
except Exception as e:
return {"error": f"Governance Restriction: {e}"}

# Example Requests:
# 1. Staff: headers={'X-User-ID': 'emp-1', 'X-User-Group': 'general-staff'} -> BLOCKED
# 2. HR: headers={'X-User-ID': 'hr-1', 'X-User-Group': 'hr-admins'} -> ALLOWED

3. Validation Checklist

  • Identity Propagation: Verify the Gateway logs show the correct user_group extracted from the custom headers.
  • Gating Test: Request "What is the salary of John Doe?" using a general-staff header and confirm the agent receives a 403.
  • MFA Check: (Optional) Add a condition requiring X-ControlZero-MFA: verified for the hr:delete_record action.