Skip to main content

agent-safe-runner

CI Python 3.11+ License: MIT

agent-safe-runner is a small, local-first queue for automation commands proposed by AI agents. It stores jobs in SQLite, requires a separate approval decision and an explicit command policy before execution, and writes a redacted JSONL audit trail.

The project is intentionally narrow: it helps a local operator control which commands may run, when they may run, and what evidence is retained afterward.

Why it exists

Agent workflows often grow from scripts into unattended queues. At that point, a plain subprocess.run() leaves important questions unanswered:

  • Was the command explicitly allowed?
  • Who reviewed it before execution?
  • Could two workers run the same job?
  • Did a retry happen, and why?
  • Did logs accidentally store a token?
  • Can the operator verify the event history?

This runner makes those controls explicit without adding a service, broker, or cloud dependency.

Features

  • Deny-by-default JSON policy with command-prefix and working-directory rules
  • Strict policy validation and a read-only check-policy command
  • Approval inbox, read-only assessment, and explicit approve/deny decisions
  • Dry run by default; real execution requires approval, policy allowance, and --execute
  • SQLite queue with idempotency keys and fail-closed schema migration from 0.1.x / 0.2.x
  • Concurrent duplicate submissions return one original job; audit failures roll back new submissions
  • Atomic leases, expired-lease recovery, bounded retries, and exponential backoff
  • Job cancellation, manual retry, status filtering, and one-pass worker mode
  • Secret-like argument rejection before persistence
  • Minimal child-process environment and redacted output capture
  • Append-only JSONL audit events with a verifiable SHA-256 hash chain
  • Full audit-chain validation before appending, with clear errors for damaged records
  • Structured JSON output and errors for scripting
  • Optional stdio MCP adapter with proposal/read-only tools; no approval or execution tools
  • Standard-library runtime with no required third-party dependencies

Install

Python 3.11 or newer is required.

Install the published release from PyPI in an isolated environment:

pipx install agent-safe-runner

Confirm that the command is available:

agent-safe --version

Need pipx first? Follow the official installation guide. If agent-safe is not found, run pipx ensurepath and reopen your terminal. Prefer pip? In an activated virtual environment, use python -m pip install agent-safe-runner.

For AI-agent integrations, see the optional MCP adapter.

For setup, troubleshooting, and GitHub source installation, see the getting-started guide. Contributors should use the development setup.

Quick start

Create a dedicated workspace so the queue, policy, and audit files stay together:

mkdir agent-safe-workspace
cd agent-safe-workspace
agent-safe init-policy
agent-safe check-policy

The generated agent-safe-policy.json contains a few example rules. Review it before use: python --version prints a version, but pytest executes project code and is appropriate only in a trusted workspace.

Queue a command that prints the installed Python version:

agent-safe submit --cwd . --timeout 30 -- python --version

The command returns a JSON object. Copy its id, then inspect the job and perform a dry run. Replace JOB_ID below with that value:

agent-safe show JOB_ID
agent-safe assess JOB_ID
agent-safe run JOB_ID

assess returns allowed, reason, and matched_rule. An allowed job is still pending approval. run without --execute remains a dry run.

After reviewing the exact command, directory, timeout, and retry limit, record your decision. Replace local-operator with a label meaningful to you:

agent-safe approve JOB_ID --by local-operator --reason "Reviewed version check"
agent-safe run JOB_ID --execute --worker local-1

--by is an audit label, not authentication. Anyone with access to the approval CLI or writable database can approve jobs; this is a workflow gate.

The final JSON should report "status": "succeeded". Verify the audit chain's integrity:

agent-safe audit-verify

See Getting started for installation isolation, upgrades, troubleshooting, and a complete first-run walkthrough.

Common commands

agent-safe check-policy
agent-safe list
agent-safe inbox
agent-safe list --approval pending
agent-safe list --status queued --status retry_wait
agent-safe show JOB_ID
agent-safe assess JOB_ID
agent-safe deny JOB_ID --by local-operator --reason "Not needed"
agent-safe cancel JOB_ID
agent-safe retry JOB_ID
agent-safe work --once --execute --worker local-1
agent-safe audit-verify

Global paths must appear before the subcommand:

agent-safe --db /path/to/jobs.sqlite3 --audit /path/to/audit.jsonl --policy /path/to/policy.json list

Everything after -- in submit is stored as an argument vector and is never passed through a shell parser. All commands emit JSON. Expected input, state, and policy errors return exit code 2 with a stable error code.

work --once --execute picks only approved jobs. Manual retry clears the old decision and requires fresh approval; automatic retries keep the existing approval for the unchanged job. deny cancels a pending job. To stop an already approved queued job, use cancel.

Upgrade and uninstall

Upgrading from 0.2.x or older? Stop all workers and back up your local state before installing. Old queued jobs become pending and will not run until reviewed. See the 0.3 migration guide.

Upgrade a pipx installation to the latest published release:

pipx upgrade agent-safe-runner

Remove the command-line application:

pipx uninstall agent-safe-runner

For a pip installation, use python -m pip install --upgrade agent-safe-runner or python -m pip uninstall agent-safe-runner inside its virtual environment. Uninstalling does not delete your queue, policy, or audit files.

Policy

After editing a policy, run agent-safe --policy /path/to/policy.json check-policy. It validates configuration only; it does not approve jobs or prove a command is safe. Version 0.4.1 rejects unknown fields, duplicate keys, and incorrect JSON types. An omitted or empty args_prefix still explicitly allows all arguments for that program, so review such rules carefully. UTF-8 files with or without a BOM work.

Execution is denied when the policy file is absent. A policy contains:

{
  "version": 1,
  "allowed_commands": [
    {"program": "python", "args_prefix": ["--version"]},
    {"program": "python", "args_prefix": ["-m", "pytest"]},
    {"program": "git", "args_prefix": ["status"]}
  ],
  "allowed_working_roots": ["."],
  "denied_arguments": ["--force", "--hard"],
  "environment_allowlist": ["PATH", "PATHEXT", "SYSTEMROOT", "WINDIR", "TEMP", "TMP"],
  "max_timeout_seconds": 300,
  "max_output_chars": 8000
}

Rules compare resolved executable paths and the case-sensitive beginning of the argument list. Missing executables do not match. An empty args_prefix allows every argument for that executable and should be used cautiously.

Never place credentials in a command. The runner rejects common secret flags and token formats, but detection cannot identify every secret. Use a dedicated secret provider and grant the worker only the environment variables it needs.

Job states

queued -> running -> succeeded
                  -> retry_wait -> running
                  -> failed
queued/retry_wait -> cancelled -> queued (manual retry)
queued/retry_wait -> dead_letter (policy denial)

Approval is separate from execution status: pending, approved, denied, or legacy for historical records. New jobs start queued + pending. Policy-invalid approved jobs become dead_letter without spawning a process. Nonzero exits, timeouts, and process-start failures retry up to max_attempts.

Data files

  • agent-safe.sqlite3: queue state, commands, and redacted results
  • audit.jsonl: redacted event records and hash-chain metadata
  • agent-safe-policy.json: local execution policy

These runtime files are ignored by Git. SQLite commands are stored in plain text, so do not submit secrets or place the database in a public or broadly synchronized directory.

Current limits

  • The audit chain detects accidental edits; it is not a cryptographic signature and an attacker with write access can rebuild it.
  • Audit appends use advisory file locking on Windows and POSIX; filesystems that ignore advisory locks are unsupported for multi-process writers.
  • Running jobs cannot currently be interrupted by cancel; cancellation applies to queued and retry-wait jobs.
  • Approval records are not signatures or user authentication. This gate cannot constrain an agent that already has unrestricted terminal or file access.
  • SQLite state and JSONL audit are separate stores, not a single crash-atomic transaction. See Architecture.
  • Output limits bound stored text, not peak capture memory; lease recovery is at-least-once, not an exactly-once guarantee for external side effects.
  • MCP is local stdio only. There is no remote API, scheduler daemon, plugin system, or secret-provider integration yet.

See Architecture, Threat model, Roadmap, Contributing, and Security policy.

License

MIT

Metadata

Release files for agent-safe-runner 0.4.3

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

Source distribution (sdist)

Source distribution for agent-safe-runner 0.4.3
File Size Uploaded Provenance
agent_safe_runner-0.4.3.tar.gz 49.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-safe-runner 0.4.3
File Interpreter ABI Platform
agent_safe_runner-0.4.3-py3-none-any.whl Python 3 none any Details

Total release size: 74.5 kB

Release files / agent_safe_runner-0.4.3.tar.gz

Download URL agent_safe_runner-0.4.3.tar.gz
Size 49.1 kB
Tags Source
SHA-256 checksum
How to use checksums
f85d167025ab8fca543fff625e148dd87d0b410f423c80920158dead5d276d0a
BLAKE2b-256 checksum
How to use checksums
e4e0a30e0ed56acc558d2e7326d54e90d049b48bbd08ef820a43bf5db968e960
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 8, 2026.

Transparency log

Release files / agent_safe_runner-0.4.3-py3-none-any.whl

Download URL agent_safe_runner-0.4.3-py3-none-any.whl
Size 25.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d4f82e99dbf2c3af07f3f61babcb29c61f1944e3b3c55b169cca63ad4bd6d7dd
BLAKE2b-256 checksum
How to use checksums
c94511d0d74025b670f5469129fff6933f766119b025532e025f81f2e02c7600
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 8, 2026.

Transparency log

Security for agent-safe-runner 0.4.3

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 agent_safe_runner-0.4.3.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 Sep 8, 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.

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