Human‑in‑the‑Loop Architecture Primer
A repeatable, auditable workflow turns a proposal into an execution only after a deterministic series of checks. By binding the human‑approval token to the exact payload, the decision becomes a verifiable part of the transaction rather than a post‑hoc disclaimer.
The architecture distinguishes four sources of truth:
- Current knowledge – stored in the context or retrieval component.
- Live values – obtained from authoritative APIs at request time.
- Enforceable business rules – expressed as deterministic code that must be satisfied before any state change.
- Model tuning – performed after systematic evaluation and labeling; it supplements but does not replace rule‑based enforcement or freshness checks.
Quick‑Diagnosis Table
| Symptom | Likely Root Cause | Immediate Mitigation |
|---|---|---|
| Unauthorized data mutation after automation | Approval not cryptographically tied to payload | Introduce payload hash in the approval token |
| Escalating reviewer backlog on high‑risk actions | Flat approval process regardless of impact | Tier risk and assign reviewer capacity |
| Irreversible financial adjustments cannot be rolled back | Execution step runs before final sign‑off | Enforce exact‑action approval as the last gate |
| Audit logs missing key fields | Logging tied to mutable objects | Serialize immutable request snapshots |
Decision Flow
flowchart TD A["Proposal"] --> B["Risk‑Policy Evaluation"] B --> C["Tier Assignment"] C --> D["Exact‑Action Approval"] D --> E["Execution"] E --> F["Immutable Audit Record"] The flow consists of Proposal → Risk‑Policy → Exact‑Action Approval → Execution. The final audit record captures the hash‑bound token, tier, reviewer identifiers and timestamps.
Architecture Responsibilities
| Component | Primary Responsibility | Guarantees (intent) |
|---|---|---|
| Proposal Engine | Emit a JSON payload describing the intended mutation; compute a deterministic SHA‑256 hash | Payload immutability (via hash) |
| Risk‑Policy Service | Apply deterministic rules, assign a risk tier, and expose a risk score | Consistent tier assignment |
| Approval Service | Present the exact payload + hash to a reviewer; on sign‑off, issue a signed token containing the hash | Human decision binding |
| Execution Engine | Verify token signature and payload hash before invoking downstream actions | Tamper‑evidence |
| Audit Logger | Persist an immutable event (e.g., append‑only log) with full payload, hash and approval token | Non‑repudiation |
Python Helper – Decision & Payload Binding
# -*- coding: utf-8 -*- """ Teaching‑only helper that demonstrates: 1. deterministic risk tiering, 2. creation of a hash‑bound approval token, 3. verification before execution. All dependencies are from the Python standard library. """ import json import hashlib import hmac import time from typing import Dict, Literal, TypedDict # ---------------------------------------------------------------------- # Types # ---------------------------------------------------------------------- class Payload(TypedDict): action: str # e.g. "adjust_credit_limit" entity_id: str # unique identifier of the subject parameters: Dict[str, float] # e.g. {"value_change": 25000.0} requested_by: str # service or user ID RiskTier = Literal[1, 2, 3] # ---------------------------------------------------------------------- # Deterministic risk policy # ---------------------------------------------------------------------- def risk_tier(payload: Payload) -> RiskTier: """ Simple deterministic rule set. - Tier 1: value_change < 1 000 and reversible - Tier 2: value_change < 10 000 and reversible - Tier 3: otherwise (potentially irreversible) """ change = payload["parameters"].get("value_change", 0.0) irreversible = payload["parameters"].get("irreversible", False) if change < 1_000 and not irreversible: return 1 if change < 10_000 and not irreversible: return 2 return 3 # ---------------------------------------------------------------------- # Payload hashing # ---------------------------------------------------------------------- def payload_hash(payload: Payload) -> str: """ Returns a hex‑encoded SHA‑256 over the canonical JSON representation. """ canonical = json.dumps(payload, sort_keys=True, separators=(",", ":")) return hashlib.sha256(canonical.encode("utf-8")).hexdigest() # ---------------------------------------------------------------------- # Token creation (illustrative only) # ---------------------------------------------------------------------- SECRET_KEY = b"super‑secret‑key‑rotate‑daily" def create_approval_token(payload: Payload, reviewer: str) -> str: """ Very simple JWT‑like token: header.body.signature. Intended for teaching – a production system should use a robust JWT library. """ header = json.dumps({"alg": "HS256", "typ": "JWT"}).encode() body = json.dumps( { "sub": reviewer, "iat": int(time.time()), "hash": payload_hash(payload), } ).encode() signature = hmac.new(SECRET_KEY, header + b"." + body, hashlib.sha256).hexdigest() token = f"{header.hex()}.{body.hex()}.{signature}" return token # ---------------------------------------------------------------------- # Verification before execution # ---------------------------------------------------------------------- def verify_and_execute(payload: Payload, token: str) -> None: """ Confirms that the token’s hash matches the supplied payload. Raises AssertionError on mismatch – in a real system this would abort the transaction. """ header_hex, body_hex, signature = token.split(".") body = json.loads(bytes.fromhex(body_hex)) expected_hash = payload_hash(payload) assert body["hash"] == expected_hash, "Payload hash mismatch – possible tampering" expected_sig = hmac.new( SECRET_KEY, f"{header_hex}.{body_hex}".encode(), hashlib.sha256 ).hexdigest() assert signature == expected_sig, "Invalid approval signature" # ----- Execution placeholder ----- print(f"Executing {payload['action']} for {payload['entity_id']} …") # Replace with an idempotent, atomic operation in production. # ---------------------------------------------------------------------- # Example usage (not executed in docs) # ---------------------------------------------------------------------- if __name__ == "__main__": example: Payload = { "action": "adjust_credit_limit", "entity_id": "cust-12345", "parameters": {"value_change": 2_500.0, "irreversible": False}, "requested_by": "loan‑engine", } tier = risk_tier(example) assert tier == 2, "Tier assignment mismatch in example" token = create_approval_token(example, reviewer="compliance‑officer") verify_and_execute(example, token) Teaching‑Only – The code uses only the standard library and a fixed secret key for clarity. Replace the token logic with a production‑grade JWT implementation and rotate secrets regularly.
Architectural Decision Records (ADRs)
ADR 001 – Payload‑Hash Binding
Context
Early prototypes stored the human sign‑off flag in a mutable column. Audits later revealed that downstream services could modify the underlying request after approval, weakening accountability.
Decision
Include a cryptographic hash of the exact payload in the approval token. Execution components must verify the hash before performing any state change.
Implications
- Positive – Provides evidence that the approved payload has not been altered. Auditors can recompute the hash from immutable logs.
- Negative – Legitimate changes (e.g., enrichment) require a new approval round, which may increase latency for low‑risk items.
Acceptance Criteria
- Audit logs contain both the payload hash and the approval token.
- Unit tests confirm that modifying a payload after token issuance raises an
AssertionError.
ADR 002 – Tier‑Based Reviewer Load Balancing
Context
A single compliance team was overloaded by a mix of low‑ and high‑risk proposals, causing SLA pressures for high‑impact actions.
Decision
Define three deterministic risk tiers with distinct reviewer requirements:
| Tier | Max Δ Value | Irreversibility | Reviewers Required |
|---|---|---|---|
| 1 | < 1 000 | No | 0 (auto‑approve after sanity check) |
| 2 | < 10 000 | No | 1 (single reviewer) |
| 3 | ≥ 10 000 | Yes | 2 (dual sign‑off) |
Tier 1 proposals are routed to an automated sanity check; Tier 3 actions trigger a dedicated dual‑approval queue.
Implications
- Positive – Reviewer effort aligns with risk, reducing backlog for high‑impact changes.
- Negative – The tiering function must remain deterministic; any change to the rule set requires a versioned policy rollout.
Acceptance Criteria
- Simulated runs confirm that identical payloads are consistently assigned the same tier across service versions.
- Policy version is recorded with each decision; a mismatch between recorded and expected version causes the decision to be rejected.
Evaluation & Maintenance Checklist
- [ ] Deterministic Policy – Verify that the risk‑policy service returns the same tier for identical payloads across successive runs.
- [ ] Hash Integrity – Run a periodic job that recomputes payload hashes from audit logs and compares them to stored token hashes.
- [ ] Signature Rotation – Rotate the signing secret on a defined schedule; ensure services accept both current and previous keys during overlap.
- [ ] Reviewer Load Monitoring – Track average queue time per tier; adjust staffing or automation when thresholds are exceeded.
- [ ] Irreversibility Guardrail – For Tier 3 actions, require an explicit “I understand this is irreversible” acknowledgment, logged as a separate event.
- [ ] Regulatory Change Process – When new regulations appear, update the risk‑policy rule set, increment the policy version, and back‑test against historic proposals before production rollout.
- [ ] Test Coverage – Include unit tests for
risk_tier,payload_hash, and token verification; add integration tests that simulate a full proposal → execution flow.
References
- Microsoft Retrieval‑Augmented Generation concepts: https://learn.microsoft.com/en-us/azure/foundry/concepts/retrieval-augmented-generation
- LoRA: Low‑Rank Adaptation of Large Language Models, arXiv 2106.09685: https://arxiv.org/abs/2106.09685
End of guide.

