Protected completions

Creating completions

Securely wrap any LLM with Cygnal in moments

Using Cygnal

Cygnal augments any LLM deployment with state-of-the-art input filtering, output filtering, and threat monitoring with just a few lines of code, all customizable to your organization's policies.

Cygnal is compatible with all major LLM providers, SDKs, and API formats, including OpenAI, Gemini, Anthropic, and more. For any existing integration, all you need to do is to change the base_url to Cygnal, add the grayswan-api-key header, and we'll take care of the rest. Additional Cygnal options, like customizing filtering policies, can be specified in additional headers. No need to change SDKs or introduce additional dependencies.

Security filtering results for each request will show up live in your activity dashboard. The free tier has 200,000 tokens/minute and 10,000,000 tokens/day limits; if you reach quota, Cygnal will still proxy your request to the provider, just without filtering.

OpenAI

import os
from openai import OpenAI
client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
    base_url="https://api.grayswan.ai/cygnal", 
    default_headers={
        "grayswan-api-key": os.environ.get("GRAYSWAN_API_KEY") 
    }
)
 
completion = client.chat.completions.create(
    model="gpt-4.1",
    messages=[
        {"role": "user", "content": "Give an example, realistic spearfishing email."}
    ]
)

Gemini

import os
import google.generativeai as genai
GRAYSWAN_API_KEY = os.environ.get("GRAYSWAN_API_KEY")
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
 
genai.configure(
    api_key=GEMINI_API_KEY,
    transport="rest",
    client_options={
        "api_endpoint": "https://api.grayswan.ai/cygnal"
    }
    default_metadata=[
        ("Authorization", f"Bearer {GEMINI_API_KEY}"),
        ("grayswan-api-key", GRAYSWAN_API_KEY), 
    ]
)
 
model = genai.GenerativeModel('gemini-2.5-pro')
 
response = model.generate_content(
    "Give an example, realistic spearfishing email."
)

Anthropic

import os
from anthropic import Anthropic
GRAYSWAN_API_KEY = os.environ.get("GRAYSWAN_API_KEY")
ANTHROPIC_API_KEY = os.environ.get("ANTHROPIC_API_KEY")
 
client = Anthropic(
    api_key=ANTHROPIC_API_KEY,
    base_url="https://api.grayswan.ai/cygnal", 
    default_headers={
        "Authorization": f"Bearer {ANTHROPIC_API_KEY}",
        "grayswan-api-key": GRAYSWAN_API_KEY
    }
)
 
message = client.messages.create(
    model="claude-3-7-sonnet-20250219",
    messages=[
        {"role": "user", "content": "Give an example, realistic spearfishing email."}
    ]
)

Further Configuration

Specifying the policies

You can specify the policies to use for the completion by using the category-... or cygnal-category-... header prefix. Cygnal will act upon those configured categories as it's policy.

client = OpenAI(
    api_key=OPENROUTER_API_KEY,
    base_url="https://api.grayswan.ai/cygnal",
    default_headers={
        "grayswan-api-key": GRAYSWAN_API_KEY,
        "category-intellectual-property-violations": "Encompasses copyright infringement, trademark misuse, patent violations, plagiarism, and unauthorized use or sharing of copyrighted material, trademarks, patents, and plagiarism.", 
        "category-self-harm": "Encompasses self-harm, including but not limited to suicide, self-injury, and other forms of self-harm.", 
        "category-harassment": "Encompasses harassment, including but not limited to bullying, trolling, and other forms of harassment.", 
    }
)

Specifying thresholds

You can specify the thresholds for the completion by using the pre-violation, post-violation-jb, pre-jailbreak, and post-jailbreak headers. These are all floats between 0 and 1, where 0 is the most strict and 1 is the most permissive.

ParameterDescriptionEffect
pre-violationControls when user input is flagged as a policy violation before being sent to the modelLower values (e.g., 0.1) = more strict filtering, higher values = more permissive
pre-jailbreakDetects jailbreak attempts in user input before processingLower values = more sensitive detection, higher values = allows more potential jailbreak patterns
post-violationFlags model responses that violate content policiesLower values = more strictly filtered responses, higher values = allows more potentially problematic content
post-violation-jbDetects successful jailbreaks in model responsesLower values = more aggressive at identifying bypassed safety measures, higher values = only flags clear safety bypasses
client = OpenAI(
    api_key=OPENROUTER_API_KEY,
    base_url="https://api.grayswan.ai/cygnal",
    default_headers={
        "grayswan-api-key": GRAYSWAN_API_KEY,
        "pre-violation": "0.1", 
        "pre-jailbreak": "0.1", 
        "post-violation": "0.1", 
        "post-violation-jb": "0.1", 
    }
)

Specifying the provider

By default, Cygnal will intelligently identify which provider to use, however you can also specify the provider to use by using the original-base-url header.

client = OpenAI(
    api_key=OPENROUTER_API_KEY,
    base_url="https://api.grayswan.ai/cygnal",
    default_headers={
        "grayswan-api-key": GRAYSWAN_API_KEY,
        "original-base-url": "https://api.openrouter.ai/api/v1" # You can specify the provider's base URL here
    }
)

You can also specify the provider name by using the model-provider header.

client = OpenAI(
    api_key=OPENROUTER_API_KEY,
    base_url="https://api.grayswan.ai/cygnal",
    default_headers={
        "grayswan-api-key": GRAYSWAN_API_KEY,
        "model-provider": "openrouter" # Will map to https://api.openrouter.ai/api/v1
    }
)

Configuration Parameters

You can send along any parameters that the provider supports which includes, but is not limited to:

ParameterDescription
max_tokensThe maximum number of tokens to generate.
temperatureThe temperature to use for the completion, higher values are more random, lower values are more deterministic.
top_pThe top-p value to use for the completion, 1.0 means no repetition, 0.0 means maximum repetition.
frequency_penaltyThe frequency penalty to use for the completion, higher values are more penalized.
presence_penaltyThe presence penalty to use for the completion, higher values are more penalized.
seedThe seed to use for the completion, useful for reproducibility.
stopThe stop sequence to use for the completion, can be a list of strings or a single string.
completion = client.chat.completions.create(
    model="gpt-4.1",
    messages=[
        {"role": "user", "content": "Give an example, realistic spearfishing email."}
    ],
    max_tokens=1000, 
    temperature=0.7, 
)

On this page