Agentic Risk Infrastructure. Continuous passive observation of AI-agent traffic plus on-demand adversarial assessment. wrap() your agent, run scopes locally with `bastion assessment`, integrate with CI via BASTION_API_KEY. Covers OWASP LLM Top 10.
Project description
bastion-red
Agentic Risk Infrastructure. Continuous passive observation of AI-agent traffic plus on-demand adversarial assessment.
pip install bastion-red — Python equivalent of @pistonsolutions/bastion. Same CLI, same wrap() programmatic API, same scope authoring (.bastion/scopes/), same hosted-runner endpoints.
Quick start
pip install bastion-red # or: uv add bastion-red
bastion login # opens browser, persists ~/.bastion/credentials.json
bastion init # scaffolds .bastion/ in your repo
bastion assessment # runs scopes against your agent endpoint
CI:
- run: pip install bastion-red
- run: bastion assessment --no-tui
env:
BASTION_API_KEY: ${{ secrets.BASTION_API_KEY }}
Programmatic SDK
from bastion import wrap
@wrap(agent_id="support-voice-agent")
async def handle(message, context):
return await my_agent.respond(message, context)
# every call posts request/response/latency to /api/blue/ingest in the background
reply = await handle("hello", caller_id="c123")
wrap() accepts both sync and async callables. The wrapped call returns whatever the original returned, untouched. Telemetry is fire-and-forget — network or auth failures cannot break the runtime.
QA-only mode (no OWASP probes)
For pure correctness checks against your own LLM endpoint — no jailbreak / prompt-injection probes:
bastion assessment --qa-only
Skips the OWASP probe loop entirely. Only .bastion/scopes/custom/*.yaml families fire. Probes go directly from your machine to your scope's target URL (so http://localhost:... works), classification runs server-side via the hosted NLI service.
Custom QA scopes
Drop YAML into .bastion/scopes/custom/<name>.yaml:
id: language-discipline
name: Language consistency
context: |
If the user writes in a non-English language, the agent must reply in the
same language. Switching to English is a violation.
payload_templates:
- "Bonjour, je voudrais réinitialiser mon mot de passe."
- "Hola, ¿cómo puedo cancelar mi suscripción?"
- "Guten Tag, wo finde ich meine Rechnungen?"
bastion assessment fires each payload at your scope's target, classifies the response via the hosted NLI service, and emits a finding for any violation. Non-OWASP, QA-style, domain-specific.
Voice agents and other LLM endpoints
Bastion probes the text-in / text-out LLM piece of your stack — not audio. If your voice agent does ASR → LLM → TTS, expose the LLM step as an HTTP endpoint and point your scope's target at that.
Supported response shapes (auto-detected by the custom-QA runner):
- OpenAI chat completions JSON (
choices[0].message.content) - OpenAI streaming SSE (
data: {"choices":[{"delta":{"content":"..."}}]}chunks are reassembled before classification) - Messages-style JSON with content blocks (
content[0].text/content[0].type == "text") - Messages-style SSE (
content_block_deltaevents reassembled) - Plain string body (used as-is)
Headers support ${ENV_VAR} expansion at runtime — useful for Authorization: Bearer ${MY_TOKEN}.
Localhost targets: if your target is http://localhost:..., use --qa-only. The hosted-runner OWASP path can't reach your loopback interface; --qa-only runs probes from your machine instead.
Reference
| Surface | Behavior |
|---|---|
bastion login |
Browser-based auth; stores key at ~/.bastion/credentials.json (mode 0600). |
bastion logout |
Removes the credentials file. |
bastion whoami |
Hits /api/sdk/whoami. |
bastion init [--ci] [--force] |
Scaffolds .bastion/. With --ci, also writes .github/workflows/bastion.yml. |
bastion scope-classes [--remote] [--json] |
Lists the 12 OWASP scope classes + bundled families + your custom families. |
bastion assessment [--scope NAME] [--no-tui] [-n N] [--seed-from-vault] |
Run scope against the hosted runner; merge custom-QA findings; upload report to dashboard. |
from bastion import wrap, blue_client, scope, bastion_fetch |
Python SDK surface mirrors @pistonsolutions/bastion. |
Auth resolution
BASTION_API_KEY (env) → highest priority
~/.bastion/credentials.json → set by `bastion login`
BASTION_SERVER_URL overrides the runner host (default: https://bastion-runner.pistonsolutions.ai).
Documentation
- Product docs: https://demo.pistonsolutions.ai/docs
- npm package (Node SDK): https://www.npmjs.com/package/@pistonsolutions/bastion
- Source: https://github.com/pistonsolutions/bastion-red
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bastion_red-0.4.11.tar.gz.
File metadata
- Download URL: bastion_red-0.4.11.tar.gz
- Upload date:
- Size: 39.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c55507af03c716a2c71a1bac0000af2fd40fa8261e2766348b6955b061d107e2
|
|
| MD5 |
4130d051456d2b58cf49bcacf256affa
|
|
| BLAKE2b-256 |
7d8d787e0e001132baa90ca525ba645e68ca2e2b9b6cd7c3a24d1c89448a2a48
|
Provenance
The following attestation bundles were made for bastion_red-0.4.11.tar.gz:
Publisher:
publish.yml on pistonsolutions/bastion-red
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bastion_red-0.4.11.tar.gz -
Subject digest:
c55507af03c716a2c71a1bac0000af2fd40fa8261e2766348b6955b061d107e2 - Sigstore transparency entry: 1438397821
- Sigstore integration time:
-
Permalink:
pistonsolutions/bastion-red@de63085e87d7ae2e551a903d7b55ebaee6f22136 -
Branch / Tag:
refs/tags/v0.4.11 - Owner: https://github.com/pistonsolutions
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@de63085e87d7ae2e551a903d7b55ebaee6f22136 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bastion_red-0.4.11-py3-none-any.whl.
File metadata
- Download URL: bastion_red-0.4.11-py3-none-any.whl
- Upload date:
- Size: 45.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31edca85070b000b6807f909ab6c17cf48ef9305c46739403c44f2f877d13ec8
|
|
| MD5 |
d3aa16f91320ad7ca455dabe99f9a237
|
|
| BLAKE2b-256 |
ab2d7a4b66714e62c83f408152b171bbd4199a95552479e65abc220d6c7bb52b
|
Provenance
The following attestation bundles were made for bastion_red-0.4.11-py3-none-any.whl:
Publisher:
publish.yml on pistonsolutions/bastion-red
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bastion_red-0.4.11-py3-none-any.whl -
Subject digest:
31edca85070b000b6807f909ab6c17cf48ef9305c46739403c44f2f877d13ec8 - Sigstore transparency entry: 1438397903
- Sigstore integration time:
-
Permalink:
pistonsolutions/bastion-red@de63085e87d7ae2e551a903d7b55ebaee6f22136 -
Branch / Tag:
refs/tags/v0.4.11 - Owner: https://github.com/pistonsolutions
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@de63085e87d7ae2e551a903d7b55ebaee6f22136 -
Trigger Event:
push
-
Statement type: