Skip to main content

OS-enforced sandbox backend for LangChain Deep Agents using Landlock (Linux) and Seatbelt (macOS)

Project description

nono logo

OS-enforced sandbox backend for LangChain Deep Agents using nono.

Run Langchain DeepAgents with python native, kernel-enforced sandboxing.

Installation

pip install langchain-nono

Usage

import json

from deepagents import create_deep_agent
from langchain_nono import NonoSandbox
from nono_py import ProxyConfig, RouteConfig

sandbox = NonoSandbox(
    working_dir="/tmp/agent-workspace",
    proxy_config=ProxyConfig(
        allowed_hosts=["api.openai.com"],
        routes=[
            RouteConfig(
                prefix="/openai",
                upstream="https://api.openai.com",
                credential_key="openai-key",
            )
        ],
    ),
    block_network=True,
)

agent = create_deep_agent(
    backend=sandbox,
    system_prompt="You are a coding assistant.",
)

Configuration

sandbox = NonoSandbox(
    working_dir="/tmp/agent-workspace",     # Required: read-write access
    allow_read=["/data/models"],            # Additional read-only paths
    allow_readwrite=["/tmp/scratch"],        # Additional read-write paths
    policy_json=json.dumps({                # Optional: nono policy JSON
        "groups": {
            "project_rw": {
                "description": "RW access to a project directory",
                "allow": {"readwrite": ["/tmp/agent-workspace"]}
            }
        }
    }),
    policy_groups=["project_rw"],           # Groups to resolve from policy_json
    proxy_config=ProxyConfig(               # Optional: host filtering + credential injection
        allowed_hosts=["api.openai.com"],
    ),
    snapshot_session_dir="/tmp/nono-session",  # Optional: enable snapshots + rollback
    block_network=True,                     # Block outbound network (default)
    timeout=300,                            # Default command timeout in seconds
)

Network Filtering

Pass proxy_config=ProxyConfig(...) to start the nono proxy when the sandbox is created. execute() automatically receives the proxy environment variables, so host filtering and credential injection apply to sandboxed child processes without extra wiring in the caller.

from nono_py import InjectMode, ProxyConfig, RouteConfig

sandbox = NonoSandbox(
    working_dir="/tmp/agent-workspace",
    proxy_config=ProxyConfig(
        allowed_hosts=["api.openai.com"],
        routes=[
            RouteConfig(
                prefix="/openai",
                upstream="https://api.openai.com",
                credential_key="openai-key",
                inject_mode=InjectMode.HEADER,
            )
        ],
    ),
    block_network=True,
)

events = sandbox.drain_network_audit_events()
sandbox.shutdown_proxy()

Snapshots

Pass snapshot_session_dir=... to enable content-addressable snapshots and rollback for the sandbox workspace.

from nono_py import ExclusionConfig

sandbox = NonoSandbox(
    working_dir="/tmp/agent-workspace",
    snapshot_session_dir="/tmp/nono-session",
    snapshot_exclusion=ExclusionConfig(exclude_patterns=["node_modules"]),
)

baseline = sandbox.create_snapshot_baseline()
manifest, changes = sandbox.create_snapshot_incremental()
restored = sandbox.restore_snapshot(0)

Examples

Inline policy for an agent that can write in its workspace, read a reference folder, and is denied access to a sibling secrets folder because that path is never granted:

python examples/01_policy_inline.py

Policy loaded from a JSON file with the same workspace/reference split, plus an explicit deny.access rule for the secrets folder on macOS:

python examples/02_policy_from_file.py

Policy-aware upload_files() and download_files() with user-facing error messages instead of raw backend error codes:

python examples/03_policy_file_transfer.py

The matching policy document is:

examples/policy_example.json

How it works

Each execute() call:

  1. Forks the current process
  2. Applies OS-level sandbox restrictions in the child (Landlock or Seatbelt)
  3. Exec's the command
  4. Captures stdout/stderr and waits for exit

The parent process remains unsandboxed and can call execute() repeatedly. Sandbox restrictions are enforced by the kernel and cannot be bypassed from userspace.

Platform support

Platform Mechanism Minimum version
Linux Landlock LSM Kernel 5.13+
macOS Seatbelt macOS 10.15+

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

langchain_nono-0.1.0.tar.gz (186.6 kB view details)

Uploaded Source

Built Distribution

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

langchain_nono-0.1.0-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

File details

Details for the file langchain_nono-0.1.0.tar.gz.

File metadata

  • Download URL: langchain_nono-0.1.0.tar.gz
  • Upload date:
  • Size: 186.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for langchain_nono-0.1.0.tar.gz
Algorithm Hash digest
SHA256 af58bce90217795c4cc44f9beab239ef77ef92289fccd976d50c8ba9c63f0e93
MD5 de26507d373da1affa84602367970667
BLAKE2b-256 c17766cc09f4b32f19a8e51babbe2f00ad3a8aeb9be2226515417518e9aacc6e

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_nono-0.1.0.tar.gz:

Publisher: publish.yml on always-further/langchain-nono

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

File details

Details for the file langchain_nono-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: langchain_nono-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for langchain_nono-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3169c7e59ee6737828fe8f3861450f2a70256a64907a1151b0acb1c98b80eaea
MD5 7941566850f8cde6e91228857603688b
BLAKE2b-256 af4821fdc92dd5c2a4791e89ed2b66eab5bd7fe55fc5da667f13e9c1696c35e2

See more details on using hashes here.

Provenance

The following attestation bundles were made for langchain_nono-0.1.0-py3-none-any.whl:

Publisher: publish.yml on always-further/langchain-nono

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