Agent SkillsAgent Skills
jeremylongshore

perplexity-enterprise-rbac

@jeremylongshore/perplexity-enterprise-rbac
jeremylongshore
2,103
284 forks
Updated 5/5/2026
View on GitHub

Configure Perplexity API key scoping, per-team model access, cost controls, and search domain restrictions for enterprise deployments. Trigger with phrases like "perplexity enterprise", "perplexity RBAC", "perplexity team access", "perplexity roles", "perplexity permissions".

Installation

$npx agent-skills-cli install @jeremylongshore/perplexity-enterprise-rbac
Claude Code
Cursor
Copilot
Codex
Antigravity

Details

Pathplugins/saas-packs/perplexity-pack/skills/perplexity-enterprise-rbac/SKILL.md
Branchmain
Scoped Name@jeremylongshore/perplexity-enterprise-rbac

Usage

After installing, this skill will be available to your AI coding assistant.

Verify installation:

npx agent-skills-cli list

Skill Instructions


name: perplexity-enterprise-rbac description: 'Configure Perplexity API key scoping, per-team model access, cost controls,

and search domain restrictions for enterprise deployments.

Trigger with phrases like "perplexity enterprise", "perplexity RBAC",

"perplexity team access", "perplexity roles", "perplexity permissions".

' allowed-tools: Read, Write, Edit version: 1.0.0 license: MIT author: Jeremy Longshore jeremy@intentsolutions.io tags:

  • saas
  • perplexity
  • rbac compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw

Perplexity Enterprise RBAC

Overview

Control access to Perplexity Sonar API at the organizational level. Perplexity does not have built-in RBAC -- you implement access control through: separate API keys per team/environment, a gateway that enforces model and budget policies, and domain restrictions for compliance.

Access Control Strategy

LayerMechanismPerplexity Support
AuthenticationAPI key per teamYes (multiple keys)
Model restrictionGateway enforcementBuild yourself
Budget capPer-key monthly limitVia dashboard
Domain restrictionsearch_domain_filterYes (per-request)
Rate limitingGateway + key limitsYes (per-key RPM)

Prerequisites

  • Perplexity API account with admin access
  • Separate API keys per team/environment
  • Gateway or middleware for policy enforcement

Instructions

Step 1: Create Per-Team API Keys

Generate separate keys at perplexity.ai/settings/api:

Key: pplx-support-bot-prod     β†’ Budget: $200/mo, sonar only
Key: pplx-research-team        β†’ Budget: $1000/mo, sonar + sonar-pro
Key: pplx-data-team            β†’ Budget: $500/mo, sonar only
Key: pplx-executive-reports    β†’ Budget: $300/mo, sonar-pro

Step 2: Gateway with Policy Enforcement

// perplexity-gateway.ts
import OpenAI from "openai";

interface TeamPolicy {
  apiKey: string;
  allowedModels: string[];
  maxTokensPerRequest: number;
  maxRequestsPerMinute: number;
  requiredDomainFilter?: string[];  // Force search to specific domains
  blockedDomainFilter?: string[];   // Block specific domains
}

const TEAM_POLICIES: Record<string, TeamPolicy> = {
  support: {
    apiKey: process.env.PPLX_KEY_SUPPORT!,
    allowedModels: ["sonar"],
    maxTokensPerRequest: 512,
    maxRequestsPerMinute: 30,
  },
  research: {
    apiKey: process.env.PPLX_KEY_RESEARCH!,
    allowedModels: ["sonar", "sonar-pro", "sonar-reasoning-pro"],
    maxTokensPerRequest: 4096,
    maxRequestsPerMinute: 50,
  },
  compliance: {
    apiKey: process.env.PPLX_KEY_COMPLIANCE!,
    allowedModels: ["sonar", "sonar-pro"],
    maxTokensPerRequest: 2048,
    maxRequestsPerMinute: 20,
    requiredDomainFilter: ["sec.gov", "edgar.sec.gov", "law.cornell.edu"],
  },
  marketing: {
    apiKey: process.env.PPLX_KEY_MARKETING!,
    allowedModels: ["sonar"],
    maxTokensPerRequest: 1024,
    maxRequestsPerMinute: 20,
    blockedDomainFilter: ["-competitor1.com", "-competitor2.com"],
  },
};

function enforcePolicy(
  team: string,
  requestedModel: string,
  requestedTokens: number
): { client: OpenAI; model: string; maxTokens: number; domainFilter?: string[] } {
  const policy = TEAM_POLICIES[team];
  if (!policy) throw new Error(`Unknown team: ${team}`);

  if (!policy.allowedModels.includes(requestedModel)) {
    console.warn(`Team ${team} not allowed ${requestedModel}, using ${policy.allowedModels[0]}`);
  }

  const model = policy.allowedModels.includes(requestedModel)
    ? requestedModel
    : policy.allowedModels[0];

  const maxTokens = Math.min(requestedTokens, policy.maxTokensPerRequest);

  return {
    client: new OpenAI({ apiKey: policy.apiKey, baseURL: "https://api.perplexity.ai" }),
    model,
    maxTokens,
    domainFilter: policy.requiredDomainFilter || policy.blockedDomainFilter,
  };
}

Step 3: Enforced Search with Domain Restrictions

async function teamSearch(
  team: string,
  query: string,
  requestedModel: string = "sonar"
) {
  const { client, model, maxTokens, domainFilter } = enforcePolicy(
    team, requestedModel, 2048
  );

  const response = await client.chat.completions.create({
    model,
    messages: [{ role: "user", content: query }],
    max_tokens: maxTokens,
    ...(domainFilter && { search_domain_filter: domainFilter }),
  } as any);

  return {
    answer: response.choices[0].message.content,
    citations: (response as any).citations || [],
    model: response.model,
    team,
    tokens: response.usage?.total_tokens,
  };
}

// Usage
const result = await teamSearch("compliance", "latest SEC filing for AAPL", "sonar-pro");
// -> Uses sonar-pro (allowed for compliance team)
// -> Searches only sec.gov, edgar.sec.gov, law.cornell.edu

const supportResult = await teamSearch("support", "How to reset password", "sonar-pro");
// -> Downgrades to sonar (support team only allowed sonar)

Step 4: Usage Tracking per Team

class TeamUsageTracker {
  private usage: Map<string, Array<{ timestamp: number; tokens: number; model: string; cost: number }>> = new Map();

  record(team: string, tokens: number, model: string) {
    const entries = this.usage.get(team) || [];
    const cost = model === "sonar-pro" ? tokens * 0.000009 : tokens * 0.000001;
    entries.push({ timestamp: Date.now(), tokens, model, cost });
    this.usage.set(team, entries);
  }

  getDailySummary(team: string) {
    const today = new Date().toDateString();
    const entries = (this.usage.get(team) || []).filter(
      (e) => new Date(e.timestamp).toDateString() === today
    );
    return {
      team,
      queries: entries.length,
      totalTokens: entries.reduce((s, e) => s + e.tokens, 0),
      estimatedCost: entries.reduce((s, e) => s + e.cost, 0).toFixed(4),
      modelBreakdown: {
        sonar: entries.filter((e) => e.model === "sonar").length,
        "sonar-pro": entries.filter((e) => e.model === "sonar-pro").length,
      },
    };
  }
}

Step 5: Key Rotation Schedule

Rotate API keys every 90 days. Name keys with quarter (pplx-research-2026Q1) for tracking.

set -euo pipefail
# 1. Generate new key at perplexity.ai/settings/api
# 2. Deploy new key alongside old key (24-hour overlap)
# 3. Verify new key works
curl -s -o /dev/null -w "%{http_code}" \
  -H "Authorization: Bearer $NEW_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"sonar","messages":[{"role":"user","content":"test"}],"max_tokens":5}' \
  https://api.perplexity.ai/chat/completions
# 4. Remove old key from perplexity.ai/settings/api

Error Handling

IssueCauseSolution
401 for a teamKey expired or revokedRegenerate key for that team
Model downgrade unexpectedPolicy restricting accessCheck team's allowedModels
Compliance citations from wrong domainDomain filter not appliedVerify requiredDomainFilter in policy
Budget exceededTeam over monthly capAlert team lead, increase cap or throttle

Output

  • Per-team API key management
  • Gateway enforcing model and token policies
  • Domain-restricted search for compliance teams
  • Usage tracking and cost allocation per team

Resources

Next Steps

For migration planning, see perplexity-migration-deep-dive.

More by jeremylongshore

View all
environment-config-manager
2,103

managing-environment-configurations: This skill enables Claude to manage environment configurations and secrets across different deployments using the environment-config-manager plugin. It is invoked when the user needs to generate, update, or retrieve configuration settings for various environments (e.g., development, staging, production). Use this skill when the user explicitly mentions "environment configuration," "secrets management," "deployment configuration," or asks to "generate config files". It helps streamline DevOps workflows by providing production-ready configurations based on best practices.

fairdb-backup-manager
2,103

Automatically manages PostgreSQL backups with pgBackRest and Wasabi S3 storage when working with FairDB databases Activates when you request "fairdb backup manager" functionality.

git-commit-smart
2,103

generating-smart-commits: This skill generates conventional commit messages using AI analysis of staged Git changes. It automatically determines the commit type (feat, fix, docs, etc.), identifies breaking changes, and formats the message according to conventional commit standards. Use this when asked to create a commit message, write a Git commit, or when the user uses the `/commit-smart` or `/gc` command. It is especially useful after changes have been staged with `git add`.

docker-compose-generator
2,103

generating-docker-compose-files: This skill enables Claude to generate Docker Compose configurations for multi-container applications. It leverages best practices for production-ready deployments, including defining services, networks, volumes, health checks, and resource limits. Claude should use this skill when the user requests a Docker Compose file, specifies application architecture involving multiple containers, or mentions needs for container orchestration, environment variables, or persistent data management in a Docker environment. Trigger terms include "docker-compose", "docker compose file", "multi-container", "container orchestration", "docker environment", "service definition", "volume management", "network configuration", "health checks", "resource limits", and ".env files".