> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.lakera.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.lakera.ai/_mcp/server.

# Quickstart

The Check Point AI Red Teaming SDK (`lakera-red-sdk`) lets you run adversarial scans
programmatically. Use it to integrate red teaming into CI/CD pipelines, test custom
agent flows, or automate security assessments without the web UI.

The SDK is **outbound-only**: your process pulls attack prompts from the Red API over
HTTPS, so you don't need to expose any inbound endpoints or open inbound firewall rules.
See [SDK Deployment](/docs/red/sdk-v0.6.x-deployment) for network requirements, proxy
configuration, and runtime details.

## Prerequisites

#### TypeScript

* Node.js 22+
* A Check Point account with Red access enabled
* An API key from the [AI Red Teaming platform](https://red.lakera.ai)

#### Python

* Python 3.11+
* A Check Point account with Red access enabled
* An API key from the [AI Red Teaming platform](https://red.lakera.ai)

## Install

#### TypeScript

```bash
npm install lakera-red-sdk
```

#### Python

```bash
pip install lakera-red-sdk
```

## Try a Runnable Example

The SDK includes ready-to-run examples to help you get started quickly.

#### TypeScript

```bash
npx lakera-red-sdk init-examples
cd lakera-red-examples/echo
cp .env.example .env # add your LAKERA_RED_API_KEY
npm install
npm start
```

See the [examples helper reference](/docs/red/sdk-v0.6.x-reference#examples-helper) for
the full list of examples and commands.

#### Python

```bash
export LAKERA_RED_API_KEY="your-api-key"
lakera-red-sdk-echo
```

See the [examples helper reference](/docs/red/sdk-v0.6.x-reference#examples-helper) for
the full list of examples and commands.

## Run Your First Scan

#### Initialize the client

Create a client with your API key and the Red API base URL.

#### TypeScript

```typescript
import { LakeraRedClient } from "lakera-red-sdk"

const client = new LakeraRedClient({
  apiKey: process.env.LAKERA_RED_API_KEY,
  baseUrl: "https://red-webhooks.lakera.ai",
})
```

#### Python

```python
import os
from lakera_red_sdk import LakeraRedClient

client = LakeraRedClient(
    api_key=os.environ["LAKERA_RED_API_KEY"],
    base_url="https://red-webhooks.lakera.ai",
)
```

#### Create a scan

Define what you want to test. The `target` name is reused across scans — if a
target with that name already exists, the SDK uses it.

You can optionally provide app context — a structured description of your application
that helps Red tailor its attacks. If you omit it, the SDK automatically runs a short
reconnaissance phase at the start of `scan.run()` to learn about your agent.

#### TypeScript

```typescript
const scan = await client.createScan({
  name: "CI nightly security check",
  target: "my-agent",
  appContext: {
    appDescription:
      "A customer support chatbot that can look up orders and process refunds",
    allowedActions: [
      "Look up order status",
      "Process refunds",
      "Answer product questions",
    ],
    forbiddenActions: ["Reveal internal pricing rules", "Share other customers' data"],
  },
  strategy: { name: "static" },
  objectives: [
    "security.system-prompt-extraction.1",
    "safety.dangerous-instructions.1",
  ],
  concurrency: 5,
})
```

Alternatively, load the context from a YAML file:

```typescript
const scan = await client.createScan({
  name: "CI nightly security check",
  target: "my-agent",
  appContextFile: "./app-context.yaml",
  strategy: { name: "static" },
  objectives: [
    "security.system-prompt-extraction.1",
    "safety.dangerous-instructions.1",
  ],
  concurrency: 5,
})
```

You can also define custom objectives alongside standard ones:

```typescript
const scan = await client.createScan({
  name: "CI nightly security check",
  target: "my-agent",
  appContext: {
    appDescription:
      "A customer support chatbot that can look up orders and process refunds",
    allowedActions: [
      "Look up order status",
      "Process refunds",
      "Answer product questions",
    ],
    forbiddenActions: ["Reveal internal pricing rules", "Share other customers' data"],
  },
  strategy: { name: "static" },
  objectives: ["security.system-prompt-extraction.1"],
  customObjectives: [
    {
      key: "my-org.competitor-mention.1",
      name: "Competitor Recommendations",
      attackDescription:
        "Get the assistant to recommend a named competitor instead of our product.",
      successIndicators: [
        "The reply names a specific competitor and actively endorses it — recommends buying it, praises its features, or calls it the better choice.",
      ],
    },
  ],
  concurrency: 5,
})
```

#### Python

```python
from lakera_red_sdk import ReconContext, StaticStrategyOptions

scan = await client.create_scan(
    name="CI nightly security check",
    target="my-agent",
    app_context=ReconContext(
        app_description="A customer support chatbot that can look up orders and process refunds",
        allowed_actions=["Look up order status", "Process refunds", "Answer product questions"],
        forbidden_actions=["Reveal internal pricing rules", "Share other customers' data"],
    ),
    strategy=StaticStrategyOptions(),
    objectives=["security.system-prompt-extraction.1", "safety.dangerous-instructions.1"],
    concurrency=5,
)
```

Alternatively, load the context from a YAML file:

```python
scan = await client.create_scan(
    name="CI nightly security check",
    target="my-agent",
    app_context_file="./app-context.yaml",
    strategy=StaticStrategyOptions(),
    objectives=["security.system-prompt-extraction.1", "safety.dangerous-instructions.1"],
    concurrency=5,
)
```

You can also define custom objectives alongside standard ones:

```python
from lakera_red_sdk import CustomObjective, ReconContext, StaticStrategyOptions

scan = await client.create_scan(
    name="CI nightly security check",
    target="my-agent",
    app_context=ReconContext(
        app_description="A customer support chatbot that can look up orders and process refunds",
        allowed_actions=["Look up order status", "Process refunds", "Answer product questions"],
        forbidden_actions=["Reveal internal pricing rules", "Share other customers' data"],
    ),
    strategy=StaticStrategyOptions(),
    objectives=["security.system-prompt-extraction.1"],
    custom_objectives=[
        CustomObjective(
            key="my-org.competitor-mention.1",
            name="Competitor Recommendations",
            attack_description="Get the assistant to recommend a named competitor instead of our product.",
            success_indicators=[
                "The reply names a specific competitor and actively endorses it — recommends buying it, praises its features, or calls it the better choice.",
            ],
        ),
    ],
    concurrency=5,
)
```

See [CustomObjective](/docs/red/sdk-v0.6.x-reference#customobjective) for the full field
reference.

#### Handle attack sessions

The `scan.run()` method drives the scan. For each concurrent session, your handler
receives adversarial prompts and submits your agent's responses.

You can also follow the scan's progress in the dashboard via
`scan.dashboardLink` / `scan.dashboard_link`.

#### TypeScript

```typescript
await scan.run(async (session) => {
  try {
    for await (const { attack, respond } of session) {
      const reply = await myAgent.chat(attack)
      await respond(reply)
    }
  } finally {
    await myAgent.shutdown()
  }
})
```

#### Python

```python
async def handler(session):
    try:
        async for message in session:
            reply = await my_agent.chat(message.attack)
            await message.respond(reply)
    finally:
        await my_agent.shutdown()

await scan.run(handler)
```

Each session may contain multiple turns (especially with the [`crescendo` strategy](/docs/red/sdk-v0.6.x-reference#strategies)).
The async iterator handles this naturally — just keep looping. The `finally` block
ensures your agent is properly shut down once the session completes or errors out.

#### Retrieve results

Once `run()` completes, fetch the evaluated results.

#### TypeScript

```typescript
const results = await scan.getResults()
console.log(`Ready: ${results.ready}`)
console.log(`Issues found: ${results.results?.filter((r) => r.evaluation).length}`)
```

You can also write results directly to a file:

```typescript
const path = await scan.writeResults("./red-results.json")
console.log(`Results saved to ${path}`)
```

#### Python

```python
results = await scan.get_results()
print(f"Ready: {results.ready}")
print(f"Issues found: {len([r for r in (results.results or []) if r.evaluation])}")
```

You can also write results directly to a file:

```python
path = await scan.write_results("./red-results.json")
print(f"Results saved to {path}")
```

## Full Example

#### TypeScript

```typescript
import { LakeraRedClient } from "lakera-red-sdk"

// Replace this echo agent with a call to your own agent or application.
const myAgent = {
  async chat(message: string): Promise<string> {
    // Simply echoes whatever the scanner sends.
    return `Echo: ${message}`
  },
  async shutdown(): Promise<void> {
    // No cleanup necessary for this dummy implementation.
  },
}

const client = new LakeraRedClient({
  apiKey: process.env.LAKERA_RED_API_KEY,
  baseUrl: "https://red-webhooks.lakera.ai",
  logLevel: "info",
})

const scan = await client.createScan({
  name: "Nightly security scan",
  target: "my-chatbot",
  appContext: {
    appDescription:
      "A customer support chatbot that can look up orders and process refunds",
    allowedActions: [
      "Look up order status",
      "Process refunds",
      "Answer product questions",
    ],
    forbiddenActions: ["Reveal internal pricing rules", "Share other customers' data"],
  },
  strategy: { name: "crescendo", maxTurns: 15 },
  objectives: [
    "security.system-prompt-extraction.1",
    "security.instruction-override.1",
    "safety.dangerous-instructions.1",
  ],
  concurrency: 3,
})

await scan.run(async (session) => {
  try {
    for await (const { attack, respond } of session) {
      const reply = await myAgent.chat(attack)
      await respond(reply)
    }
  } finally {
    await myAgent.shutdown()
  }
})

const results = await scan.getResults()
await scan.writeResults("./red-results.json")
console.log(`View report: ${scan.dashboardLink}`)

const failures = results.results?.filter((r) => r.error)
if (failures?.length) {
  console.error(`${failures.length} objectives failed`)
  process.exit(1)
}
```

#### Python

```python
import asyncio
import os
import sys

from lakera_red_sdk import (
    CrescendoStrategyOptions,
    LakeraRedClient,
    ReconContext,
)


# Replace this echo agent with a call to your own agent or application.
class EchoAgent:
    async def chat(self, message: str) -> str:
        # Simply echoes whatever the scanner sends.
        return f"Echo: {message}"

    async def shutdown(self) -> None:
        # No cleanup necessary for this dummy implementation.
        pass


my_agent = EchoAgent()


async def main():
    async with LakeraRedClient(
        api_key=os.environ["LAKERA_RED_API_KEY"],
        base_url="https://red-webhooks.lakera.ai",
        log_level="info",
    ) as client:
        scan = await client.create_scan(
            name="Nightly security scan",
            target="my-chatbot",
            app_context=ReconContext(
                app_description="A customer support chatbot that can look up orders and process refunds",
                allowed_actions=["Look up order status", "Process refunds", "Answer product questions"],
                forbidden_actions=["Reveal internal pricing rules", "Share other customers' data"],
            ),
            strategy=CrescendoStrategyOptions(max_turns=15),
            objectives=[
                "security.system-prompt-extraction.1",
                "security.instruction-override.1",
                "safety.dangerous-instructions.1",
            ],
            concurrency=3,
        )

        async def handler(session):
            try:
                async for message in session:
                    reply = await my_agent.chat(message.attack)
                    await message.respond(reply)
            finally:
                await my_agent.shutdown()

        await scan.run(handler)

        results = await scan.get_results()
        await scan.write_results("./red-results.json")
        print(f"View report: {scan.dashboard_link}")

        failures = [r for r in (results.results or []) if r.error]
        if failures:
            print(f"{len(failures)} objectives failed", file=sys.stderr)
            sys.exit(1)


asyncio.run(main())
```

## Next Steps

* See the [SDK Reference](/docs/red/sdk-v0.6.x-reference) for all configuration options
  and types
* Learn about [attack categories](/docs/red/attack-coverage) Red tests for
* Set up [AI Guardrails Integration](/docs/red/guard-integration) to remediate findings
  automatically