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
Agentthat runs a tool-use loop and pauses before any tool you markRiskTier.SENSITIVE, until a human approves, edits, or rejects it. - Model-agnostic providers (
AnthropicProvider,OpenAiProvider) over an injectedhttpxclient — 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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| airlock_hitl-0.1.1.tar.gz | 58.8 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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 logSecurity 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.
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 logA 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.