Skip to main content

airlock-hitl

A human-approval gate for the dangerous things an AI agent does. This is the Python package; it mirrors the TypeScript package one-to-one. The full story, design notes, and a live dashboard demo are in the repository.

An agent that can act on untrusted input is dangerous: a prompt injection or a plain mistake can make it pay, email, or delete the wrong thing — and a system prompt won't stop it. Airlock assumes the model will be hijacked and puts the safety boundary in the architecture: every tool you mark SENSITIVE pauses for a human to approve, edit, or reject before it runs.

Install

pip install airlock-hitl      # or: uv add airlock-hitl

The distribution is named airlock-hitl; the import is airlock. Requires Python 3.13+.

Quickstart

The agent wants to send an email — the run pauses before it happens, and the email is sent only once you approve.

import asyncio

from airlock import (
    Agent,
    AgentDependencies,
    ApproveDecision,
    CompletionResult,
    FakeLlmProvider,
    InMemoryAuditSink,
    InMemoryEventBus,
    InMemoryRunStore,
    RiskBasedGatePolicy,
    RiskTier,
    SystemClock,
    Tool,
    ToolCall,
    ToolCallId,
    UuidIdGenerator,
)


async def send_email(args):
    print("SENDING:", dict(args))
    return "sent"


# Mark the tool SENSITIVE: it must be approved before it runs.
tool = Tool(
    name="send_email",
    description="Send an email",
    parameters={"type": "object"},
    risk=RiskTier.SENSITIVE,
    handler=send_email,
)

# A scripted model — swap for AnthropicProvider / OpenAiProvider in production.
provider = FakeLlmProvider(
    [
        CompletionResult(
            text=None,
            tool_calls=(ToolCall(id=ToolCallId("1"), name="send_email", args={"to": "alice@example.com"}),),
        ),
        CompletionResult(text="Done.", tool_calls=()),
    ]
)

agent = Agent(
    AgentDependencies(
        provider=provider,
        tools=[tool],
        events=InMemoryEventBus(),
        store=InMemoryRunStore(),
        audit=InMemoryAuditSink(),
        clock=SystemClock(),
        ids=UuidIdGenerator(),
        gate_policy=RiskBasedGatePolicy(),
        system_prompt="You are a support agent.",
    )
)


async def main():
    paused = await agent.run("Email Alice a refund confirmation")
    print(paused.status)  # "awaiting_approval" — nothing sent yet
    done = await agent.resume(
        paused.run_id, paused.approval.request_id, ApproveDecision(approver="you@example.com")
    )
    print(done.status)  # "completed" — now the email was sent


asyncio.run(main())

In production, swap FakeLlmProvider for AnthropicProvider or OpenAiProvider, and the in-memory adapters for RedisRunStore + RedisEventBus so runs pause and resume across processes. Runnable end-to-end demos (CLI approver, Redis, the dashboard) are in the repository.

What you get

  • An Agent that runs a tool-use loop and pauses before any tool you mark RiskTier.SENSITIVE, until a human approves, edits, or rejects it.
  • Model-agnostic providers (AnthropicProvider, OpenAiProvider) over an injected httpx client — no vendor SDKs.
  • A Redis store and Pub/Sub bus for pause/resume across processes, plus in-memory fakes for tests and demos.

Layout (hexagonal — imports point inward)

  • airlock.domain — tools, risk tiers, messages, runs, events, errors. No I/O.
  • airlock.application — the agent loop, the gate policy, and the ports (Protocols).
  • airlock.infrastructure — adapters: providers, the Redis store and bus, audit sinks, clocks, id generators, and the in-memory fakes.
  • airlock.interface — driving adapters: the runner and the approver.
  • airlock.core — Settings (pydantic-settings).

License

MIT — see the repository for contributing and the full engineering write-up.

Metadata

Release files for airlock-hitl 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for airlock-hitl 0.1.1
File Size Uploaded Provenance
airlock_hitl-0.1.1.tar.gz 58.8 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for airlock-hitl 0.1.1
File Interpreter ABI Platform
airlock_hitl-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 88.5 kB

Release files / airlock_hitl-0.1.1.tar.gz

Download URL airlock_hitl-0.1.1.tar.gz
Size 58.8 kB
Tags Source
SHA-256 checksum
How to use checksums
463bc80cd2057689110bff7072297ddd9d8e1f2f804e519373836fdbe92269eb
BLAKE2b-256 checksum
How to use checksums
6282aac7d1af6ad539f3ac7513b70b3dc4d9ec8c39b07ab8044bc06b12764538
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 25, 2026.

Transparency log

Release files / airlock_hitl-0.1.1-py3-none-any.whl

Download URL airlock_hitl-0.1.1-py3-none-any.whl
Size 29.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9ce234b8ed7ea817df8e6040fa4704840131e39df6ce1acb6a76e71aba20d42b
BLAKE2b-256 checksum
How to use checksums
407ba83ea3315922ea1d3c2deb15cc4b59a6ae9643ae6175749ce981db24bbcb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 25, 2026.

Transparency log

Security for airlock-hitl 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for airlock_hitl-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 25, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page