Skip to main content

Sandbox security, workspace, and harness primitives for AI coding agents

Project description

HarnessBox

PyPI CI License: MIT Python 3.12+

Run AI coding agents in secure sandbox environments with workspace orchestration, auto-pause, and multi-session support.

import os
from harnessbox import HarnessBox

async with HarnessBox(
    provider="e2b",
    harness="claude-code",
    secrets={
        "provider_api_key": os.getenv("E2B_API_KEY"),
        "harness_secrets": {"ANTHROPIC_API_KEY": os.getenv("ANTHROPIC_API_KEY")},
    },
) as hb:
    async for event in hb.send_message("Fix the failing test"):
        print(event.delta or "", end="")

HarnessBox is the sole public API — provision sandboxes, manage workspaces, run agent sessions. Zero runtime dependencies.

Install

pip install harnessbox

# With E2B provider
pip install "harnessbox[e2b]"

Quickstart

import os
from harnessbox import HarnessBox, GitWorkspace

hb = HarnessBox(
    provider="e2b",
    harness="claude-code",
    secrets={
        "provider_api_key": os.getenv("E2B_API_KEY"),
        "harness_secrets": {"ANTHROPIC_API_KEY": os.getenv("ANTHROPIC_API_KEY")},
    },
    workspace=GitWorkspace(
        remote="https://github.com/user/repo.git",
        branch="main",
        commit_on_exit=True,
    ),
)

sandbox_id = await hb.create()
async for event in hb.send_message("Fix the tests"):
    print(event.delta or "", end="")
await hb.kill()

How It Works

HarnessBox is a Python library. You import it, provision a sandbox, and stream agent output. That's the whole product.

from harnessbox import HarnessBox

hb = HarnessBox(provider="e2b", harness="claude-code", secrets={...})
await hb.create()

async for event in hb.send_message("Fix the failing test"):
    print(event.delta or "", end="")

await hb.kill()

Everything else is a deployment choice:

┌────────────────────────────────────────────────────────────┐
│              HarnessBox (Python SDK)                         │
│                                                             │
│  • Create workspaces and sessions                          │
│  • Stream agent output as async events                     │
│  • Auto-pause idle sandboxes, resume on next message       │
│  • Persist state across restarts (SQLite)                  │
│  • Security policies, credential guards                    │
└─────────────────────┬───────────────────┬──────────────────┘
                      │                   │
        "I'm a script │                   │ "I need a web UI
        or service"   │                   │  or team access"
                      ▼                   ▼
           ┌─────────────────┐  ┌────────────────────────────┐
           │  Use the SDK    │  │  Run `harnessbox serve`    │
           │  directly       │  │  (same SDK + HTTP/SSE)     │
           │                 │  │                            │
           │  No server.     │  │  Adds: multi-client,      │
           │  No infra.      │  │  web dashboard, shared    │
           │  Just Python.   │  │  state across consumers.  │
           └─────────────────┘  └────────────────────────────┘

Think of it like SQLite vs Postgres. SQLite is embedded — no server, works great for one process. Postgres adds a server for shared access. Same SQL, same data model, different deployment. HarnessBox works the same way.

When you don't need the server:

  • Scripts and CI pipelines
  • Single-developer tools
  • Programmatic agents (backend services)
  • Anything where one Python process is enough

When you add the server:

  • You're building a web UI for your team
  • Multiple clients (web + CLI + SDK) need to see the same workspaces
  • You want an always-on orchestrator that survives process restarts
  • You're running our hosted platform (base_url="https://api.harnessbox.dev")

Server

The server is the SDK running as a long-lived process that accepts HTTP connections. Same features, accessible over the network.

# Self-hosted
pip install "harnessbox[server]"
harnessbox serve --port 8080

# Or with Docker
docker run -p 8080:8080 harnessbox/server

Point the SDK at your server (planned for v0.4.0):

# SDK becomes a thin client — all orchestration happens server-side
hb = HarnessBox(base_url="http://localhost:8080", secrets={...})
# Same API, same streaming, same everything

Server endpoints:

  • POST /v1/workspaces — create workspace
  • GET /v1/workspaces — list workspaces
  • DELETE /v1/workspaces/{id} — destroy workspace
  • POST /v1/workspaces/{id}/prompt — send prompt (SSE stream)
  • GET /v1/workspaces/{id}/events — subscribe to live events (SSE)

Security

HarnessBox generates agent-specific deny rules and PreToolUse hook guards that protect credentials inside sandboxes:

Threat Defense
printenv / env / os.environ Bash deny rules + hook guard
Read .env, .aws/credentials Read deny rules
WebFetch exfiltration Tool deny rules
Agent spawning sub-agents Agent deny rules
/proc/self/environ Bash deny rules + hook guard
IMDS credential theft (169.254.169.254) Hook guard regex
Git credential helper leak git config credential.* deny
from harnessbox import SecurityPolicy

policy = SecurityPolicy(
    denied_tools=["WebFetch", "WebSearch", "Agent"],
    denied_bash_patterns=["rm -rf /"],
    deny_network=True,
    include_credential_guards=True,  # on by default
)

Built-in Harness Types

Harness Config Dir System Prompt CLI
claude-code .claude CLAUDE.md claude --dangerously-skip-permissions ...
codex .codex AGENTS.md codex --model o4-mini -q {prompt}
opencode .opencode AGENTS.md opencode -p {prompt}

Key Features

Feature Description
Auto-pause/resume Idle workspaces pause → $0/hr. Resume transparently on next message.
Multi-session Multiple concurrent agent sessions per workspace.
Branch-based pooling Same (remote, branch) reuses existing workspace.
Security policies Credential guards, tool deny lists, network blocking.
Git workflows Clone, commit, push on exit. Branch creation from base.
Zero dependencies Stdlib only at runtime. Provider SDKs are optional extras.
Any provider E2B, Docker, Daytona, EC2. Protocol-based extensibility.

API Reference

HarnessBox

from harnessbox import HarnessBox, HarnessBoxSecrets

hb = HarnessBox(
    provider="e2b",                    # Provider name or instance
    harness="claude-code",             # Agent harness type
    api_key="hb_live_...",             # Platform key (None = self-hosted)
    secrets=HarnessBoxSecrets(         # Or pass as dict
        provider_api_key="e2b_...",
        harness_secrets={"ANTHROPIC_API_KEY": "sk-ant-..."},
    ),
    model="claude-sonnet-4-6-20250514",
    system_prompt=Path("CLAUDE.md"),    # Path to load from file, or str for inline content
    workspace=GitWorkspace(...),
    security_policy=SecurityPolicy(...),
    setup_script="npm install",
    timeout=300,
)

# Lifecycle
sandbox_id = await hb.create()
async for event in hb.send_message("Fix tests"):
    print(event.delta)
response = await hb.send_message("Fix tests", stream=False)
result = await hb.run_command("pytest")
await hb.write_file("/workspace/f.py", "content")
content = await hb.read_file("/workspace/f.py")
await hb.kill()

# Context manager (auto create + kill)
async with HarnessBox(provider="e2b") as hb:
    async for event in hb.send_message("Hello"):
        print(event.delta)

GitWorkspace

GitWorkspace(
    remote: str,                          # HTTPS git remote URL
    *,
    branch: str = "main",
    base_branch: str | None = None,       # Branch to fork from
    commit_on_exit: bool = False,
    commit_message: str | None = None,
    clone_depth: int | None = None,
    auth_token: str | None = None,        # Never stored as env var
)

SecurityPolicy

SecurityPolicy(
    denied_tools: list[str] = [],
    denied_bash_patterns: list[str] = [],
    deny_network: bool = False,
    include_credential_guards: bool = True,
)

Project Structure

harnessbox/
  __init__.py                   # public API
  harnessbox.py                 # HarnessBox — sole public entry point
  workspace_manager.py          # internal workspace orchestration
  agent_manager.py              # internal agent lifecycle
  sandbox.py                    # internal sandbox orchestration
  workspace.py                  # Workspace protocol, GitWorkspace
  providers.py                  # SandboxProvider protocol
  lifecycle.py                  # WorkspaceState machine
  storage.py                    # StorageBackend protocol
  streaming.py                  # UniversalEvent, StreamParser
  events.py                     # EventBuffer (SSE replay)
  server.py                     # HTTP/SSE transport
  config/
    harness.py                  # HarnessTypeConfig registry
    manifest.py                 # SandboxManifest builder
  security/
    policy.py                   # SecurityPolicy, deny rules
    hooks.py                    # PreToolUse hook guard
    events.py                   # SandboxEvent, EventHandler
  _providers/
    e2b.py                      # E2B provider
  _storage/
    sqlite.py                   # SQLite backend
    memory.py                   # In-memory backend
tests/                          # 651 tests

License

MIT

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

harnessbox-0.3.0.tar.gz (187.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

harnessbox-0.3.0-py3-none-any.whl (101.1 kB view details)

Uploaded Python 3

File details

Details for the file harnessbox-0.3.0.tar.gz.

File metadata

  • Download URL: harnessbox-0.3.0.tar.gz
  • Upload date:
  • Size: 187.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for harnessbox-0.3.0.tar.gz
Algorithm Hash digest
SHA256 b50bd8f677c30bad41b13a887f7c4e34776de109f869956d6e8c957af0319dfe
MD5 a4041345dc1fe61bfe07d4376393cfde
BLAKE2b-256 4075dccad525e60686c1f6eae2b084138b31f3dbda647e1bb28c6c0daf37c9f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for harnessbox-0.3.0.tar.gz:

Publisher: publish.yml on Nikhil-Kadapala/HarnessBox

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file harnessbox-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: harnessbox-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 101.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for harnessbox-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7e6d4e2f8adf624f8c849467ba0203e6d0c952331a325304cdb7d42d6a91f560
MD5 09f90b08c398dc2fd675826d07ca36a1
BLAKE2b-256 c052483a3fef5af4e37f6d06f394054f0ba7355b1298e0ae3f9b92fb1ed187c2

See more details on using hashes here.

Provenance

The following attestation bundles were made for harnessbox-0.3.0-py3-none-any.whl:

Publisher: publish.yml on Nikhil-Kadapala/HarnessBox

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page