Skip to main content
Red teaming is the practice of attacking your own system the way an adversary would, so you find weaknesses before someone else does. For an LLM application, that means sending prompts designed to jailbreak the model, leak its system prompt, extract sensitive data, or redirect it away from its task. HiddenLayer AI Attack Simulation automates this. With the Python SDK, you can run a red team session against any target you can call from Python: a hosted model, an internal API, a chatbot behind a web UI, or an agent.

How a session works

In an SDK-driven session, HiddenLayer generates the attacks and judges the results. Your code only connects the attacker to your target.
1

You start a session

You call start_session with a name, a label for your target, and settings such as the execution strategy. HiddenLayer creates a workflow and returns a session object with a workflow_id.
2

HiddenLayer generates attack prompts

HiddenLayer produces attack prompts based on the objectives and techniques you select.
3

Your handler calls the target

For each attack prompt, the SDK calls a function you write, called the handler. The handler sends the prompt to your application or model and returns the reply as a string. The SDK submits that reply back to HiddenLayer.
4

HiddenLayer judges and reports

HiddenLayer decides whether each attack succeeded and may continue a multi-turn conversation. When the session finishes, it produces an evaluation report that you can retrieve with the SDK or view in the Console.
Because your code calls the target, HiddenLayer never needs network access to your application or credentials for it.
All AI Attack Simulation endpoints are in beta. The SDK emits a hiddenlayer.BetaWarning when you call them, including through the session helpers. Beta APIs have no compatibility guarantees, and their parameters and responses can change between SDK versions. To hide the warning, call warnings.filterwarnings("ignore", category=hiddenlayer.BetaWarning). See the Beta API FAQ.

Before you begin

  • Install the SDK and configure credentials. See Installation and Authentication and configuration.
  • Set HIDDENLAYER_CLIENT_ID and HIDDENLAYER_CLIENT_SECRET in your environment, or set HIDDENLAYER_TOKEN to a bearer token. Every example on this page reads credentials from the environment.
  • Your tenant needs access to AI Attack Simulation.
  • You need a way to call your target from Python. The examples use a placeholder function so they run without extra packages. Install whatever your real target needs, such as openai or httpx.
For your first run, use a small static prompt set (execution_strategy_type="static_prompt_set") to confirm that your handler and target work before you start a larger adaptive evaluation. See Execution strategies.

Run a session with the async client

The recommended approach uses AsyncHiddenLayer and run_with_callback_parallel, which processes several attack prompts at the same time. The SDK example notebooks use this pattern. The handler receives four arguments: It must return the target’s reply as a string.
red_team_async.py
Expected result: the script prints the workflow ID right away, then runs until HiddenLayer finishes the session. This can take several minutes. It then prints the final status, the text evaluation report, and summary counts. The session and its report also appear in the Console.
Print or log the workflow_id as soon as the session starts. If your script stops, you need it to resume, check status, or terminate the session.
This handler sends each attack prompt to an OpenAI chat model. It requires pip install openai and an OPENAI_API_KEY environment variable. It follows the SDK’s red_team_openai.ipynb notebook.
red_team_openai_handler.py
Use this handler in place of the placeholder in the main example, and pass target_model=TARGET_MODEL and target_system_prompt=TARGET_SYSTEM_PROMPT to start_session.

Control parallelism

run_with_callback_parallel(handler, max_parallel=None, poll_batch_interval=0.5) runs up to max_parallel handler calls at once. If you leave max_parallel as None, it uses the session’s max_parallel_techniques. Set it lower if your target has rate limits. If any handler call raises an exception, the SDK cancels the remaining in-flight calls and re-raises the exception. Handle expected target errors inside your handler if you want the session to continue.

start_session parameters

client.evaluation_sessions.red_team.start_session(...) accepts these keyword arguments. Defaults are the SDK defaults. Where the SDK sends nothing, the HiddenLayer service applies its own default.

Read the results

After the session completes, call client.evaluations.red_team.retrieve_evaluation_results(workflow_id). The response has workflow_id, run_id, status, and a result object with these fields:
The SDK types result.report as a plain dict, so its keys are not guaranteed. The keys used below come from the SDK example notebooks: report["summary"] with total_sessions, success_rate_pct, success_total, attempts_total, and error_total, and report["by_objective"], which maps each objective ID to a dict with success and attempts. Use .get() and check types so your code keeps working if the structure changes.
print_results.py
Run it with the workflow ID as an argument, for example python print_results.py <workflow_id>. An objective is marked FAIL if at least one attack against it succeeded.

Run a session with the sync client

If your code is not asynchronous, use HiddenLayer and run_with_callback. The handler is a regular function. The sync session processes one attack prompt at a time, so it is slower than the parallel async approach.
red_team_sync.py
Expected result: the same as the async example, but attack prompts are handled one at a time. Sessions also expose lower-level methods if you need more control: iterate_actions() yields each ready attack action, and get_next_action(block=True) returns the next one. The async session also provides get_available_actions(max_actions=10). If you use these, you must submit each target reply yourself with client.evaluations.red_team.submit_target_response(workflow_id=..., session_id=..., target_response=...). run_with_callback and run_with_callback_parallel do this for you.

Execution strategies

Set execution_strategy_type to choose how HiddenLayer builds attacks:
The exact behavioral difference between single and random is not documented in the SDK. The descriptions above follow the existing usage examples and need confirmation.
For static_prompt_set, pass a prompt set ID. The SDK example notebook mentions these built-in sets: do-anything-now-ape, financial-assistant-basic, and financial-assistant-advanced. You can also copy the ID of a prompt set you uploaded from the Console.

Monitor a session

Call client.evaluations.red_team.retrieve_status(workflow_id) to check progress, for example from a separate process or dashboard. Useful fields include:
monitor.py

Resume a session

If your script stops while a session is running, the workflow continues to exist on the HiddenLayer side. Reconnect to it with resume_session(workflow_id, *, poll_interval=2.0, poll_max_wait=None, max_parallel_techniques=None), then drive it again with your handler. If you do not pass max_parallel_techniques, the resumed session uses 1.
resume.py

Terminate a session

To stop a running session, call terminate_session(workflow_id).
Terminating a session is irreversible. The workflow stops and cannot be restarted. Confirm the workflow ID before you run this.
terminate.py
The async client provides the same method: await client.evaluation_sessions.red_team.terminate_session(workflow_id).

Timeouts

Red team sessions can run for a long time. Two separate limits apply:
  • poll_max_wait (on start_session and resume_session, default None): an overall time limit, in seconds, measured from when the session object is created. The SDK checks it while it polls for attack prompts. When exceeded, it raises a plain Exception with a message like Polling timed out after ..., not PollTimeoutError. With the default None, there is no limit.
  • wait_for_completion: after all attack prompts are handled, run_with_callback and run_with_callback_parallel call wait_for_completion() with its defaults (poll_interval=3.0, max_wait=300.0). If the workflow does not reach a terminal status within 300 seconds, it raises PollTimeoutError. If the workflow status is FAILED, it raises RedTeamSessionError with the message Workflow failed: ....
A client-side timeout does not stop the workflow on the HiddenLayer side. After a timeout, check the status with retrieve_status, fetch results later, or resume the session. You can also call session.wait_for_completion(max_wait=...) yourself with a longer limit, or max_wait=None for no limit.

Error handling

Import the session helper exceptions from hiddenlayer.lib.red_team_exceptions:
The session helpers map HTTP errors to WorkflowNotFoundError and InvalidSessionError by catching httpx.HTTPStatusError. However, the SDK client raises hiddenlayer.APIStatusError subclasses, such as hiddenlayer.NotFoundError, rather than httpx.HTTPStatusError. In practice you may receive hiddenlayer.NotFoundError or hiddenlayer.BadRequestError instead. This behavior needs confirmation. Until then, catch both RedTeamSessionError and hiddenlayer.APIStatusError, as the examples on this page do.
Also handle errors from your own target inside the handler. An unhandled exception in the handler stops run_with_callback_parallel and cancels other in-flight handler calls. See Error handling for the full SDK exception hierarchy.

Common errors and fixes

You passed an unsupported strategy name. Use one of the three lowercase values.
Check that you passed prompt_set_id. The SDK does not validate that it is present. Confirm the ID in the Console.
A parameter failed validation. A common cause is attacker_guidance that contains code, JSON, XML, markdown, or other characters outside plain sentence punctuation. Another is a severity_mapping key that is not a known objective ID. Print e.body for details.
Your handler finished, but the workflow took longer than five minutes to finalize. The workflow is still running. Call session.wait_for_completion(max_wait=...) with a longer limit, or check retrieve_status later and then fetch the results.
The poll_max_wait limit you set was exceeded. Increase it, or leave it as None. Resume the session with resume_session to continue.
HiddenLayer reported the workflow as FAILED. The message includes the error from the workflow status. Check that your handler returns meaningful strings and that your target is reachable, then start a new session.
The workflow ID is wrong, or you are connected to a different environment (region) than the one that created it.
Check your credentials and environment, and confirm that your tenant has access to AI Attack Simulation. See Authentication and configuration.

More examples

The SDK repository includes example notebooks for different kinds of targets: an OpenAI model, a custom HTTP API, a web chat UI driven by Playwright, a static prompt set, a webhook-based target, a WebSocket target, and a generic template. For more background and Console-based workflows, see: