fix: Wire crisis_hook.check_crisis() into run_agent.py conversation loop (#677) #703

Open
Rockachopa wants to merge 3 commits from burn-677-1776207287 into main
Owner

Closes #677

Problem

The crisis detection module existed but was not called from run_agent.py's conversation loop. Crisis detection was dead code.

Fix

1. Created agent/crisis_hook.py

Simple, focused module with check_crisis() function:

  • Direct ideation patterns → level: high
  • Indirect distress patterns → level: medium
  • Returns crisis response from SOUL.md protocol

2. Wired into run_agent.py

Added crisis check in run_conversation() method:

# Before processing user message
_crisis = check_crisis(user_message)
if _crisis.detected:
    logger.warning(f"Crisis detected: {_crisis.level}")
    return _crisis.response  # Skip normal processing

3. Added tests

tests/test_crisis_hook.py:

  • Direct ideation detection
  • Indirect distress detection
  • Normal message passthrough
  • Case insensitivity
  • Response content validation

Impact

Users in crisis now receive:

  • "Are you safe right now?" as first response
  • 988 Suicide and Crisis Lifeline information
  • Gospel: "Jesus saves those who call on His name"

Files Changed

  • agent/crisis_hook.py: New module (120 lines)
  • run_agent.py: Added import and crisis check
  • tests/test_crisis_hook.py: New tests (100 lines)

Testing

python3 -m pytest tests/test_crisis_hook.py -v
Closes #677 ## Problem The crisis detection module existed but was not called from run_agent.py's conversation loop. Crisis detection was dead code. ## Fix ### 1. Created `agent/crisis_hook.py` Simple, focused module with `check_crisis()` function: - Direct ideation patterns → `level: high` - Indirect distress patterns → `level: medium` - Returns crisis response from SOUL.md protocol ### 2. Wired into `run_agent.py` Added crisis check in `run_conversation()` method: ```python # Before processing user message _crisis = check_crisis(user_message) if _crisis.detected: logger.warning(f"Crisis detected: {_crisis.level}") return _crisis.response # Skip normal processing ``` ### 3. Added tests `tests/test_crisis_hook.py`: - Direct ideation detection - Indirect distress detection - Normal message passthrough - Case insensitivity - Response content validation ## Impact Users in crisis now receive: - "Are you safe right now?" as first response - 988 Suicide and Crisis Lifeline information - Gospel: "Jesus saves those who call on His name" ## Files Changed - `agent/crisis_hook.py`: New module (120 lines) - `run_agent.py`: Added import and crisis check - `tests/test_crisis_hook.py`: New tests (100 lines) ## Testing ```bash python3 -m pytest tests/test_crisis_hook.py -v ```
Rockachopa added 3 commits 2026-04-14 23:08:45 +00:00
Part of #677. Provides check_crisis() function for conversation loop integration.
Closes #677. Crisis detection now runs before every user message is processed.
test: Add tests for crisis_hook module
Some checks failed
Contributor Attribution Check / check-attribution (pull_request) Failing after 34s
Docker Build and Publish / build-and-push (pull_request) Has been skipped
Nix / nix (ubuntu-latest) (pull_request) Failing after 7s
Supply Chain Audit / Scan PR for supply chain risks (pull_request) Successful in 34s
Tests / e2e (pull_request) Successful in 2m58s
Tests / test (pull_request) Failing after 33m9s
Nix / nix (macos-latest) (pull_request) Has been cancelled
afb036f099
Part of #677. Tests crisis detection patterns.
Timmy approved these changes 2026-04-15 00:12:42 +00:00
Dismissed
Timmy left a comment
Owner

Review: PR #703 — Wire crisis_hook.check_crisis() into run_agent.py

Overall this is a solid implementation of a critical safety feature. The pattern detection, dataclass design, and test coverage are good. A few issues to address:

1. Duplicate import (bug, minor)

agent/crisis_hook.py is imported at module level on line 79 (from agent.crisis_hook import check_crisis) AND again inside the try block at line ~7888 (from agent.crisis_hook import check_crisis). The module-level import makes the ImportError guard inside run_conversation() dead code — if the import fails, it will fail at module load time and crash the entire agent, not gracefully skip. Either remove the top-level import and rely solely on the lazy import inside the try/except, or remove the try/except and trust the top-level import.

2. Session ID logged without sanitization (minor security)

run_agent.py line ~7889: logger.warning(f"Crisis detected in session {self.session_id}: {_crisis.level}") — if session IDs ever contain user-controlled data, this could enable log injection. Low risk given the context but worth noting.

3. message_lower computed but never used

crisis_hook.py line 82: message_lower = message.lower().strip() is assigned but the regex patterns all use re.IGNORECASE via (?i) inline flags and match against the original message, not message_lower. Remove the unused variable.

4. Escaped quotes in _CRISIS_RESPONSE string

The _CRISIS_RESPONSE string uses \' escapes (e.g., I\'m here), but since the string is delimited with triple-double-quotes, single quotes don't need escaping. These work but are unnecessary noise.

5. No test for the run_agent.py integration path

All tests exercise check_crisis() in isolation, which is great. But there's no integration test verifying that run_conversation() actually returns the crisis response and short-circuits normal processing. Given this is the whole point of the PR (wiring it in), an integration test would strengthen confidence.

6. Missing "critical" level

CrisisResult.level docstring lists "critical" as a possible value, but no pattern ever returns level="critical". Either add patterns for it or remove it from the docstring to avoid confusion.

None of these are blocking. The duplicate import (#1) is the most important to fix. LGTM otherwise — the crisis detection patterns are reasonable and the SOUL.md protocol response is well-crafted.

## Review: PR #703 — Wire crisis_hook.check_crisis() into run_agent.py Overall this is a solid implementation of a critical safety feature. The pattern detection, dataclass design, and test coverage are good. A few issues to address: ### 1. Duplicate import (bug, minor) `agent/crisis_hook.py` is imported at module level on line 79 (`from agent.crisis_hook import check_crisis`) AND again inside the try block at line ~7888 (`from agent.crisis_hook import check_crisis`). The module-level import makes the `ImportError` guard inside `run_conversation()` dead code — if the import fails, it will fail at module load time and crash the entire agent, not gracefully skip. Either remove the top-level import and rely solely on the lazy import inside the try/except, or remove the try/except and trust the top-level import. ### 2. Session ID logged without sanitization (minor security) `run_agent.py` line ~7889: `logger.warning(f"Crisis detected in session {self.session_id}: {_crisis.level}")` — if session IDs ever contain user-controlled data, this could enable log injection. Low risk given the context but worth noting. ### 3. `message_lower` computed but never used `crisis_hook.py` line 82: `message_lower = message.lower().strip()` is assigned but the regex patterns all use `re.IGNORECASE` via `(?i)` inline flags and match against the original `message`, not `message_lower`. Remove the unused variable. ### 4. Escaped quotes in `_CRISIS_RESPONSE` string The `_CRISIS_RESPONSE` string uses `\'` escapes (e.g., `I\'m here`), but since the string is delimited with triple-double-quotes, single quotes don't need escaping. These work but are unnecessary noise. ### 5. No test for the `run_agent.py` integration path All tests exercise `check_crisis()` in isolation, which is great. But there's no integration test verifying that `run_conversation()` actually returns the crisis response and short-circuits normal processing. Given this is the whole point of the PR (wiring it in), an integration test would strengthen confidence. ### 6. Missing `"critical"` level `CrisisResult.level` docstring lists `"critical"` as a possible value, but no pattern ever returns `level="critical"`. Either add patterns for it or remove it from the docstring to avoid confusion. None of these are blocking. The duplicate import (#1) is the most important to fix. LGTM otherwise — the crisis detection patterns are reasonable and the SOUL.md protocol response is well-crafted.
codex-agent was assigned by Rockachopa 2026-04-15 01:17:01 +00:00
Timmy requested changes 2026-04-15 23:07:16 +00:00
Timmy left a comment
Owner

Duplicate of crisis hook wiring into run_agent.py. Please close in favor of #757 which is the most complete implementation with CrisisSeverity enum, compiled patterns, confidence scores, and proper run_agent.py integration.

Duplicate of crisis hook wiring into run_agent.py. Please close in favor of #757 which is the most complete implementation with CrisisSeverity enum, compiled patterns, confidence scores, and proper run_agent.py integration.
Some checks failed
Contributor Attribution Check / check-attribution (pull_request) Failing after 34s
Docker Build and Publish / build-and-push (pull_request) Has been skipped
Nix / nix (ubuntu-latest) (pull_request) Failing after 7s
Supply Chain Audit / Scan PR for supply chain risks (pull_request) Successful in 34s
Tests / e2e (pull_request) Successful in 2m58s
Tests / test (pull_request) Failing after 33m9s
Nix / nix (macos-latest) (pull_request) Has been cancelled
Checking for merge conflicts…
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin burn-677-1776207287:burn-677-1776207287
git checkout burn-677-1776207287
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Timmy_Foundation/hermes-agent#703