Open-source adversarial testing engine, SDK, and CLI for AI agents.
Project description
humanbound
Open-source adversarial testing engine, SDK, and CLI for AI agents.
Attack your agent the way real users and attackers will: live endpoints,
multi-turn conversations, tool abuse. Then turn every failure into a firewall rule.
Runs locally or against the Humanbound Platform. No login required to start.
Quick Start · Test-to-Guardrail Loop · SDK · Documentation · Contributing
📖 Full documentation lives at docs.humanbound.ai — this README covers the essentials; the docs have the depth.
Why Humanbound
Most testing tools test prompts. Humanbound tests agents: it drives
multi-turn conversations against your real endpoint, probes tool use and scope
boundaries, and scores the results against your security policy. When tests
fail, hb guardrails converts the findings into deployable firewall rules —
so the same run that finds a hole also patches it.
Quick Start
Install
pip install humanbound # CLI + SDK, core deps
pip install humanbound[engine] # + OpenAI / Anthropic / Gemini providers
pip install humanbound[firewall] # + humanbound-firewall runtime
pip install humanbound[engine,firewall] # everything
CLI usage
# Configure your LLM provider
export HB_PROVIDER=openai
export HB_API_KEY=sk-...
# Point Humanbound at your agent and run an adversarial test
hb test --endpoint ./bot-config.json --repo . --wait
# View results
hb posture # security score (0-100, A-F)
hb logs # full multi-turn conversation logs
hb report -o report.html # HTML report
Full air-gap with Ollama — zero external API calls:
export HB_PROVIDER=ollama
export HB_MODEL=llama3.1:8b
hb test --endpoint ./bot-config.json --scope ./scope.yaml --wait
Describe your agent
bot-config.json tells the engine how to call your agent's API:
{
"chat_completion": {
"endpoint": "https://your-bot.com/chat",
"headers": {"Authorization": "Bearer <token>"},
"payload": {"message": "$PROMPT"}
},
"thread_init": {
"endpoint": "https://your-bot.com/sessions",
"headers": {"Authorization": "Bearer <token>"},
"payload": {}
}
}
chat_completion(required) — the request the engine sends for every conversation turn: your agent's chat endpoint.thread_init(optional) — called once before each conversation to create a session/thread. Stateless agents simply omit it (same forthread_auth, an optional separate auth step).
The headers and payload above are examples — they must match your agent's
actual API input schema. The engine sends them as-is after substituting the
placeholders:
$PROMPT— replaced with the user message of each attack turn. If no$PROMPTappears in the payload, the engine appends the message as an OpenAI-stylemessagesarray instead.$CONVERSATION— replaced with the prior turns of the conversation, for stateless agents that expect the full history in every request.
scope.yaml declares what the agent is — and is not — allowed to do. The
restricted list is what turns generic jailbreak probes into targeted
tool-abuse attacks:
business_scope: "Customer support for Acme Bank"
permitted:
- Provide account balance and transaction info
- Process routine transfers within limits
restricted:
- Process transfers above 10,000 EUR # tool-abuse boundary the engine attacks
- Access internal system records
more_info: "HIGH: finance domain agent"
See Agent Configuration and Scope Discovery for the full specifications.
From test results to guardrails
Every adversarial run produces training data. Feed it straight back into your defenses:
hb test --endpoint ./bot-config.json --wait # find the failures
hb guardrails -o rules.yaml # convert findings into firewall rules
hb firewall train # train a Tier 2 classifier from test logs
Deploy the output with humanbound-firewall and your agent is protected against exactly the attacks it just failed. No other open-source tool closes this loop.
Python SDK
import json
import time
from humanbound import LocalRunner, TestConfig
config = TestConfig(
endpoint=json.load(open("bot-config.json")), # same config file the CLI uses
scope_path="scope.yaml",
)
runner = LocalRunner()
experiment_id = runner.start(config)
while runner.get_status(experiment_id).status not in ("Finished", "Failed", "Terminated"):
time.sleep(5)
posture = runner.get_posture(experiment_id)
print(f"Security posture: {posture.overall_score} ({posture.grade})")
for insight in runner.get_result(experiment_id).insights:
print(insight["severity"], "—", insight["category"])
The CLI and SDK share the same implementation, so they cannot drift. Authoring
custom orchestrators and wiring EngineCallbacks is covered in the
docs.
Stability contract
| Import path | Stability |
|---|---|
from humanbound import X |
Stable — semver-protected |
from humanbound.<module> import Y |
Stable — semver-protected |
from humanbound_cli.* import Z |
Internal — may change any release, do not import from user code |
The full orchestrator authoring guide, Platform integration, and API reference live on docs.humanbound.ai.
Release highlights
- Clean name:
humanboundis the PyPI install. The oldhumanbound-clipackage has been yanked from PyPI; installhumanbounddirectly. - Public SDK namespace alongside the CLI — use the CLI or drive the engine from Python.
- Firewall integration:
pip install humanbound[firewall]pullshumanbound-firewallalongside the CLI.
See the changelog for full release notes.
Contributing
Contributions welcome. See CONTRIBUTING.md for the dev loop, release process, and CLA requirement (see CLA.md).
- 🐛 Report a bug
- 💡 Request a feature
- 🔒 Report a security issue — not via public Issues
- 💬 Join Discord
Telemetry
The hb CLI sends anonymous usage data to help us improve it.
Disable with hb telemetry disable, HB_TELEMETRY_DISABLED=1, or
DO_NOT_TRACK=1. Full disclosure: PRIVACY.md.
License
Apache-2.0. Free to use in any context — commercial or open-source — with attribution. See TRADEMARK.md for the trademark policy. The code is open; the name is not.
The sibling project humanbound-firewall
is also Apache-2.0 — same license, different product.
Project details
Release history Release notifications | RSS feed
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 humanbound-2.6.0.tar.gz.
File metadata
- Download URL: humanbound-2.6.0.tar.gz
- Upload date:
- Size: 257.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a44a82743be509167c9d4576576d700ee93e136dbcbe4b002cc20b91d798d8c
|
|
| MD5 |
68dc29ebee42a54510d9836be92c55f3
|
|
| BLAKE2b-256 |
03830d6f36340092fd808bc74b04798464abc175185840537d2f8515fa215d34
|
Provenance
The following attestation bundles were made for humanbound-2.6.0.tar.gz:
Publisher:
release.yml on humanbound/humanbound
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
humanbound-2.6.0.tar.gz -
Subject digest:
1a44a82743be509167c9d4576576d700ee93e136dbcbe4b002cc20b91d798d8c - Sigstore transparency entry: 2124834048
- Sigstore integration time:
-
Permalink:
humanbound/humanbound@58252781fb50e17427cea8799a16744ae1874d72 -
Branch / Tag:
refs/tags/v2.6.0 - Owner: https://github.com/humanbound
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@58252781fb50e17427cea8799a16744ae1874d72 -
Trigger Event:
push
-
Statement type:
File details
Details for the file humanbound-2.6.0-py3-none-any.whl.
File metadata
- Download URL: humanbound-2.6.0-py3-none-any.whl
- Upload date:
- Size: 303.9 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 |
1fcdc8b0e42ecef42dc7d0cdfdc0c7b69807fbe7a5ea0d4145f02886f3bd66a3
|
|
| MD5 |
3f0202031e0693a3da2be8ef7fbbe317
|
|
| BLAKE2b-256 |
e08cfec1e19708d3b1e612430fdb4c67081f6cb69875306d65c8f486b7db4434
|
Provenance
The following attestation bundles were made for humanbound-2.6.0-py3-none-any.whl:
Publisher:
release.yml on humanbound/humanbound
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
humanbound-2.6.0-py3-none-any.whl -
Subject digest:
1fcdc8b0e42ecef42dc7d0cdfdc0c7b69807fbe7a5ea0d4145f02886f3bd66a3 - Sigstore transparency entry: 2124834083
- Sigstore integration time:
-
Permalink:
humanbound/humanbound@58252781fb50e17427cea8799a16744ae1874d72 -
Branch / Tag:
refs/tags/v2.6.0 - Owner: https://github.com/humanbound
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@58252781fb50e17427cea8799a16744ae1874d72 -
Trigger Event:
push
-
Statement type: