agent-safe-runner 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_safe_runner-0.4.0/.github/ISSUE_TEMPLATE/bug_report.yml +28 -0
- agent_safe_runner-0.4.0/.github/workflows/ci.yml +32 -0
- agent_safe_runner-0.4.0/.github/workflows/publish.yml +72 -0
- agent_safe_runner-0.4.0/.gitignore +14 -0
- agent_safe_runner-0.4.0/CHANGELOG.md +72 -0
- agent_safe_runner-0.4.0/CONTRIBUTING.md +44 -0
- agent_safe_runner-0.4.0/LICENSE +21 -0
- agent_safe_runner-0.4.0/PKG-INFO +273 -0
- agent_safe_runner-0.4.0/README.md +245 -0
- agent_safe_runner-0.4.0/ROADMAP.md +37 -0
- agent_safe_runner-0.4.0/SECURITY.md +25 -0
- agent_safe_runner-0.4.0/docs/architecture.md +87 -0
- agent_safe_runner-0.4.0/docs/getting-started.md +195 -0
- agent_safe_runner-0.4.0/docs/mcp.md +134 -0
- agent_safe_runner-0.4.0/docs/migration-0.3.md +70 -0
- agent_safe_runner-0.4.0/docs/publishing.md +83 -0
- agent_safe_runner-0.4.0/docs/threat-model.md +40 -0
- agent_safe_runner-0.4.0/policy.example.json +13 -0
- agent_safe_runner-0.4.0/pyproject.toml +43 -0
- agent_safe_runner-0.4.0/scripts/check_release.py +55 -0
- agent_safe_runner-0.4.0/src/agent_safe_runner/__init__.py +3 -0
- agent_safe_runner-0.4.0/src/agent_safe_runner/__main__.py +5 -0
- agent_safe_runner-0.4.0/src/agent_safe_runner/audit.py +126 -0
- agent_safe_runner-0.4.0/src/agent_safe_runner/cli.py +156 -0
- agent_safe_runner-0.4.0/src/agent_safe_runner/core.py +531 -0
- agent_safe_runner-0.4.0/src/agent_safe_runner/errors.py +32 -0
- agent_safe_runner-0.4.0/src/agent_safe_runner/mcp_server.py +170 -0
- agent_safe_runner-0.4.0/src/agent_safe_runner/policy.py +121 -0
- agent_safe_runner-0.4.0/src/agent_safe_runner/redaction.py +56 -0
- agent_safe_runner-0.4.0/tests/test_approval.py +340 -0
- agent_safe_runner-0.4.0/tests/test_cli.py +56 -0
- agent_safe_runner-0.4.0/tests/test_cli_approval.py +57 -0
- agent_safe_runner-0.4.0/tests/test_core.py +188 -0
- agent_safe_runner-0.4.0/tests/test_mcp.py +146 -0
- agent_safe_runner-0.4.0/tests/test_optional_mcp.py +23 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report a reproducible defect
|
|
3
|
+
title: "[Bug]: "
|
|
4
|
+
labels: [bug]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
attributes:
|
|
8
|
+
label: What happened?
|
|
9
|
+
description: Include the expected and observed behavior.
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
attributes:
|
|
14
|
+
label: Reproduction
|
|
15
|
+
description: Provide the smallest safe reproduction without credentials or private data.
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
- type: input
|
|
19
|
+
attributes:
|
|
20
|
+
label: Version and operating system
|
|
21
|
+
validations:
|
|
22
|
+
required: true
|
|
23
|
+
- type: checkboxes
|
|
24
|
+
attributes:
|
|
25
|
+
label: Safety check
|
|
26
|
+
options:
|
|
27
|
+
- label: I removed credentials, tokens, cookies, and private paths from this report.
|
|
28
|
+
required: true
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
workflow_call:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
os: [ubuntu-latest, windows-latest]
|
|
17
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
18
|
+
runs-on: ${{ matrix.os }}
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v5
|
|
21
|
+
- uses: actions/setup-python@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
cache: pip
|
|
25
|
+
- run: python -m pip install ".[dev]"
|
|
26
|
+
- run: agent-safe --version
|
|
27
|
+
- run: python -m agent_safe_runner --version
|
|
28
|
+
- run: python -m pytest -q
|
|
29
|
+
- name: Install optional MCP adapter
|
|
30
|
+
run: python -m pip install ".[mcp]"
|
|
31
|
+
- name: Test real MCP stdio client
|
|
32
|
+
run: python -m pytest tests/test_mcp.py -q
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
publish:
|
|
7
|
+
description: "Publish to PyPI (requires configured Trusted Publisher); false only validates artifacts"
|
|
8
|
+
type: boolean
|
|
9
|
+
required: true
|
|
10
|
+
default: false
|
|
11
|
+
release:
|
|
12
|
+
types: [published]
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
concurrency:
|
|
18
|
+
group: pypi-publish
|
|
19
|
+
cancel-in-progress: false
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
test:
|
|
23
|
+
if: github.event_name == 'release' || github.ref == 'refs/heads/main'
|
|
24
|
+
uses: ./.github/workflows/ci.yml
|
|
25
|
+
|
|
26
|
+
build:
|
|
27
|
+
needs: test
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v5
|
|
31
|
+
with:
|
|
32
|
+
persist-credentials: false
|
|
33
|
+
- uses: actions/setup-python@v6
|
|
34
|
+
with:
|
|
35
|
+
python-version: "3.11"
|
|
36
|
+
- run: python -m pip install build twine pipx
|
|
37
|
+
- run: python -m build
|
|
38
|
+
- name: Validate package metadata, contents, and release tag
|
|
39
|
+
env:
|
|
40
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
41
|
+
run: python scripts/check_release.py dist
|
|
42
|
+
- run: python -m twine check --strict dist/*
|
|
43
|
+
- name: Verify pipx installation of the exact wheel
|
|
44
|
+
env:
|
|
45
|
+
PIPX_HOME: ${{ runner.temp }}/agent-safe-pipx
|
|
46
|
+
PIPX_BIN_DIR: ${{ runner.temp }}/agent-safe-bin
|
|
47
|
+
run: |
|
|
48
|
+
python -m pipx install --python "$(command -v python)" dist/*.whl
|
|
49
|
+
"$PIPX_BIN_DIR/agent-safe" --version
|
|
50
|
+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
51
|
+
with:
|
|
52
|
+
name: python-distributions
|
|
53
|
+
path: dist/
|
|
54
|
+
if-no-files-found: error
|
|
55
|
+
retention-days: 14
|
|
56
|
+
|
|
57
|
+
publish:
|
|
58
|
+
needs: build
|
|
59
|
+
if: github.event_name == 'release' || inputs.publish == true
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
environment:
|
|
62
|
+
name: pypi
|
|
63
|
+
url: https://pypi.org/project/agent-safe-runner/
|
|
64
|
+
permissions:
|
|
65
|
+
id-token: write
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
68
|
+
with:
|
|
69
|
+
name: python-distributions
|
|
70
|
+
path: dist/
|
|
71
|
+
- name: Publish verified distributions using short-lived OIDC credentials
|
|
72
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.4.0] - 2026-09-03
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Optional local stdio MCP interface: submit_command, get_job, list_jobs, assess_job, verify_audit.
|
|
12
|
+
- Strict bounded input schemas, MCP source labels, namespaced idempotency keys, redacted errors, and per-request policy reload.
|
|
13
|
+
- Read-only SQLite access for MCP inspection; approval/execution remain separate operator actions.
|
|
14
|
+
- Real subprocess MCP client tests, core-only dependency checks, and optional-extra CI coverage.
|
|
15
|
+
- PyPI Trusted Publishing workflow with cross-platform tests, artifact validation, pipx smoke test, and isolated OIDC publishing job.
|
|
16
|
+
- MCP setup and first-time PyPI publication documentation. The workflow alone does not mean PyPI publication has completed.
|
|
17
|
+
|
|
18
|
+
## [0.3.0] - 2026-09-02
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- Pending-by-default approval, operator label, decision time/reason, and proposal source.
|
|
23
|
+
- `inbox`, read-only `assess`, explicit `approve` / `deny`, and `list --approval`.
|
|
24
|
+
- Transactional decision checks and redacted audit intents; audit append failure rolls back a decision.
|
|
25
|
+
- Migration checklist and regression tests for approval, concurrent decisions, and old queues.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **Breaking:** execution and claims require approval as well as policy allowance.
|
|
30
|
+
- Old queued/retry-wait jobs and expired running jobs require review after migration.
|
|
31
|
+
- Manual retry (including dead-letter jobs) clears approval; automatic retries retain it.
|
|
32
|
+
- New jobs store an absolute working directory even when `--cwd` is omitted.
|
|
33
|
+
- Argument prefixes are case-sensitive; review policies that relied on case folding.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Missing executable names no longer match each other; POSIX executable paths retain case sensitivity.
|
|
38
|
+
- Execution uses the resolved executable path instead of searching again in the job directory.
|
|
39
|
+
- Process-start failures release the lease and follow the bounded retry policy.
|
|
40
|
+
- Workers recover expired leases even when no other queued job exists.
|
|
41
|
+
- Cancellation and manual retry use conditional state updates to avoid overwriting a concurrent claim.
|
|
42
|
+
|
|
43
|
+
## [0.2.1] - 2026-08-28
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- End-user installation, upgrade, uninstall, troubleshooting, and first-run instructions.
|
|
48
|
+
- `agent-safe --version` and `python -m agent_safe_runner` entry points.
|
|
49
|
+
- A harmless `python --version` rule in the generated sample policy.
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- Package metadata now links to the Umefor Labs repository, documentation, and issue tracker.
|
|
54
|
+
- CI action runtimes were updated and now include an installed-command smoke test.
|
|
55
|
+
|
|
56
|
+
## [0.2.0] - 2026-08-28
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
|
|
60
|
+
- Deny-by-default command policy with prefixes, working roots, argument denials, and execution limits.
|
|
61
|
+
- Atomic job leases, expired-lease recovery, bounded retry with backoff, cancellation, and manual retry.
|
|
62
|
+
- Secret-like argument rejection, minimal child environment, output redaction, and output limits.
|
|
63
|
+
- Hash-chained JSONL audit verification.
|
|
64
|
+
- Structured CLI commands for policy initialization, queue inspection, execution, workers, cancellation, retry, and audit verification.
|
|
65
|
+
- Migration support for databases created by `0.1.x`.
|
|
66
|
+
- Cross-platform CI configuration, threat model, security policy, and contributing guide.
|
|
67
|
+
|
|
68
|
+
## [0.1.0] - 2026-08-28
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
- Initial SQLite queue, idempotent submission, dry run, execution, JSONL audit, and CLI.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for helping improve `agent-safe-runner`.
|
|
4
|
+
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
python -m venv .venv
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Activate it in PowerShell on Windows:
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
.\.venv\Scripts\Activate.ps1
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or on macOS/Linux:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
source .venv/bin/activate
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Then install and test (repeat the install after changing package metadata):
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python -m pip install -e ".[dev]"
|
|
27
|
+
python -m pytest
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Keep runtime dependencies in the Python standard library unless a new dependency has a clear security and maintenance benefit.
|
|
31
|
+
|
|
32
|
+
## Pull requests
|
|
33
|
+
|
|
34
|
+
1. Open an issue before a large behavior or schema change.
|
|
35
|
+
2. Add focused tests for changed behavior.
|
|
36
|
+
3. Preserve deny-by-default execution and backward-compatible database migration.
|
|
37
|
+
4. Do not add examples containing real credentials, tokens, cookies, or private paths.
|
|
38
|
+
5. Update the README and changelog when user-facing behavior changes.
|
|
39
|
+
|
|
40
|
+
Security-sensitive changes should include the threat being addressed, assumptions, failure mode, and test evidence.
|
|
41
|
+
|
|
42
|
+
## Commit style
|
|
43
|
+
|
|
44
|
+
Use a short imperative subject, for example `Reject secrets before persistence`. Keep unrelated changes in separate commits.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JARVIS contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: agent-safe-runner
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: A local-first, auditable job runner for AI-agent automation
|
|
5
|
+
Project-URL: Homepage, https://github.com/umefor-labs/agent-safe-runner
|
|
6
|
+
Project-URL: Documentation, https://github.com/umefor-labs/agent-safe-runner/blob/main/docs/getting-started.md
|
|
7
|
+
Project-URL: Issues, https://github.com/umefor-labs/agent-safe-runner/issues
|
|
8
|
+
Project-URL: Source, https://github.com/umefor-labs/agent-safe-runner
|
|
9
|
+
Author: Umefor Labs
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: agents,automation,job-queue,local-first,security
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
24
|
+
Provides-Extra: mcp
|
|
25
|
+
Requires-Dist: jsonschema<5,>=4.20; extra == 'mcp'
|
|
26
|
+
Requires-Dist: mcp<3,>=2.1; extra == 'mcp'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# agent-safe-runner
|
|
30
|
+
|
|
31
|
+
[](https://github.com/umefor-labs/agent-safe-runner/actions/workflows/ci.yml)
|
|
32
|
+
[](https://www.python.org/downloads/)
|
|
33
|
+
[](LICENSE)
|
|
34
|
+
|
|
35
|
+
`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.
|
|
36
|
+
|
|
37
|
+
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.
|
|
38
|
+
|
|
39
|
+
> [!WARNING]
|
|
40
|
+
> This project is an execution gate, not an operating-system sandbox. Run workers with a low-privilege account and use containers or OS isolation for untrusted code.
|
|
41
|
+
|
|
42
|
+
## Why it exists
|
|
43
|
+
|
|
44
|
+
Agent workflows often grow from scripts into unattended queues. At that point, a plain `subprocess.run()` leaves important questions unanswered:
|
|
45
|
+
|
|
46
|
+
- Was the command explicitly allowed?
|
|
47
|
+
- Who reviewed it before execution?
|
|
48
|
+
- Could two workers run the same job?
|
|
49
|
+
- Did a retry happen, and why?
|
|
50
|
+
- Did logs accidentally store a token?
|
|
51
|
+
- Can the operator verify the event history?
|
|
52
|
+
|
|
53
|
+
This runner makes those controls explicit without adding a service, broker, or cloud dependency.
|
|
54
|
+
|
|
55
|
+
## Features
|
|
56
|
+
|
|
57
|
+
- Deny-by-default JSON policy with command-prefix and working-directory rules
|
|
58
|
+
- Approval inbox, read-only assessment, and explicit approve/deny decisions
|
|
59
|
+
- Dry run by default; real execution requires approval, policy allowance, and `--execute`
|
|
60
|
+
- SQLite queue with idempotency keys and fail-closed schema migration from `0.1.x` / `0.2.x`
|
|
61
|
+
- Atomic leases, expired-lease recovery, bounded retries, and exponential backoff
|
|
62
|
+
- Job cancellation, manual retry, status filtering, and one-pass worker mode
|
|
63
|
+
- Secret-like argument rejection before persistence
|
|
64
|
+
- Minimal child-process environment and redacted output capture
|
|
65
|
+
- Append-only JSONL audit events with a verifiable SHA-256 hash chain
|
|
66
|
+
- Structured JSON output and errors for scripting
|
|
67
|
+
- Optional stdio MCP adapter with proposal/read-only tools; no approval or execution tools
|
|
68
|
+
- Standard-library runtime with no required third-party dependencies
|
|
69
|
+
|
|
70
|
+
## Install
|
|
71
|
+
|
|
72
|
+
Python 3.11 or newer is required.
|
|
73
|
+
|
|
74
|
+
Install the latest version directly from GitHub:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
python -m pip install "https://github.com/umefor-labs/agent-safe-runner/archive/refs/heads/main.zip"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Confirm that the command is available:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
agent-safe --version
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
If your system does not expose the `agent-safe` command after installation,
|
|
87
|
+
use `python -m agent_safe_runner` in its place.
|
|
88
|
+
|
|
89
|
+
### Short installation command (after PyPI publication)
|
|
90
|
+
|
|
91
|
+
Once a release is listed on [PyPI](https://pypi.org/project/agent-safe-runner/),
|
|
92
|
+
users can install it in isolation with:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pipx install agent-safe-runner
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Until the first PyPI upload is verified, use the GitHub installation above.
|
|
99
|
+
A GitHub push alone does not publish to PyPI; maintainers can follow the
|
|
100
|
+
[publishing checklist](docs/publishing.md).
|
|
101
|
+
|
|
102
|
+
For AI-agent integrations, see the [optional MCP adapter](docs/mcp.md).
|
|
103
|
+
|
|
104
|
+
For an isolated installation with `pipx`, see the
|
|
105
|
+
[getting-started guide](docs/getting-started.md). Contributors should use the
|
|
106
|
+
[development setup](CONTRIBUTING.md).
|
|
107
|
+
|
|
108
|
+
## Quick start
|
|
109
|
+
|
|
110
|
+
Create a dedicated workspace so the queue, policy, and audit files stay together:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
mkdir agent-safe-workspace
|
|
114
|
+
cd agent-safe-workspace
|
|
115
|
+
agent-safe init-policy
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The generated `agent-safe-policy.json` contains a few example rules. Review it
|
|
119
|
+
before use: `python --version` prints a version, but `pytest` executes project
|
|
120
|
+
code and is appropriate only in a trusted workspace.
|
|
121
|
+
|
|
122
|
+
Queue a command that prints the installed Python version:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
agent-safe submit --cwd . --timeout 30 -- python --version
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The command returns a JSON object. Copy its `id`, then inspect the job and perform
|
|
129
|
+
a dry run. Replace `JOB_ID` below with that value:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
agent-safe show JOB_ID
|
|
133
|
+
agent-safe assess JOB_ID
|
|
134
|
+
agent-safe run JOB_ID
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`assess` returns `allowed`, `reason`, and `matched_rule`. An allowed job is still
|
|
138
|
+
pending approval. `run` without `--execute` remains a dry run.
|
|
139
|
+
|
|
140
|
+
After reviewing the exact command, directory, timeout, and retry limit, record
|
|
141
|
+
your decision. Replace `local-operator` with a label meaningful to you:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
agent-safe approve JOB_ID --by local-operator --reason "Reviewed version check"
|
|
145
|
+
agent-safe run JOB_ID --execute --worker local-1
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`--by` is an audit label, **not authentication**. Anyone with access to the
|
|
149
|
+
approval CLI or writable database can approve jobs; this is a workflow gate.
|
|
150
|
+
|
|
151
|
+
The final JSON should report `"status": "succeeded"`. Verify the audit chain's
|
|
152
|
+
integrity:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
agent-safe audit-verify
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
See [Getting started](docs/getting-started.md) for installation isolation,
|
|
159
|
+
upgrades, troubleshooting, and a complete first-run walkthrough.
|
|
160
|
+
|
|
161
|
+
## Common commands
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
agent-safe list
|
|
165
|
+
agent-safe inbox
|
|
166
|
+
agent-safe list --approval pending
|
|
167
|
+
agent-safe list --status queued --status retry_wait
|
|
168
|
+
agent-safe show JOB_ID
|
|
169
|
+
agent-safe assess JOB_ID
|
|
170
|
+
agent-safe deny JOB_ID --by local-operator --reason "Not needed"
|
|
171
|
+
agent-safe cancel JOB_ID
|
|
172
|
+
agent-safe retry JOB_ID
|
|
173
|
+
agent-safe work --once --execute --worker local-1
|
|
174
|
+
agent-safe audit-verify
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Global paths must appear before the subcommand:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
agent-safe --db /path/to/jobs.sqlite3 --audit /path/to/audit.jsonl --policy /path/to/policy.json list
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Everything after `--` in `submit` is stored as an argument vector and is never
|
|
184
|
+
passed through a shell parser. All commands emit JSON. Expected input, state, and
|
|
185
|
+
policy errors return exit code `2` with a stable error code.
|
|
186
|
+
|
|
187
|
+
`work --once --execute` picks only approved jobs. Manual `retry` clears the old
|
|
188
|
+
decision and requires fresh approval; automatic retries keep the existing
|
|
189
|
+
approval for the unchanged job. `deny` cancels a pending job. To stop an already
|
|
190
|
+
approved queued job, use `cancel`.
|
|
191
|
+
|
|
192
|
+
## Upgrade and uninstall
|
|
193
|
+
|
|
194
|
+
**Upgrading from 0.2.x or older?** Stop all workers and back up your local state
|
|
195
|
+
before installing. Old queued jobs become pending and will not run until
|
|
196
|
+
reviewed. See the [0.3 migration guide](docs/migration-0.3.md).
|
|
197
|
+
|
|
198
|
+
Upgrade to the latest GitHub version:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
python -m pip install --upgrade "https://github.com/umefor-labs/agent-safe-runner/archive/refs/heads/main.zip"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Remove the command-line application:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
python -m pip uninstall agent-safe-runner
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Uninstalling does not delete your queue, policy, or audit files.
|
|
211
|
+
|
|
212
|
+
## Policy
|
|
213
|
+
|
|
214
|
+
Execution is denied when the policy file is absent. A policy contains:
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"version": 1,
|
|
219
|
+
"allowed_commands": [
|
|
220
|
+
{"program": "python", "args_prefix": ["--version"]},
|
|
221
|
+
{"program": "python", "args_prefix": ["-m", "pytest"]},
|
|
222
|
+
{"program": "git", "args_prefix": ["status"]}
|
|
223
|
+
],
|
|
224
|
+
"allowed_working_roots": ["."],
|
|
225
|
+
"denied_arguments": ["--force", "--hard"],
|
|
226
|
+
"environment_allowlist": ["PATH", "PATHEXT", "SYSTEMROOT", "WINDIR", "TEMP", "TMP"],
|
|
227
|
+
"max_timeout_seconds": 300,
|
|
228
|
+
"max_output_chars": 8000
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
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.
|
|
233
|
+
|
|
234
|
+
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.
|
|
235
|
+
|
|
236
|
+
## Job states
|
|
237
|
+
|
|
238
|
+
```text
|
|
239
|
+
queued -> running -> succeeded
|
|
240
|
+
-> retry_wait -> running
|
|
241
|
+
-> failed
|
|
242
|
+
queued/retry_wait -> cancelled -> queued (manual retry)
|
|
243
|
+
queued/retry_wait -> dead_letter (policy denial)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Approval is separate from execution status: `pending`, `approved`, `denied`, or
|
|
247
|
+
`legacy` for historical records. New jobs start `queued` + `pending`.
|
|
248
|
+
Policy-invalid approved jobs become `dead_letter` without spawning a process.
|
|
249
|
+
Nonzero exits, timeouts, and process-start failures retry up to `max_attempts`.
|
|
250
|
+
|
|
251
|
+
## Data files
|
|
252
|
+
|
|
253
|
+
- `agent-safe.sqlite3`: queue state, commands, and redacted results
|
|
254
|
+
- `audit.jsonl`: redacted event records and hash-chain metadata
|
|
255
|
+
- `agent-safe-policy.json`: local execution policy
|
|
256
|
+
|
|
257
|
+
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.
|
|
258
|
+
|
|
259
|
+
## Current limits
|
|
260
|
+
|
|
261
|
+
- The audit chain detects accidental edits; it is not a cryptographic signature and an attacker with write access can rebuild it.
|
|
262
|
+
- Audit appends use advisory file locking on Windows and POSIX; filesystems that ignore advisory locks are unsupported for multi-process writers.
|
|
263
|
+
- Running jobs cannot currently be interrupted by `cancel`; cancellation applies to queued and retry-wait jobs.
|
|
264
|
+
- Approval records are not signatures or user authentication. This gate cannot constrain an agent that already has unrestricted terminal or file access.
|
|
265
|
+
- SQLite state and JSONL audit are separate stores, not a single crash-atomic transaction. See [Architecture](docs/architecture.md).
|
|
266
|
+
- Output limits bound stored text, not peak capture memory; lease recovery is at-least-once, not an exactly-once guarantee for external side effects.
|
|
267
|
+
- MCP is local stdio only. There is no remote API, scheduler daemon, plugin system, or secret-provider integration yet.
|
|
268
|
+
|
|
269
|
+
See [Architecture](docs/architecture.md), [Threat model](docs/threat-model.md), [Roadmap](ROADMAP.md), [Contributing](CONTRIBUTING.md), and [Security policy](SECURITY.md).
|
|
270
|
+
|
|
271
|
+
## License
|
|
272
|
+
|
|
273
|
+
MIT
|