Metadata-Version: 2.4
Name: anticells
Version: 0.3.0
Summary: Official Python SDK for ANTICELLS products.
Author: ANTICELLS
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://anticells.theantitech.com/
Project-URL: Documentation, https://anticells.theantitech.com/
Keywords: anticells,ai,api,gaslighter,red-team,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.26.0
Requires-Dist: pydantic<3,>=2.7.4
Requires-Dist: tqdm>=4.66.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: build>=1.2.1; extra == "dev"
Requires-Dist: twine>=5.1.0; extra == "dev"

# ANTICELLS Python SDK

Python SDK for ANTICELLS products. The Gaslighter product is available as a
namespace inside the package:

```python
from anticells import gaslighter

client = gaslighter.Client.from_env()
```

Customers normally provide only an API key.

## Install

From PyPI:

```powershell
python -m pip install anticells
```

For local development from this repository:

```powershell
python -m pip install -e .\sdk
```

For maintainers building release artifacts:

```powershell
cd sdk
python -m pip install -U build twine
python -m build
python -m twine check dist/*
```

This creates both a wheel and source distribution in `sdk/dist/`.

For a built local wheel:

```powershell
python -m pip install .\dist\anticells-0.3.0-py3-none-any.whl
```

## Environment

```powershell
$env:ANTICELLS_API_KEY = "glk_live_customer_key"
```

Optional auth header override:

```powershell
$env:ANTICELLS_API_KEY_HEADER = "X-API-Key"
```

For `Authorization: Bearer <key>` instead:

```powershell
$env:ANTICELLS_API_KEY_HEADER = "Authorization"
```

## Command Line

Check connectivity:

```powershell
anticells gaslighter health
anticells gaslighter personas
```

Manage account API keys:

```powershell
anticells gaslighter keys list
anticells gaslighter keys create --name "Notebook key"
anticells gaslighter keys revoke "key_..."
```

Register and inspect targets:

```powershell
anticells gaslighter targets list
anticells gaslighter targets get "target_..."

anticells gaslighter targets register `
  --url "http://localhost:8080/api/v1/execute" `
  --mode relay `
  --name "Production assistant" `
  --skip-manifest `
  --input-field "message" `
  --body-template '{"message":"__TARGET_INPUT__"}'
```

Run the relay from the machine that can reach a private/local target:

```powershell
anticells gaslighter relay run `
  --target "target_..." `
  --url "http://127.0.0.1:8080/api/v1/execute" `
  --target-credential "target_model_key_or_jwt" `
  --target-auth-type bearer `
  --target-auth-header "Authorization" `
  --target-auth-prefix "Bearer" `
  --input-field "message" `
  --body-template '{"message":"__TARGET_INPUT__"}'
```

Run one campaign:

```powershell
anticells gaslighter attacks run `
  --target "target_..." `
  --objective "Evaluate whether the target preserves approval boundaries." `
  --persona "audit_interface"
```

Run a family sweep:

```powershell
anticells gaslighter sweeps run `
  --target "target_..." `
  --family "system_prompt_extraction" `
  --family "tool_abuse" `
  --prompts-per-family 2
```

Run against a chatbot that has no API endpoint:

```powershell
anticells gaslighter attacks run `
  --wait `
  --objective "Evaluate whether the target preserves approval boundaries."

anticells gaslighter sweeps run `
  --wait `
  --family "system_prompt_extraction" `
  --prompts-per-family 1
```

Wait Mode creates and retains a manual target. For every generated message it
shows which chatbot conversation to use, then waits for the copied chatbot
response. Paste the full response and enter `::end` on its own line.

Interrupted sessions can be listed and resumed:

```powershell
anticells gaslighter wait list
anticells gaslighter wait resume "SESSION_ID"
```

## Quick Start

```python
from anticells import gaslighter

client = gaslighter.Client(api_key="glk_live_customer_key")

target = client.register_target(
    url="http://target-service:8080/chat",
    name="Staging assistant",
    connection_mode="sdk_relay",
    skip_manifest=True,
    target_body_template={"message": "__TARGET_INPUT__"},
    target_body_template_configured=True,
    target_input_field="message",
)

relay_runner, relay_thread, relay_stop = gaslighter.start_target_relay_thread(
    client,
    target_id=target.id,
    target_url="http://target-service:8080/chat",
    body_template={"message": "__TARGET_INPUT__"},
    body_template_configured=True,
    input_field="message",
)

try:
    result = client.attack(
        target_id=target.id,
        objective="Evaluate whether the target preserves approval boundaries.",
        persona="audit_interface",
        verbose=True,
    )
    print(result.outcome)
    print(result.judge_summary)
finally:
    relay_stop.set()
    relay_thread.join(timeout=5)
    relay_runner.close()
```

`objective`, `custom_objective`, and the API-native `bad_objective` are all
accepted. The SDK sends the API field as `bad_objective`.

## Wait Mode Without a Target API

The user still needs an ANTICELLS API key, but the chatbot being tested does
not need an HTTP endpoint:

```python
from anticells import gaslighter

client = gaslighter.Client.from_env()

result = client.attack(
    wait_mode=True,
    objective="Evaluate whether the target preserves approval boundaries.",
)
print(result.outcome)
```

Family sweeps use the same interaction and always process child campaigns
sequentially in Wait Mode:

```python
result = client.family_sweep(
    wait_mode=True,
    families=["system_prompt_extraction", "hallucination"],
    prompts_per_family=1,
)
```

At startup the SDK prints a session id. Resume an interrupted run before its
pending one-hour relay request expires:

```python
result = client.resume_wait("SESSION_ID")
sessions = client.list_wait_sessions()
```

Resume files are stored in `~/.anticells/wait-sessions`, contain prompts and
any response awaiting acknowledgement, and never contain the ANTICELLS API
key. They are removed after successful completion and retained after an
interruption or failed run. `WaitModeOptions` can override the state directory,
input/output functions, terminator, or provide a notebook-friendly
`response_reader` callback.

## Python Key Management

```python
from anticells import gaslighter

client = gaslighter.Client.from_env()

keys = client.list_api_keys()
created = client.create_api_key(name="Notebook key")
client.revoke_api_key(created["key"]["id"])
```

## Target Registration Options

`register_target` mirrors the ANTICELLS target registration contract:

```python
from anticells import gaslighter

client = gaslighter.Client.from_env()

target = client.register_target(
    url="https://target.example/chat",
    name="Production assistant",
    connection_mode="direct",
    credential="target-side-secret",
    auth={"type": "bearer", "header": "Authorization", "prefix": "Bearer"},
    skip_manifest=True,
    extra_payload={"tenant": "acme"},
    target_body_template={"query": "__TARGET_INPUT__"},
    target_body_template_configured=True,
    target_input_field="query",
    target_input_aliases=["message", "prompt"],
    upload_endpoint="/upload",
    tool_invocation_endpoint="/tools",
    file_read_endpoint="/files/read",
    upload_file_field="artifact",
    upload_message_field="note",
    upload_extra_fields={"workspace": "red-team"},
)
```

For reusable configuration objects:

```python
from anticells import gaslighter

target = client.register_target_config(
    gaslighter.RegisterTarget(url="https://target.example/chat")
)
client.update_target_config(target.id, gaslighter.UpdateTarget(credential=None))
```

Use `connection_mode="sdk_relay"` for private/local targets. In relay mode, the
SDK calls the target directly and the ANTICELLS service does not need direct
network access to it.

For bearer auth, put only the token/JWT in `credential`. Use
`{"type": "bearer", "header": "Authorization", "prefix": "Bearer"}` for
`Authorization: Bearer <token>`.

## Family Sweep

```python
from anticells import gaslighter

batch = client.family_sweep(
    target_id=target.id,
    families=["system_prompt_extraction", "tool_abuse", "hallucination"],
    prompts_per_family=2,
    direct_phase_enabled=True,
    continue_on_child_failure=True,
    verbose=True,
)

print(batch.status)
```

For full personalization:

```python
started = client.start_family_sweep_config(
    gaslighter.StartFamilySweep(
        target_id=target.id,
        persona="audit_interface",
        objective_match_mode="specified_only",
        stateful_delivery="full_history",
        max_history_turns=10,
        direct_phase_enabled=False,
        prompts_per_family=5,
        families=["system_prompt_extraction", "tool_abuse"],
        allow_weak_preflight=True,
        preflight_override_reason="Authorized audit",
        continue_on_child_failure=False,
    )
)

result = client.wait_for_batch(started.batch_id, verbose=True)
```

`families=["all"]`, `families=["*"]`, or an empty family list runs every family.

## Reports

```python
report_markdown = client.get_campaign_report(result.campaign_id, tier="growth")
saved_path = client.save_campaign_report(
    result.campaign_id,
    "reports/gaslighter-campaign.md",
    tier="growth",
)
print(saved_path)
```

The CLI can save reports too:

```bash
anticells gaslighter attacks run --target "$TARGET_ID" --objective "..." --trace --report-path reports/campaign.md
```

## Notes

- `verbose=None` auto-enables tqdm only in interactive terminals.
- `verbose=True` forces progress output.
- `verbose=False` is suitable for CI and pipeline logs.
- `X-API-Key: <key>` is the default API-key style for the ANTICELLS gateway.
- Use `api_key_header="Authorization"` if you need `Authorization: Bearer <key>`.
- Use the public ANTICELLS API URL for packaged customer builds.
- Deploy an engine version with manual-target support before using SDK Wait Mode.
