Skip to main content

Edward

The supervisor for coding agents that run when nobody's watching.

CI jobs, overnight runs, scheduled batches — unattended agents fail quietly: the same broken test retried 40 times, rm -rf on the wrong directory, budget burned at 3am with no one to hit stop. Edward watches the event stream, builds a picture of what the agent is actually doing across turns, and intervenes when the picture stops looking right — PAUSE (resumable), CANCEL, or BLOCK — with a signed receipt for every decision.

CI PyPI downloads python license deps benchmark PRs welcome

PyPI · Benchmark · Contributing · Changelog

Agents fail quietly. Edward notices.

Edward live intervention: passive stall detected, agent cancelled at 3,589 tokens
Live run: a looping agent is stopped mid-flight — decision signed, audited, resumable.

Agents fail quietly. They retry the same broken test 40 times, burn $8 in tokens on a loop, run rm -rf on a database directory, and write to files they were never supposed to touch. The agent doesn't know it's failing — from its perspective, it's still trying.

Edward sits between the agent and its runtime. It watches the event stream, builds a picture of what the agent is actually doing across turns, and intervenes when the picture stops looking right.

Edward architecture: agent events → cross-turn state → deterministic triggers → advisory scorer → kernel decision → signed receipts

Why not just if/else?

A watchdog (error_count > 5 → stop) looks at individual events. The failure modes that actually kill long-running agents don't show up in any single event — they emerge from the shape of the trajectory over time. We tested this directly on held-out data (seed 137, frozen config):

Scenario Watchdog Edward (State Engine) Watchdog ctx Edward ctx
budget bleed 20% 100% 2,322 409
infinite loop 0% 100% 6,084 409
convergence stall 0% 100% 1,442 409
dangerous command 75% 100% 522 434

Watchdogs miss temporal failure modes entirely because they have no memory across turns. Edward maintains a sliding window of tool calls, tracks file modifications, and computes elapsed time — none of which fit in a single-event check.

Measured, not claimed

Edward validates itself against StepShield (NeurIPS 2026), the first benchmark treating intervention timing as a first-class metric (9,429 trajectories, step-level labels, 216 held-out):

Detector Recall FPR (clean) EIR₃ (timing) Cost / decision
LLMJudge (GPT-4.1-mini, paper) 95.4% 5.6% 0.89 GPT-4.1-mini price
Edward contract probe (Jev 1.13) 59.3% 10.2% 0.91 ~$0.0001, one batched call
Edward contract probe (local 4B) 58.3% 17.6% 0.78 ~$0.00002, on your GPU
Edward rules only 7.4% — — 0
HybridGuard (paper) 75.9% 44.4% 0.40 —
StaticGuard 847 rules (paper) 86.1% 77.8% 0.23 —

The deterministic layer alone is quantitatively blind to content-semantic violations (7.4%) — the "silent corruption" gap — while keeping the best false-positive rate. Swapping the judgment backend changes the trade, not the architecture: the local 4B keeps events on your network at zero marginal cost; TypeSafe Jev lifts EIR₃ above the paper's GPT-4.1-mini judge (0.91 vs 0.89) with 42% fewer false positives, one batched calibrated call per probe battery. Trajectory-level recall is the shared frontier for small judges — we measure and publish it rather than claim it away. Full series, raw logs, reproduction commands: BENCHMARK.md.

StepShield holdout: EIR3 by system and cost-vs-quality scatter

StepShield holdout recall by attack family: Jev 1.13 vs local 4B

External benchmarks: RedCode-Exec recognition and ATBench F1

What it detects

Eight trigger rules, tuned on a dev split (seed 42) and frozen for held-out evaluation (seed 137):

Signal Fires when
Error rate > 40% over the last 8+ calls, no recovery signal
Retry count ≥ 3 retries of the same thing
Token budget > 80% consumed
Convergence stall > 600s + > 5 turns, no completion
Passive stall 12 consecutive reads, 0 writes
Dangerous command rm -rf, sudo, git push --force, `curl
Scope violation writes outside the allowed path prefixes
Silent corruption risk ≥ 10 consecutive file writes with zero shell verification

Policy packs make the knobs yours: conservative / balanced (= FROZEN defaults) / aggressive, as TOML or JSON.

Quickstart

pipx install edward-guard            # zero dependencies, Python 3.11+

edward doctor                        # environment checks
edward demo                          # self-running proof: 6 failure scenarios, PASS/FAIL
edward demo --live-scorer --offline  # same proof through the full scorer pipeline (heuristic stub, no GPU)

edward wrap -- pi "fix the flaky test"                     # full monitoring + intervention
edward wrap --no-scorer -- python my_agent.py              # any command, rule-only
edward wrap --scope ./src --auto-resume 60 -- pi "task"    # scoped writes, auto-resume
$ edward demo
policy: balanced  trials/scenario: 3

scenario             expect     result        latency
-----------------------------------------------------
normal               no-fire    clean               —  ok
transient_failure    no-fire    clean               —  ok
infinite_loop        fire       100% detected      8.0  ok
budget_bleed         fire       100% detected     12.0  ok
dangerous            fire       100% detected      4.7  ok
stall                fire       100% detected      4.0  ok

PASS in 0.0s (deterministic rules frozen defaults; scorer off)

Real output, not a mock — six failure scenarios against the frozen rule set, plus the two clean controls. Wraps any subprocess: Pi, Codex, claude -p, CI jobs, plain scripts. --agent auto|generic|pi picks the adapter (pi gets native RPC; the registry is extensible via edward.adapters entry points).

Interventions are resumable, not fatal: PAUSE exits with code 75, pins the agent session, and edward wrap --continue picks the same session back up from the audit log. CANCEL / BLOCK exit 76. Audit lands in ~/.edward/audit.jsonl — including an estimated avoided-spend per intervention.

The scorer is optional and always advisory. Point EDWARD_SCORER_URL at any local OpenAI-compatible scoring endpoint (a 4B model on your GPU box is plenty — see deploy/ for the team-LAN topology). Scorer down? Edward logs a warning and runs rule-only. It stays protective.

Pluggable scorer backends. EDWARD_SCORER_BACKEND selects where judgments come from: endpoint (default — the LAN scorer server above), jev (TypeSafe Jev — all probes batched into one calibrated call; set TYPESAFE_API_KEY), or heuristic (deterministic marker stub for offline demos and tests). edward doctor shows the active backend. All backends are advisory and share the same circuit breaker.

Edward + Jev — who decides what. With the jev backend (edward/backends.py), one Jev call receives the full cross-turn state (error trends, write streaks, budget) and returns calibrated judgments — should this trajectory continue, pause, or escalate, and how confident is that? Deterministic code owns everything irreversible: blocklists, scope checks, budget caps, intervention execution, and the signed receipt chain. Jev's confidence gates routing, never actions. Known limitation: the local-4B and Jev paths trade recall differently (see BENCHMARK.md for measured numbers and reproduction commands).

v0.3.0 highlights

  • Pluggable scorer backends — EDWARD_SCORER_BACKEND selects endpoint (your LAN 4B), jev (TypeSafe Jev: all probes in one batched calibrated call), or heuristic. edward demo --live-scorer --offline runs the full rules+scorer pipeline with no GPU and no API key.
  • Agent adapter registry — --agent auto|generic|pi|<plugin>; third-party adapters join via the edward.adapters entry-point group.
  • Process-tree interventions — pause/kill terminate the whole agent subtree (POSIX process groups, Windows CTRL_BREAK + taskkill /T) — no more orphaned npm/python children.
  • v0.2.0 added signed evidence receipts (Ed25519 hash chain, offline edward verify) and the human approval loop (--wait-approval 300).
resume from audit + offline receipt verification

Unattended runs & CI

Edward is built for agents nobody is watching. In a workflow:

- uses: VeridicalTech/Edward@main
  with:
    command: 'pi "fix the flaky test"'
    policy: balanced          # or a path to your policy TOML
    max-seconds: 1800
    # scorer-url: http://gpu-box.lan:8000   # optional local 4B judge

The command runs under supervision. If Edward intervenes — loop, stall, budget bleed, dangerous command — the job fails with a ::warning and the Ed25519 receipt trail is uploaded as an artifact, so the 3am failure comes with evidence instead of a silent $12 bill. edward verify runs in-pipeline: tampered audit logs fail the build.

Why zero dependencies?

Edward's control loop runs stdlib-only: it must boot on any Python 3.11+ box, inside any container, in front of any agent — including air-gapped ones. The heavy lifting (scoring) is delegated to a separate local service, which you own and can swap (4B quantized, bigger, whatever) without touching the control plane.

Repository map

edward/                the package
  cli.py               wrap / demo / eval / audit / doctor
  engine.py            ControlPlane: events → triggers → scorer → decision → audit
  state_engine.py      cross-turn agent state
  triggers.py          8 rules, policy-parameterized (defaults FROZEN)
  scorer_client.py     /v1/score client + circuit breaker
  stepshield.py        external benchmark adapter (EIR metrics)
  scenarios.py         failure scenario suite (demo/eval source of truth)
benchmark.py           300-trial held-out benchmark
robustness_eval.py     4-dimension robustness attack
BENCHMARK.md           full measurement series + reproduction commands
deploy/                team-LAN deployment templates

Status & roadmap

  • v0.3.0 on PyPI: scorer backends (endpoint / Jev / heuristic), agent adapter registry, process-tree hardening
  • StepShield integration with paper-aligned EIR metrics — including the Jev 1.13 backend row (EIR₃ 0.906)
  • Scorer fine-tune — attempted and abandoned under a pre-registered two-strike protocol (post-mortem in BENCHMARK.md)
  • Robustness suite as edward eval --suite robustness
  • Cloud fleet console (team tier)

Ecosystem

  • JevTree — Jev-native probability-tree planner for multi-step decisions. Complementary layers: JevTree reasons about which path to take (candidate expansion, Pareto selection over utility, probability, risk and reversibility); Edward supervises whether the executed path stays safe, in-scope, and convergent (hard constraints, semantic risk, pause/resume, signed receipts). A natural integration: JevTree expands and scores candidates → Edward gates them → JevTree selects → Edward supervises execution → receipts feed the replan.

Building a Jev-ecosystem tool that touches agent execution? Edward's adapter registry (edward.adapters entry points) and scorer backends are designed as extension points — open an issue.

Contributing

Deterministic layer stays deterministic: trigger defaults are FROZEN, and behavior-affecting changes require re-running the benchmark gate. See CONTRIBUTING.md.

License

MIT — © 2026 Edward contributors

Metadata

Release files for edward-guard 0.4.0

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

Source distribution (sdist)

Source distribution for edward-guard 0.4.0
File Size Uploaded Provenance Actions
edward_guard-0.4.0.tar.gz 63.7 kB Without provenance Details for edward_guard-0.4.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for edward-guard 0.4.0
File Interpreter ABI Platform Actions
edward_guard-0.4.0-py3-none-any.whl Python 3 none any Details for edward_guard-0.4.0-py3-none-any.whl

Total release size: 130.3 kB

Release files / edward_guard-0.4.0.tar.gz

Download URL edward_guard-0.4.0.tar.gz
Size 63.7 kB
Tags Source
SHA-256 checksum
How to use checksums
6a89f15afdb347e3e7a72d3d8a7173b13b271f38ba27009998091d906cb79ac3
BLAKE2b-256 checksum
How to use checksums
707c292b9029453768ab1a52be5acf8fc6ea3615d5831f7a59880742c4a5c34f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / edward_guard-0.4.0-py3-none-any.whl

Download URL edward_guard-0.4.0-py3-none-any.whl
Size 66.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
599a424e7412b17470755dbd8850c0a6c78a51586962c6a8b944fe835ece62d0
BLAKE2b-256 checksum
How to use checksums
69a28800a3e7a9add6999e5ae76cb4db17505b3907e11bcc6b2de45a963fdf56
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Security for edward-guard 0.4.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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