Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions capabilities/ai-red-teaming/agents/ai-red-teaming-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ Probe the security and safety of AI applications, agents, and foundation models.
---

Then wait for the user's request. Optional supporting skills (workflow-patterns,
attack-selection-guide, transform-reference, auth-setup-guide) are loaded lazily if
relevant — load **auth-setup-guide** when the user needs to authenticate a target,
attacker, or judge in their own cloud/environment (Azure, AWS, GCP, custom endpoints).
attack-selection-guide, transform-reference, auth-setup-guide, provisioning-and-lifecycle)
are loaded lazily if relevant: load **auth-setup-guide** when the user needs to authenticate
a target, attacker, or judge in their own cloud/environment (Azure, AWS, GCP, custom
endpoints); load **provisioning-and-lifecycle** for provisioning a bundled target
(ml-extraction-*, *-mesh), endpoint choice (/predict vs /attack), teardown/billing, and
transient-vs-fatal error recovery.
</greeting>

<critical_instructions>
Expand Down Expand Up @@ -140,6 +143,7 @@ Complete requests that don't need clarification:
- Reason about SDK internals.
- Give up after a single failure — retry with adjusted parameters.
- Use a "bash" or "shell" tool — use `execute_workflow` instead.
- Guess CLI syntax. To provision a target, ALWAYS call the `provision_environment` tool - never run `dreadnode env ...` in a shell. Public bundled targets (e.g. `ml-extraction-fraud-tabular`, `finops-mesh`) resolve by bare name; pass the bare name and do not try to qualify it.
</critical_instructions>

## Tools
Expand All @@ -164,7 +168,7 @@ The AI Red Teaming capability provides these tools:
**Multi-Agent Environments:**

- **list_environments** — List the deployable multi-agent environments (e.g. `finops-mesh`, `devsecops-mesh`, `healthcare-mesh`, `soc-mesh`) that ATLAS can target
- **provision_environment** — Deploy a hosted target and return the endpoint that matches its type. A multi-agent mesh (e.g. `finops-mesh`) returns an `/attack` URL + execute token → chain into `generate_atlas_attack`. A black-box ML classifier (e.g. `ml-extraction-mnist-image`) returns a `/predict` endpoint (plus `/pool`, `/members`, `/nonmembers`) → use `generate_evasion_attack` / `generate_extraction_attack` / `generate_membership_attack` / `generate_inversion_attack` with `api_url=<url>/predict`. **Do not fetch `/attack` on a classifier target - it does not serve it.** The sandbox is recorded and torn down automatically when the assessment completes.
- **provision_environment** — The only way to provision a target; never shell out to `dreadnode env`. Pass the task by bare name (e.g. `ml-extraction-fraud-tabular`, `finops-mesh`) - public bundled targets resolve by bare name from any workspace. Returns the endpoint that matches the target type: a multi-agent mesh returns an `/attack` URL + execute token → chain into `generate_atlas_attack`; a black-box ML classifier returns a `/predict` endpoint (plus `/pool`, `/members`, `/nonmembers`) → use `generate_evasion_attack` / `generate_extraction_attack` / `generate_membership_attack` / `generate_inversion_attack` with `api_url=<url>/predict`. **Do not fetch `/attack` on a classifier target - it does not serve it.** The sandbox is recorded and torn down automatically when the assessment completes.
- **teardown_environment** — Delete provisioned environment sandboxes to stop billing. Hosted sandboxes bill for their whole lifetime. With no id it reaps every environment provisioned this session; pass an id to reap one. Teardown also runs automatically when `update_assessment_status` marks the assessment complete, so call this only to reap early or after a partial run.

**Workflow Management:**
Expand Down
2 changes: 1 addition & 1 deletion capabilities/ai-red-teaming/capability.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
schema: 1
name: ai-red-teaming
version: "1.14.0"
version: "1.15.0"
description: >
Probe the security and safety of AI applications, agents, and foundation models.
Orchestrates adversarial attack workflows to discover vulnerabilities in LLMs,
Expand Down
25 changes: 25 additions & 0 deletions capabilities/ai-red-teaming/skills/error-troubleshooting/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,31 @@ Common errors and fixes for AIRT attack workflows.
- **Cause**: All trials errored or timed out
- **Fix**: Check for model/network errors. Reduce complexity (fewer transforms, simpler attack).

## Provisioning & Sandbox Errors

For the full lifecycle, load the `provisioning-and-lifecycle` skill.

### "Task not found" / 404 provisioning a bundled target
- **Cause**: A bare task name resolves only within the caller's org, but bundled targets (`ml-extraction-*`, `*-mesh`) live in the public `dreadnode/` catalog.
- **Fix**: Use `provision_environment` with the BARE name - it catches the 404 and retries as `<org>/<name>` automatically. Never shell out to `dreadnode env`.
- **Do NOT**: qualify a bundled task with your own org (e.g. `aisf-learner-aug-2026/ml-extraction-imdb-text`) - it is not there and there is no fallback. Use the bare name or `dreadnode/<name>`.

### "404" on GET environments/<id>/status
- **Cause**: The sandbox is already torn down or expired - you are polling a dead environment.
- **Fix**: Treat it as terminal ("terminated"), stop polling, and do not surface it as an error.

### Endpoint mismatch 404 (/attack vs /predict)
- **Cause**: Probing the wrong endpoint for the target type - e.g. fetching `/attack` on an ML classifier that only serves `/predict`.
- **Fix**: Read the `>>> NEXT STEP` line from `provision_environment`. Classifier -> `/predict`; mesh -> `/attack`. Never probe both.

### Sandbox lifecycle & billing (avoid leaks)
- **Cause**: A hosted sandbox bills for its whole lifetime; forgetting teardown leaks cost until TTL.
- **Fix**: Finish with `update_assessment_status` (auto-teardown fires on `completed` and `failed`), or call `teardown_environment()` on early abort. Set `AIRT_ENV_TEARDOWN_GRACE_SEC` >= your longest attack timeout so teardown does not kill an in-flight attack.

### Transient vs fatal (Note: vs Error:)
- **`Note:` prefix** = transient network fault (TLS/timeout/conn-reset/502-504) already auto-retried; it did not affect running or recorded work - just re-run the step, do not report failure.
- **`Error:` prefix** = a non-fatal input/tool issue - adjust params, do not blind-retry.

## Retry Strategy

1. **First failure**: Read the error message, adjust the specific parameter that failed
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
name: provisioning-and-lifecycle
description: Provision a hosted target, pick the right endpoint per target type, tear down to stop billing, and interpret transient vs fatal errors. Load this whenever the user wants to provision/attack a bundled target (ml-extraction-*, *-mesh) or asks about environments, sandboxes, teardown, or billing.
allowed-tools: provision_environment teardown_environment list_environments generate_atlas_attack generate_evasion_attack generate_extraction_attack generate_membership_attack generate_inversion_attack register_assessment update_assessment_status
---

# Provisioning and Lifecycle

How to provision a hosted target, run against the right endpoint, and tear it down cleanly. The tool layer already handles resolution, endpoint selection, retries, and teardown - your job is to use the tool (never the CLI) and interpret its output correctly.

## 1. Provisioning decision tree

- User names a bundled/hosted task (`finops-mesh`, `ml-extraction-fraud-tabular`, `ml-extraction-mnist-image`, `ml-extraction-imdb-text`) -> call `provision_environment` with the BARE name.
- User gives an HTTP URL -> skip provisioning; go straight to `generate_agentic_attack` / `generate_atlas_attack`.
- NEVER run `dreadnode env ...` in a shell, and NEVER guess a `provision`/`create` subcommand. `provision_environment` is the only supported path and it resolves the catalog for you.

## 2. Task-ref resolution

A bare name resolves server-side to a task in your org OR any public task, so bundled public targets (`ml-extraction-*`, `*-mesh`) work by bare name with no extra qualification.

- Prefer the BARE name (`ml-extraction-fraud-tabular`). It resolves to the public catalog automatically.
- A task owned by another org resolves only when it is public or owned by you. If a bare name 404s, the task is private to another org (or the name/version is wrong) - qualifying it as `<org>/<name>` will NOT help, because the same visibility rule applies.
- Do NOT qualify a bundled task with the caller's own org (e.g. `aisf-learner-aug-2026/ml-extraction-imdb-text`) - it does not live there.
- If provisioning fails, the returned message is authoritative: report it. Do not invent qualification syntax or retry random forms.

## 3. Endpoint-per-target map (fixes /attack on a /predict classifier)

Read the `>>> NEXT STEP` line in `provision_environment` output and use exactly that endpoint. Never probe both `/attack` and `/predict` on one target.

- Mesh (`*-mesh`) -> serves `/attack` -> `generate_atlas_attack` with the execute token.
- Classifier (`ml-extraction-*`, tabular/image/text, mnist/fraud/imdb) -> serves `/predict` (+ `/pool`, `/members`, `/nonmembers`) -> `generate_evasion_attack` / `generate_extraction_attack` / `generate_membership_attack` / `generate_inversion_attack` with `api_url=<url>/predict`.

## 4. Teardown and billing

Every provision bills for its whole lifetime.

- Preferred: wrap the run in `register_assessment` -> attacks -> `update_assessment_status`. The sandbox is auto-torn-down once EVERY planned attack has been recorded, whether it passed or failed.
- Gotcha: if you abandon a planned attack without recording a status (e.g. you give up after an error), the assessment never reaches terminal and the sandbox is NOT auto-torn-down - it bills until its TTL. Always either record every planned attack or call `teardown_environment()` (no id = reap every environment from this session).
- Set `AIRT_ENV_TEARDOWN_GRACE_SEC` >= your longest attack timeout before running, so assessment-completion teardown does not kill an in-flight attack.

## 5. Transient vs fatal error interpretation

- A result starting with `Note:` = transient (TLS handshake / timeout / conn reset / 502-504), already auto-retried by the tool, and it did NOT affect any running attack or recorded result. Tell the user it was transient and re-run the step.
- A result starting with `Error:` = a non-fatal input/tool issue. Adjust params; do not blind-retry.
- A `404` from probing an endpoint is exploratory, not a failure - say what you learned and switch to the correct endpoint.
- A `404` on `GET environments/<id>/status` means the sandbox is already gone (torn down or expired). Treat it as "terminated" and STOP polling - it is not an error to surface.
- Never let a raw error be the last thing the user sees about a step that actually succeeded.

## 6. ASR display

ASR is stored 0-1 internally. Never format it yourself - report what the tool returns (it renders `1.0` as `100%`). If you ever read a raw fraction from JSON, multiply by 100 before showing it.

## 7. Attribution

Assessments are attributed to the operator via the platform auth context (org / workspace) and, where available, the `origin_user` on the assessment. If a per-user field is missing on an older assessment, attribute via org/workspace and cross-reference the `assessment_id` in platform audit logs - do not claim a field that is not present.
34 changes: 27 additions & 7 deletions capabilities/ai-red-teaming/tools/environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ def list_environments() -> str:
return "\n".join(lines)


@safe_tool
def _target_kind(task_ref: str) -> str:
"""Classify a provisionable target so we return the right endpoint + guidance.

Expand Down Expand Up @@ -278,11 +277,29 @@ def provision_environment(
return "Not configured for a platform org/workspace. Run `dreadnode login` first."

model_overrides = {model_role: model} if model else None
env = TaskEnvironment(
api, org=org, workspace=workspace, task_ref=task_ref,
model_overrides=model_overrides, timeout_sec=timeout_sec,
)
ctx = _run(env.setup())

def _mk(ref: str) -> t.Any:
return TaskEnvironment(
api, org=org, workspace=workspace, task_ref=ref,
model_overrides=model_overrides, timeout_sec=timeout_sec,
)

# A bare name resolves to a task in the caller's org or any public task
# (server-side visibility rule), so bundled public targets work by bare name.
# A task owned by another org resolves only when it is public or owned by the
# caller - a private cross-org task 404s the same way whether or not it is
# qualified, so there is no client-side retry that helps; just add a hint.
env = _mk(task_ref)
try:
ctx = _run(env.setup())
except Exception as exc: # noqa: BLE001 - add a resolution hint on not-found
if not _is_not_found(exc):
raise
raise RuntimeError(
f"Task '{task_ref}' not found. A bare name resolves to a task in your org "
f"or any public task; a task owned by another org must be public or owned "
f"by you. Check the name and version, or qualify it as <org>/<name>."
) from exc
svc = (ctx.get("service_urls") or {}).get("challenge")
url = (svc.get("url") if isinstance(svc, dict) else svc) or ""
token = env._execute_token or "" # noqa: SLF001 - one-shot provision token
Expand All @@ -302,7 +319,10 @@ def provision_environment(
)
teardown_note = (
"\n>>> WHEN DONE: this sandbox bills for its whole lifetime - it is torn down "
"automatically when the assessment completes, or call teardown_environment() now."
"automatically once every planned attack is recorded (pass or fail). If you abandon "
"the run without recording all attacks, call teardown_environment() now so it does not "
"bill until its TTL. For long runs set AIRT_ENV_TEARDOWN_GRACE_SEC >= your longest "
"attack timeout so completion-teardown does not kill an in-flight attack."
)

if kind == "classifier":
Expand Down
Loading