Brief cho Claude Code: lỗi nhận sai phòng ban / Telegram topic trong CEO AI OS
Mục tiêu
Xử lý triệt để lỗi CEO AI OS / Hermes Gateway nhận sai phòng ban khi người dùng nhắn trong các Telegram forum topic khác nhau.
Kỳ vọng cuối cùng:
- Tin nhắn trong mỗi Telegram topic phải được route vào đúng session theo
chat_id + thread_id. - Tool subprocess, đặc biệt
terminal, phải nhận đúng metadata của turn hiện tại. python3 lib/whereami.py --debugphải trả đúngchat_id,thread_id,session_id,session_keycủa chính message đang xử lý.- Chỉ sau khi nguồn metadata ổn định mới được lưu mapping
department/topic name -> thread_id.
Bối cảnh hệ thống
Project chính:
/opt/ai-os/products/ceo
Hermes runtime đang dùng:
/usr/local/lib/hermes-agent
Gateway/session store:
/root/.hermes/sessions/sessions.json- SQLite/session_search cũng có transcript các turn đã xử lý.
Telegram group đang debug:
- Group:
AI Native Lab Group chat_id:-1003833933494- User debug: Michael Aurora / Telegram user id
1604824313
Helper đang dùng để hỏi phòng ban:
/opt/ai-os/products/ceo/lib/whereami.py
Lệnh test:
python3 lib/whereami.py --debugTriệu chứng chính
Người dùng nhắn trong nhiều Telegram forum topic khác nhau, nhưng bot/tool thường trả cùng một thread_id, hoặc nhận context không phải group mà là DM.
Các case đã thấy:
Case A — tin nhắn ở topic có chữ sg
Người dùng hỏi:
> Xin chào, tôi là Michael, hãy vui lòng cho tôi biết tôi đang ở phòng ban nào và thread id là gì, session lưu ở đâu để tôi thực hiện mapping (sg)?
Output từ whereami.py --debug từng trả:
chat_id:-1003833933494thread_id:59session_key:agent:main:telegram:group:-1003833933494:59- topic:
nulldo mapping đã reset
Tạm hiểu: topic sg có thể là thread 59, nhưng chưa được xác nhận làm mapping chính thức.
Case B — ảnh chụp từ topic Marketing
Người dùng nói ảnh đó là tin nhắn ở topic Marketing, không có chữ sg, nhưng bot cũng từng trả thread_id = 59.
Tra transcript/session store cho message trong ảnh cho thấy message nằm ở:
session_id:20260625_131117_22a790c2session_key:agent:main:telegram:group:-1003833933494:81origin.thread_id:81origin.message_id:3868
Nhưng trong chính turn đó, terminal tool chạy whereami.py lại trả 59.
Kết luận từ case này:
- Transcript/session store nói message thuộc thread
81. - Tool subprocess lại thấy env/session của thread
59. - Đây là mismatch giữa session của agent/transcript và session env mà tool nhận.
Case C — sau restart, vẫn sai và còn thấy context DM
Sau khi patch và restart gateway, user hỏi lại trong group/topic:
> phòng hiện tại là phòng nào, có thread id là gì
Tool subprocess nhận env như sau:
{
"HERMES_SESSION_ID": "20260625_164941_4f5943fb",
"HERMES_SESSION_KEY": "agent:main:telegram:dm:1604824313",
"HERMES_SESSION_CHAT_ID": "1604824313",
"HERMES_SESSION_THREAD_ID": "81",
"HERMES_SESSION_MESSAGE_ID": "195",
"HERMES_SESSION_USER_ID": "1604824313",
"HERMES_SESSION_PLATFORM": "telegram"
}Tức là user đang hỏi trong group/topic, nhưng terminal tool lại thấy:
session_key:agent:main:telegram:dm:1604824313chat_id:1604824313
Đây là context DM, không phải group:
- expected dạng group:
agent:main:telegram:group:-1003833933494:<thread_id>
whereami.py sau đó phải fallback sang group session mới nhất trong sessions.json, nên có lúc trả 3832, có lúc trả 59. Các giá trị fallback này không đáng tin để mapping.
Mapping hiện tại không đáng tin
Mapping cũ từng có trong memory/index:
- Marketing =
668 - IT =
81 - AI Mentor =
533 - Website =
3709 - Strategy & Growth =
59
Nhưng mapping này đã bị đánh dấu không đáng tin vì thực tế Telegram UI và session store mâu thuẫn.
Hiện tại đã reset mapping phòng ban của user về {} để tránh bot trả tên phòng sai.
Yêu cầu: không lưu mapping mới cho đến khi whereami.py --debug cho thấy các nguồn metadata khớp nhau.
File đã chỉnh
1. /opt/ai-os/products/ceo/lib/whereami.py
Đã sửa để không chỉ tin HERMES_SESSION_THREAD_ID nữa.
Logic mới:
- Ưu tiên
HERMES_SESSION_ID-> tra/root/.hermes/sessions/sessions.json-> lấysession_key/origin.thread_id. - Nếu không có, parse
HERMES_SESSION_KEY. - Nếu không có nữa, mới dùng
HERMES_SESSION_CHAT_ID+HERMES_SESSION_THREAD_ID. - Cuối cùng mới fallback sang group session mới nhất.
Có mode debug:
python3 lib/whereami.py --debugMode này trả evidence các nguồn:
- env/context
- session id/key
- record trong
sessions.json - source mà helper dùng để kết luận
2. /usr/local/lib/hermes-agent/gateway/run.py
Đã patch _set_session_env() để truyền thêm session_id=context.session_id vào set_session_vars().
Trước patch, _set_session_env() truyền:
- platform
- chat_id
- chat_name
- thread_id
- user_id
- user_name
- session_key
- message_id
Nhưng thiếu:
session_id
Patch đã thêm:
session_id=context.session_id,Kết quả compile check OK:
/usr/local/lib/hermes-agent/gateway/run.pyOK/usr/local/lib/hermes-agent/gateway/session_context.pyOK/usr/local/lib/hermes-agent/tools/environments/local.pyOK
Test giả lập set_session_vars() + _make_run_env() sau patch cho thấy env inject đúng nếu context đúng:
- case thread
81-> env raHERMES_SESSION_KEY=...:81,HERMES_SESSION_THREAD_ID=81 - case thread
59-> env raHERMES_SESSION_KEY=...:59,HERMES_SESSION_THREAD_ID=59
Nhưng sau restart thật, bug vẫn còn vì context đi vào tool có thể đã là DM hoặc stale trước đó.
Kết luận kỹ thuật hiện tại
Patch session_id là đúng nhưng chưa đủ.
Root cause hiện tại nhiều khả năng nằm sâu hơn ở lớp gateway / runtime binding session context:
- Agent/transcript có thể nằm ở session group topic đúng, ví dụ thread
81. - Terminal tool subprocess lại nhận
HERMES_SESSION_*của thread khác, ví dụ59, hoặc nhận context DMagent:main:telegram:dm:1604824313. - Điều này chứng tỏ tool runtime không luôn được bind với đúng
SessionContextcủa turn hiện tại.
Điểm đáng nghi trong /usr/local/lib/hermes-agent/gateway/run.py:
os.environ["HERMES_SESSION_KEY"] = session_key or ""Dòng này nằm trong run_sync() quanh line khoảng 14340.
Comment nói session_key đã set qua contextvars, nhưng code vẫn ghi vào os.environ process-global:
os.environlà global cho cả gateway process.- Trong môi trường gateway xử lý nhiều message/task, global env có thể làm bẩn context giữa DM/group/topic.
- Có thể các đoạn fallback hoặc subprocess env vẫn lấy giá trị stale từ
os.environ.
Cần kiểm tra kỹ đoạn này và các đoạn tương tự với HERMES_SESSION_*.
Các file/code path cần Claude Code tập trung kiểm tra
Gateway session context
/usr/local/lib/hermes-agent/gateway/session_context.py
Kiểm tra:
_VAR_MAPset_session_vars()clear_session_vars()get_session_env()
Hiện get_session_env() ưu tiên ContextVar, sau đó mới fallback os.environ.
Gateway run flow
/usr/local/lib/hermes-agent/gateway/run.py
Điểm cần trace:
- Message inbound được convert thành
SessionSourcenhư thế nào. session_keyđược build từsource.chat_id+source.thread_idra sao._handle_message_with_agenthoặc equivalent gọibuild_session_context()và_set_session_env()ở đâu.run_sync()được chạy qua_run_in_executor_with_context()có bảo toàn ContextVar đúng không.- Có đoạn nào ghi
HERMES_SESSION_*vàoos.environsau_set_session_env()không. - Có đoạn nào clear/reset contextvars quá sớm, trước khi tool call chạy xong không.
- Agent/tool dispatch có chạy trong thread/task khác không copy đúng context không.
Terminal subprocess env injection
/usr/local/lib/hermes-agent/tools/environments/local.py
Đoạn _make_run_env() inject ContextVar vào subprocess env:
from gateway.session_context import _UNSET, _VAR_MAP
for var_name, var in _VAR_MAP.items():
value = var.get()
if value is not _UNSET and value:
run_env[var_name] = valueCần xác nhận khi terminal tool chạy thật:
var.get()đang ra context của group/topic hiện tại hay DM/stale.- Nếu var là empty string thì có bị fallback sang
os.environstale trước đó không. - Có cần loại bỏ fallback hoặc clear các
HERMES_SESSION_*global khỏi subprocess env trước khi inject ContextVar không.
Terminal tool
/usr/local/lib/hermes-agent/tools/terminal_tool.py
Kiểm tra tool gọi environment execute như thế nào, có truyền env {} hay merge os.environ ra sao.
Hypothesis cần xác minh
Hypothesis 1 — os.environ global làm bẩn context
Một hoặc nhiều biến HERMES_SESSION_* vẫn bị ghi vào process global env. Sau đó _make_run_env() merge os.environ | env, rồi chỉ override các var nếu ContextVar có value truthy.
Nếu ContextVar thiếu hoặc empty, subprocess sẽ thừa hưởng stale env.
Cần kiểm tra tất cả chỗ ghi:
HERMES_SESSION_KEYHERMES_SESSION_IDHERMES_SESSION_CHAT_IDHERMES_SESSION_THREAD_IDHERMES_SESSION_MESSAGE_IDHERMES_SESSION_USER_ID
Hypothesis 2 — ContextVar không được copy qua đúng thread/tool execution path
Gateway có helper:
async def _run_in_executor_with_context(self, func, *args):
loop = asyncio.get_running_loop()
ctx = copy_context()
return await loop.run_in_executor(None, ctx.run, func, *args)Cần xác nhận toàn bộ agent/tool execution thật sự chạy bên trong context này. Có thể một số tool call hoặc nested execution chạy ngoài copied context.
Hypothesis 3 — Telegram inbound source bị parse sai thành DM
Sau restart vẫn thấy group question nhưng env tool là DM:
agent:main:telegram:dm:1604824313
Cần kiểm tra adapter Telegram tạo SessionSource ra sao cho message trong forum topic:
chat_idphải là group id-1003833933494chat_typephải làgroupthread_idphải là Telegrammessage_thread_id- không được convert thành DM user id
1604824313
Nếu inbound source đúng là DM thì bug nằm trước session context: platform adapter / event routing.
Nếu inbound source là group nhưng tool env là DM thì bug nằm giữa session context và tool dispatch.
Cách debug đề xuất
Thêm logging tạm thời hoặc debug hook ở 4 điểm, cùng một turn:
Point 1 — Ngay sau Telegram adapter tạo event/source
Log:
- platform
- chat_id
- chat_type
- user_id
- user_name
- thread_id
- message_id
- raw Telegram
message_thread_idnếu có
Point 2 — Ngay sau build_session_context()
Log:
- context.session_key
- context.session_id
- context.source.chat_id
- context.source.chat_type
- context.source.thread_id
- context.source.message_id
Point 3 — Ngay trước gọi agent/run_sync
Log:
get_session_env()cho tất cảHERMES_SESSION_*- direct ContextVar values nếu cần
Point 4 — Trong terminal tool hoặc _make_run_env() ngay trước subprocess
Log:
- ContextVar values
os.environvalues- final
run_envvalues
Mục tiêu là một bảng cho cùng một message:
| Point | chat_id | chat_type/session_key | thread_id | session_id | message_id |
|---|---|---|---|---|---|
| Telegram source | ? | ? | ? | n/a | ? |
| SessionContext | ? | ? | ? | ? | ? |
| Agent before tool | ? | ? | ? | ? | ? |
| Terminal subprocess env | ? | ? | ? | ? | ? |
Chỉ cần điểm đầu tiên bắt đầu lệch là biết root cause.
Tiêu chí fix đúng
Sau khi fix, test trong 2 topic khác nhau, ví dụ sg và Marketing.
Trong mỗi topic, user gửi:
> map test phòng này
Assistant chạy:
python3 lib/whereami.py --debugKết quả phải thỏa:
env/context.session_keylà dạng group, không phải DM:
agent:main:telegram:group:-1003833933494:<thread_id>HERMES_SESSION_CHAT_IDlà group id:
-1003833933494HERMES_SESSION_THREAD_IDbằng suffix củaHERMES_SESSION_KEY.
HERMES_SESSION_IDtra được trong/root/.hermes/sessions/sessions.jsonvà record đó có cùng session key/thread.
- Không dùng fallback
sessions.json/latest_group_fallbackđể trả kết quả.
- Hai topic khác nhau phải cho hai thread_id khác nhau, nếu Telegram UI thật sự là hai topic khác nhau.
Những điều không nên làm
- Không lưu lại mapping topic/phòng ban khi source là fallback.
- Không tin mapping cũ trong memory.
- Không fix bằng cách để
whereami.pysearch transcript theo text message, vì text có thể trùng và đó chỉ là dữ liệu lịch sử, không phải source-of-truth realtime. - Không dùng
os.environprocess-global làm source chính cho gateway concurrent message context. - Không kết luận
thread_id = 59hay81là Marketing nếu chưa test lại từ Telegram UI sau khi runtime fix.
Kết luận hiện tại
Vấn đề không còn là whereami.py đơn thuần.
whereami.py đã được sửa để đọc session store theo HERMES_SESSION_ID, nhưng tool subprocess vẫn có thể nhận sai HERMES_SESSION_*.
Kết luận mạnh nhất hiện tại:
> Hermes gateway/tool runtime đang bind sai hoặc làm bẩn session context giữa Telegram DM/group/forum topic. Cần sửa để tool subprocess nhận đúng SessionContext của turn hiện tại, thay vì nhận stale/global env hoặc DM context.
Patch đã làm với session_id=context.session_id là cần thiết, nhưng chưa đủ. Claude Code nên tập trung trace từ Telegram inbound source đến terminal _make_run_env() để tìm điểm đầu tiên context bị lệch.
Lệnh kiểm tra nhanh sau khi Claude Code sửa
cd /opt/ai-os/products/ceo
python3 lib/whereami.py --debugVà nếu cần kiểm tra runtime files:
python3 -m py_compile /usr/local/lib/hermes-agent/gateway/run.py
python3 -m py_compile /usr/local/lib/hermes-agent/gateway/session_context.py
python3 -m py_compile /usr/local/lib/hermes-agent/tools/environments/local.pySau khi patch runtime, cần restart gateway từ shell ngoài gateway process:
hermes gateway restartKhông thể restart gateway từ chính bot Telegram vì Hermes chặn để tránh restart loop.