Files
microdao-daarion/runbooks/behavior-policy-v2.1.md
Apple ef3473db21 snapshot: NODE1 production state 2026-02-09
Complete snapshot of /opt/microdao-daarion/ from NODE1 (144.76.224.179).
This represents the actual running production code that has diverged
significantly from the previous main branch.

Key changes from old main:
- Gateway (http_api.py): expanded from ~40KB to 164KB with full agent support
- Router: new /v1/agents/{id}/infer endpoint with vision + DeepSeek routing
- Behavior Policy: SOWA v2.2 (3-level: FULL/ACK/SILENT)
- Agent Registry: config/agent_registry.yml as single source of truth
- 13 agents configured (was 3)
- Memory service integration
- CrewAI teams and roles

Excluded from snapshot: venv/, .env, data/, backups, .tgz archives

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 08:46:46 -08:00

6.9 KiB

Runbook: Behavior Policy v2.1

Version: 2.1
Date: 2026-02-07
Owner: NODA1 Infra
Severity: CRITICAL (affects all agent responses)


1. File Locations

File Path Purpose
Behavior Policy gateway-bot/behavior_policy.py SOWA decision logic
HTTP API (gateway) gateway-bot/http_api.py Webhook handler, computes gateway metadata
Global System Prompt prompts/global_system_prompt_v2.md Policy document for LLM
Tests tests/test_behavior_policy.py 39 unit tests
Backup (policy) gateway-bot/behavior_policy.py.bak.* Timestamped backups
Backup (http_api) gateway-bot/http_api.py.bak.* Timestamped backups
Old policy (v1) gateway-bot/behavior_policy_v1.txt Reference only

2. Quick Disable / Rollback

Option A: Rollback to backup (fastest, ~10s)

cd /opt/microdao-daarion

# List backups
ls -lt gateway-bot/behavior_policy.py.bak.*
ls -lt gateway-bot/http_api.py.bak.*

# Rollback
cp gateway-bot/behavior_policy.py.bak.20260207_085440 gateway-bot/behavior_policy.py
cp gateway-bot/http_api.py.bak.20260207_085440 gateway-bot/http_api.py

# Restart gateway
docker compose -f docker-compose.node1.yml restart gateway

Option B: Feature flag via ENV (no restart needed for next deploy)

Add to .env:

BEHAVIOR_POLICY_VERSION=v1.1

Then in http_api.py, wrap v2.1 logic:

if os.getenv("BEHAVIOR_POLICY_VERSION", "v2.1") == "v1.1":
    # Old behavior: bare mention responds
    payload_explicit_request = False
    # ... old call

Note: Option B requires code change. Option A is preferred for emergency.

Option C: Disable SOWA entirely (all agents respond to everything)

# In http_api.py, force respond_decision = True
# NOT RECOMMENDED for production — causes spam

3. Run Unit Tests

cd /opt/microdao-daarion
python3 -m pytest tests/test_behavior_policy.py -v

Expected: 39 passed

If pytest not installed:

pip3 install --break-system-packages pytest

4. Run Live Tests (7 scenarios)

All tests use chat_id=0 (prober mode — no Telegram messages sent).

# Test 1: Bare mention in group → should NOT respond
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
  -H 'Content-Type: application/json' \
  -d '{"update_id":999001,"message":{"message_id":1001,"from":{"id":12345,"first_name":"Test"},"chat":{"id":-100999,"type":"supergroup","title":"TestGroup"},"text":"@Helion","date":1738900000}}'
# Expected: {"ok":true,"skipped":true,"reason":"bare_mention_public_topic"}

# Test 2: Mention + question → should respond
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
  -H 'Content-Type: application/json' \
  -d '{"update_id":999002,"message":{"message_id":1002,"from":{"id":12345,"first_name":"Test"},"chat":{"id":0,"type":"supergroup","title":"TestGroup"},"text":"@Helion що таке Docker?","date":1738900001}}'
# Expected: {"ok":true,"agent":"helion","prober":true,...}

# Test 3: DM → always respond
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
  -H 'Content-Type: application/json' \
  -d '{"update_id":999003,"message":{"message_id":1003,"from":{"id":12345,"first_name":"Test"},"chat":{"id":0,"type":"private"},"text":"Привіт","date":1738900002}}'
# Expected: {"ok":true,"agent":"helion","prober":true,...}

# Test 4: Broadcast → should NOT respond
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
  -H 'Content-Type: application/json' \
  -d '{"update_id":999004,"message":{"message_id":1004,"from":{"id":12345,"first_name":"Test"},"chat":{"id":-100999,"type":"supergroup","title":"TestGroup"},"text":"увага всім! релізимо v2.0","date":1738900003}}'
# Expected: {"ok":true,"skipped":true,"reason":"broadcast_not_directed"}

# Test 5: Link only → should NOT respond
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
  -H 'Content-Type: application/json' \
  -d '{"update_id":999005,"message":{"message_id":1005,"from":{"id":12345,"first_name":"Test"},"chat":{"id":-100999,"type":"supergroup","title":"TestGroup"},"text":"https://github.com/project/pull/123","date":1738900004}}'
# Expected: {"ok":true,"skipped":true,"reason":"media_or_link_without_request"}

# Test 6: Question without mention → should NOT respond
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
  -H 'Content-Type: application/json' \
  -d '{"update_id":999006,"message":{"message_id":1006,"from":{"id":12345,"first_name":"Test"},"chat":{"id":-100999,"type":"supergroup","title":"TestGroup"},"text":"Хто знає чому падає сервер?","date":1738900005}}'
# Expected: {"ok":true,"skipped":true,"reason":"not_directed_to_agent"}

# Test 7: Mention + imperative → should respond
curl -s -X POST http://localhost:9300/helion/telegram/webhook \
  -H 'Content-Type: application/json' \
  -d '{"update_id":999007,"message":{"message_id":1007,"from":{"id":12345,"first_name":"Test"},"chat":{"id":0,"type":"supergroup","title":"TestGroup"},"text":"@Helion поясни що таке SOWA","date":1738900006}}'
# Expected: {"ok":true,"agent":"helion","prober":true,...}

5. Verify After Restart

# 1. Restart gateway
docker compose -f docker-compose.node1.yml restart gateway

# 2. Wait 10s
sleep 10

# 3. Check health
curl -s http://localhost:9300/health | python3 -m json.tool

# 4. Check all agents loaded
# Expected: 10 agents, all prompt_loaded=true

# 5. Run agent ping
curl -s -X POST http://localhost:9300/debug/agent_ping | python3 -m json.tool

# 6. Check logs for errors
docker logs dagi-gateway-node1 --tail 20

6. Monitor Policy Violations

Check for policy_violation in logs:

# Real-time monitoring
docker logs -f dagi-gateway-node1 2>&1 | grep 'policy_violation'

# Last 1000 lines
docker logs dagi-gateway-node1 --tail 1000 2>&1 | grep 'policy_violation'

# Count violations per agent
docker logs dagi-gateway-node1 --tail 5000 2>&1 | grep 'policy_violation' | grep -oP 'agent=\w+' | sort | uniq -c | sort -rn

Log format:

🚨 policy_violation=no_output_extra_text agent=helion chat_id=-100123 extra_text_len=45 extra_preview='Some unexpected text...'

7. Key Contracts (Do Not Break)

has_explicit_request formula

has_explicit_request = imperative
    OR (question_mark AND (is_dm OR is_reply_to_agent OR mentioned_agents not empty OR thread_has_agent_participation))

thread_has_agent_participation

  • REQUIRED field
  • If platform cannot provide → false (fail-closed)
  • Gateway MUST always pass, even as false

NO_OUTPUT contract

  • LLM must return exactly NO_OUTPUT or empty string
  • Any extra text after marker → logged as policy_violation=no_output_extra_text
  • Gateway suppresses sending to Telegram

8. Contacts

  • NODA1 Admin: @DaarionAdmin
  • Infra: SSH root@144.76.224.179
  • Monitoring: Grafana :3030 / Prometheus :9090

END OF RUNBOOK