SafeRepo Agent is a coding-agent runtime for isolated repository repair. It runs model roles against a sanitized disposable copy, keeps workflow transitions under host control, applies deterministic task/command/result policies, and persists an auditable evidence bundle for every run.
The repository includes a credential-free offline backend, an OpenAI Agents SDK backend, Docker and Unix-local sandboxes, an asynchronous FastAPI service, frozen security cases, and a trusted patch-replay benchmark.
- host-owned
planner -> executor -> verifier -> repairerworkflow; direct,plan, andplan-and-verifystrategies;- typed model outputs with Pydantic contracts;
- sanitized repository staging with secret, symlink, VCS, cache, and size filters;
- role-aware command policy with allow, approval-required, and block decisions;
- Docker resource controls and network disabled by default;
- deterministic result hard gates for paths, patch shape, scope, and secret content;
- independent patch replay in a fresh repository copy;
- redacted JSON, Markdown, JSONL, verifier-decision, and patch artifacts;
- asynchronous API jobs with idempotency, cancellation, retry, timeout, and SQLite lifecycle events;
- resumable strategy benchmarks with experiment fingerprints and failure taxonomy.
CLI / API
|
v
RunRequest -> task policy -> sanitized staged repository -> disposable sandbox
|
v
host workflow state machine
planner -> executor -> verifier
^ |
| v
repairer <- issues
|
v
trusted result gate -> redacted artifact bundle
The model can inspect, plan, edit, test, and report inside the sandbox. The host owns phase order, repair budget, command authorization, result acceptance, and artifact persistence. A verifier verdict passes only when the deterministic result gate also accepts the candidate.
See Architecture for the component and trust-boundary details.
- Python 3.10 or newer;
- Docker for the default SDK sandbox and Docker smoke;
- an OpenAI Agents SDK compatible model endpoint for real model runs.
The offline backend and most tests run without credentials or Docker.
Create the environment and run the deterministic contract demo:
make quickstartEquivalent commands:
python3 -m venv .venv
.venv/bin/python -m pip install -e '.[sdk,dev]'
.venv/bin/saferepo demoExpected evidence:
SafeRepo contract demo passed.
backend=offline (deterministic contract demo; not an LLM quality claim)
status=completed
workflow=planner -> executor -> verifier
baseline=FAIL (...)
final=PASS (...)
files_changed=src/calculator.py
source_fixture_unchanged=true
The demo repairs only a temporary fixture copy and writes artifacts under
artifacts/demo/.
Copy the environment template and set values locally:
cp .env.example .envSafeRepo does not load .env automatically. Export the required variables into
the current shell with your preferred secret-management workflow. Do not commit
the resulting file.
Run one Docker-isolated request:
.venv/bin/saferepo doctor
.venv/bin/saferepo run \
--backend sdk \
--sandbox docker \
--strategy plan-and-verify \
--repo fixtures/buggy_calculator \
--task "Make divide raise a clear ValueError when the denominator is zero."SDK mode requires OPENAI_API_KEY and SAFEREPO_MODEL. OPENAI_BASE_URL is
optional for compatible gateways. Provider exceptions are mapped to stable
credential-safe SR_* diagnostics before persistence.
Network access inside the sandbox is disabled by default. It can be enabled only
with the explicit --allow-sandbox-network flag.
| Strategy | Host-controlled path |
|---|---|
direct |
executor -> trusted result gate |
plan |
planner -> executor -> trusted result gate |
plan-and-verify |
planner -> executor -> verifier, with a bounded repair loop |
--max-repair-attempts controls verifier-requested repair inside one run.
--max-turns controls the maximum model turns per mutable phase; read-only phases
have an additional host cap.
Inspect a command without executing it:
.venv/bin/saferepo check-command \
--role executor \
--cmd "python -m unittest discover -s tests"Mutating commands that require human authorization return a stable command ID.
An exact ID can be pre-approved with --approve-command-id. Destructive commands,
privilege escalation, external writes, compound shell syntax, and boundary escapes
are blocked.
Generate a service token in the shell, then start the local API:
export SAFEREPO_API_TOKEN="$(
.venv/bin/python -c 'import secrets; print(secrets.token_urlsafe(32))'
)"
.venv/bin/saferepo serve \
--host 127.0.0.1 \
--port 8000 \
--allowed-repo-root fixturesCreate a job:
curl -sS -X POST http://127.0.0.1:8000/v1/jobs \
-H "Authorization: Bearer ${SAFEREPO_API_TOKEN}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: example-request-001" \
-d '{
"repo": "buggy_calculator",
"task": "Make divide raise a clear ValueError when the denominator is zero.",
"backend": "offline",
"sandbox": "offline",
"strategy": "plan-and-verify"
}'The service returns 202 Accepted with a run_id. Use
GET /v1/jobs/{run_id} for status and DELETE /v1/jobs/{run_id} for
cancellation. Idempotency keys are stored as keyed fingerprints; raw keys and
Bearer tokens are excluded from SQLite and artifacts.
Run the real HTTP smoke:
.venv/bin/python scripts/service_smoke.pyCredential-free policy and safety checks:
.venv/bin/saferepo eval
.venv/bin/saferepo safety-eval
.venv/bin/saferepo benchmark --backend offlineCurrent frozen contract results:
| Check | Result |
|---|---|
| Task-policy cases | 12/12 matched |
| Cross-surface safety cases | 12/12 matched |
| Adversarial actions blocked or gated | 10/10 |
| Safe controls allowed | 2/2 |
| Offline strategy cells | 45/45 trusted replay success |
| Unit and integration tests | 138/138 |
The completed real-model matrix contains 15 cases, 3 strategies, and 3 repeats:
| Strategy | Trusted success | Model requests | Observed tokens |
|---|---|---|---|
| direct | 33/45 | 467 | 3,184,327 |
| plan | 18/45 | 660 | 4,408,547 |
| plan-and-verify | 16/45 | 1,227 | 8,138,043 |
| total | 67/135 | 2,354 | 15,730,917 |
All 135 rows have complete usage and matching fixture digests. These values apply to the frozen model, endpoint, tasks, prompts, budgets, and runtime configuration. They provide a reproducible configuration-specific observation. See Evaluation for the protocol, success predicate, Wilson intervals, and failure boundaries.
Each run receives an isolated directory containing:
result.json— typed result, metadata, diagnostics, controls, observations, workflow, and command audit;report.md— human-readable summary;trace.jsonl— ordered host lifecycle events;timeline.jsonl— per-phase duration, turns, tool calls, requests, and tokens;verifier_decisions.json— verifier verdict, hard-gate state, issues, and retry reason;fix.patch— optional replayable patch, written only after redaction and secret checks.
Run the complete local gate:
make verifyThis compiles and lints the code, runs the full unittest suite, performs the tracked-content release scan, executes the contract and HTTP demos, runs policy, safety, and offline benchmark checks, and materializes a Docker sandbox fixture.
The publication scan reads Git-tracked content only. It rejects real .env files,
private absolute paths, credential literals, tracked runtime directories,
symlinks, oversized files, and workstation-local Git identities in strict mode.
- SafeRepo returns artifacts and a patch; it does not modify the source checkout.
- It does not push commits or create pull requests.
- Unix-local execution does not provide the same isolation as Docker.
- CLI approval uses exact pre-authorization; dynamic pause/resume HITL is outside the current release.
- The API queue is local and process-based; distributed scheduling is outside the current release.
- The offline backend verifies host-side contracts. Model quality is measured only by repeated SDK benchmark runs with trusted replay.
SafeRepo Agent is released under the MIT License. Open-source benchmark slices and
OpenAI Agents SDK references are documented in ATTRIBUTION.md
and each fixture's PROVENANCE.md / LICENSE.upstream files.