> 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.

# Generate Objectives from a Threat Model

Instead of picking objectives from the catalog, you can let Red derive them from your
agent's design. Red infers a topology of the agent's components from the target's ground
truth, assesses it for known weaknesses, and generates an attack objective for each
weakness. You then scan the target with those objectives.

## Prerequisites

1. A target: see [Create a Target and Scan It](/docs/red/sdk-how-tos/create-a-target)
2. The target's real system prompt and/or tool definitions
3. Agent threat modeling enabled for your organization, and the
   [preview SDK](/docs/red/sdk-preview-reference)

## Set the ground truth

The topology is inferred from the target's ground truth, so set it first. See
[GroundTruth](/docs/red/sdk-preview-reference#groundtruth) for the fields.

## Infer the topology, generate objectives, and scan

Both steps run server-side and typically finish within seconds.

#### 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",
})

const target = await client.updateTarget("target_abc123", {
  groundTruth: {
    systemPrompt:
      "You are a support assistant for Acme. Never issue refunds over $100.",
    tools: JSON.stringify([
      { name: "process_refund", description: "Issue a refund for an order" },
    ]),
  },
})

await client.inferTopology(target.targetId)

const objectives = await client.generateObjectives(target.targetId)
if (objectives.length === 0) {
  console.log("No objectives were generated for this topology")
} else {
  const scan = await client.createScan({
    name: "Threat-model scan",
    targetId: target.targetId,
    objectives: objectives.map((o) => o.key),
  })

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

  console.log(`View report: ${scan.dashboardLink}`)
}
```

#### Python

```python
import json
import os

from lakera_red_sdk import GroundTruth, LakeraRedClient


async def main():
    async with LakeraRedClient(
        api_key=os.environ["LAKERA_RED_API_KEY"],
        base_url="https://red-webhooks.lakera.ai",
    ) as client:
        target = await client.update_target(
            "target_abc123",
            ground_truth=GroundTruth(
                system_prompt="You are a support assistant for Acme. Never issue refunds over $100.",
                tools=json.dumps(
                    [{"name": "process_refund", "description": "Issue a refund for an order"}]
                ),
            ),
        )

        await client.infer_topology(target.target_id)

        objectives = await client.generate_objectives(target.target_id)
        if not objectives:
            print("No objectives were generated for this topology")
            return

        scan = await client.create_scan(
            target.target_id,
            name="Threat-model scan",
            objectives=[o.key for o in objectives],
        )

        async def handler(session):
            async for message in session:
                await message.respond(await my_agent.chat(message.attack))

        await scan.run(handler)

        print(f"View report: {scan.dashboard_link}")
```

The topology and objectives also appear on the target's profile in the dashboard.

## Re-run after the agent changes

Every `inferTopology` call infers a new topology and replaces the stored one. When you
update the ground truth, the stored topology is marked stale (`isStale` / `is_stale`)
until you call `inferTopology` again, so check it with `getTopology` / `get_topology` to
decide whether to re-run.

Each `generateObjectives` call returns only the objectives it produced. To reuse the
current set without regenerating, read it with `getGeneratedObjectives` /
`get_generated_objectives`.

## Troubleshooting

1. HTTP 403 "Agent threat modeling is not enabled for this account": ask your Check
   Point contact to enable it for your organization.
2. HTTP 409 "target has no ground truth": set it with `updateTarget` first.
3. HTTP 409 "target has no topology": call `inferTopology` before `generateObjectives`.
4. HTTP 422: inference or generation failed on the server. "The inferred topology did
   not conform to the catalog schema" means the inferred topology did not match the
   threat-modeling catalog. Retry, and check that the system prompt and tool definitions
   describe the agent.

See [Threat Modeling](/docs/red/sdk-preview-reference#threat-modeling) in the SDK
Reference for every method and type.