A Strands Agents agent that works in the background and surfaces only when there's a real human decision — then stops, waits, and resumes to do exactly what was approved. Nothing more.
Most agent demos optimize for autonomy: let it run, let it act, review the aftermath. This project inverts that. The agent runs a bounded job, gathers evidence, and when it reaches a decision that belongs to a human, it emits a typed decision request and halts. A human approves or rejects. The agent resumes from its persisted session, executes only the approved action, and returns a report that ties the outcome back to the decision that authorized it.
- Receive a bounded job (task packet with explicit authority).
- Collect evidence and prepare a proposed action.
- Emit a typed human decision request — question, options, evidence, consequences.
- Stop. No execution before approval, no "ask forgiveness" path.
- Resume from the same persisted run after the human approves or rejects.
- Execute only the approved action.
- Produce a typed report connecting the decision to the outcome.
The decision request is not a confirmation dialog. It is a structured artifact: what the agent wanted to do, why, what evidence supported it, what it was forbidden from doing, and what would have happened on the other branch. Every stop has a reason. Every resume references the decision that unlocked it.
Because that's the only question that matters when an agent surfaces from the background. Not "what did it do?" — you can read a log for that. The interesting moment in any agentic system is the transfer of judgment: when does the machine decide, and when does the human? This project takes a hard line: authority is explicit, declared up front in the task packet, and never silently transferred.
Being built for the Agents for Humans hackathon (AWS / Strands Agents SDK), September 2026. The core loop is proven: a real Strands agent on Bedrock stops at a typed decision request, resumes on a recorded human decision, and every artifact validates against the vendored HACP schemas. See docs/roadmap.md and docs/spike-log.md for evidence.
npm installThe decision console is deterministic and needs no model credentials. It starts in public, read-only watch mode; running the demo requires operator sign-in.
-
Choose a long operator passcode and generate its SHA-256 hash. Replace the placeholder below with your chosen passcode (this command works on macOS and Linux with Node installed):
node -e 'console.log(require("node:crypto").createHash("sha256").update(process.argv[1]).digest("hex"))' 'your-long-operator-passcode'
-
Add the following to
.env.localin the repository root, replacing the placeholder with the generated 64-character hash. This file is gitignored; store the hash here, not the passcode itself. Next.js loads it automatically.WD_OPERATOR_PASSCODE_HASH=<paste-the-generated-hash>
-
Start the console:
npm run console
-
Open http://localhost:3100, expand Operator sign-in, enter the original passcode, and select Sign in. Run the demo then appears. Use
localhostfor local browser access; the session cookie isSecure. Restart the console after changing.env.local. Without a valid hash, sign-in fails closed and the console stays read-only.
# Tests (all offline; CI runs the same plus the contention proof)
npx tsc --noEmit
npm run test:auth # operator sessions, mutation guards, login rate limit
npm run test:console # engine: branches, idempotency, crash recovery, reset
npm run test:artifacts # schema validation incl. tamper-rejection
npm run test:consumption # consume-once claims, races, expiry, replay
npm run test:live-loop # the live script's decision flow (synthetic runtime)
npm run scenario # end-to-end artifact spine, deterministicThe console stores runs and consumption receipts in SQLite by default
(zero-config local demo). Setting WD_STORE=postgres swaps in the Postgres
adapters for the hosted demo — engine logic is unchanged:
WD_STORE=postgres
WD_PG_URL=postgres://user:password@host:5432/database # or DATABASE_URL
# Discrete fallbacks: WD_PG_HOST / WD_PG_PORT / WD_PG_USER / WD_PG_PASSWORD / WD_PG_DATABASEBoth stores live in the same database; the adapter creates its tables
idempotently on first use (initialize). The Postgres suites mirror the
SQLite contract — claims and contention semantics included — and run against
any disposable database, skipping green when unset:
WD_TEST_PG_URL=postgres://postgres@127.0.0.1:55440/wd_test npm run test:pgWD_PROVIDER=bedrock AWS_PROFILE=who-decides npm run live-loopOne real agent run end to end: invocation A stops at exactly one
HUMAN_DECISION_REQUIRED interrupt, a scripted decision is claimed exactly
once (the claim gates execution), invocation B resumes from the session and
executes only the approved branch as a dry-run. Artifacts land in
.tmp/live-run/<tag>/. Set WD_LIVE_TAG (filename-safe slug) to name a run;
rerunning a consumed tag stops typed. An OpenAI-compatible escape hatch exists
via WD_PROVIDER=openai-compatible with WD_BASE_URL/WD_MODEL/WD_API_KEY.
Pull requests are reviewed by Codex under the
ACK lane under
.agent-control/lanes/pr-review-loop.yaml (see
docs/ack-startup-guide.md). Normal feature PRs
target dev; promotion to main is a separate human-mediated PR. Merge
commits only, never squash. Qodo remains disabled.
The decision console (npm run console, port 3100) is a single-operator
demo with public watch mode:
- State is publicly readable. Starting runs, submitting decisions, resetting
the console, and probing duplicate resumes require a server-side operator
session issued after passcode sign-in. Sessions expire after 12 hours;
the browser carries a
Secure,HttpOnly,SameSite=Strictcookie. - Authenticated console decisions record the originating operator session in
the HACP human-decision artifact. This is shared-passcode authentication,
not individual user accounts. Engine/CLI callers without an authenticated
channel retain explicit
demo-unauthenticated-local-consoleattribution. - Public hosting requires HTTPS and the reverse proxy setup in
deploy/PROVISION.md.
npm run consoleis the local development server; the hosted deployment uses a production build. - The prepared effect is always a dry-run: the exact payload is recorded and shown, and no external mutation is performed in any branch.
- Resetting the console archives the current run; completed run records and artifacts stay in the local database for audit.
This repository is a new project, but it builds on disclosed prior work by the same author and on open-source libraries. See docs/disclosure.md for the full list, notably:
- HACP — Human-Approved Coordination Protocol: pre-existing conceptual work. Its machine-readable schemas (Apache-2.0) are incorporated here with attribution and drive the typed artifacts in this demo.
- Strands Agents SDK (Apache-2.0, AWS).
Apache-2.0 — see LICENSE.