[chore] solution/backend: 에이전트 대화창 다시 염 — AGENT_CHAT_ENABLED 기본 1
카카오톡 채널의 통신사 인증이 끝나 어제 걸어 둔 보류를 푼다. 코드는 어제도 오늘도 그대로고 값만 바꿨다 — 닫고 여는 일이 커밋을 되짚는 일이 되면 안 된다는 어제 판단이 하루 만에 값을 쳤다. - config/agent_config: 기본값 0 → 1 - ★ 켜도 LLM 키가 없으면 안 열린다(runtime.is_configured 가 스위치와 키를 둘 다 본다). 키 없는 환경에서 켜 둔 채 잊어도 "눌러도 안 되는 입구" 가 안 생긴다 - 스위치 테스트를 새 기본값에 맞춰 갱신 — 키가 없을 때도 안 열리는 것을 함께 검사 카카오 연결 카드는 아직 감춰져 있다(KAKAO_CHANNEL_PUBLIC_ID 미설정). 채우면 코드는 발급되지만 소비할 웹훅(4단계)이 없어 연결이 완성되지 않는다. test_agent_runtime·test_kakao_link 34 passed. npm run lint 통과 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
acd5383b0f
commit
5b54daac10
@ -83,9 +83,10 @@ ALIMTALK_TEMPLATE_CODE=
|
|||||||
# 묶어야 한다. 빌더에서 코드를 받아 채널에 한 번 입력하는 절차다.
|
# 묶어야 한다. 빌더에서 코드를 받아 채널에 한 번 입력하는 절차다.
|
||||||
# ★ 이 값이 비면 연결 화면이 아예 안 뜬다 — 어디에 코드를 칠지 말해 줄 수 없는데
|
# ★ 이 값이 비면 연결 화면이 아예 안 뜬다 — 어디에 코드를 칠지 말해 줄 수 없는데
|
||||||
# 코드만 발급하면 사장님에게는 고장난 화면이다.
|
# 코드만 발급하면 사장님에게는 고장난 화면이다.
|
||||||
# ★ 사장님 대화창(에이전트). 기본 꺼짐 — 카카오톡 채널이 준비되기 전에는 띄우지 않는다.
|
# 사장님 대화창(에이전트). 1=사용, 0=감춤.
|
||||||
# 코드는 다 있지만 채널 없이 열어 두면 사장님에게는 어디에도 닿지 않는 입구다.
|
# ★ 1 이어도 LLM 키가 없으면 안 열린다 — 키 없는 환경에서 켜 둔 채 잊어도
|
||||||
AGENT_CHAT_ENABLED=0
|
# "눌러도 안 되는 입구" 가 생기지 않는다.
|
||||||
|
AGENT_CHAT_ENABLED=1
|
||||||
KAKAO_CHANNEL_PUBLIC_ID=
|
KAKAO_CHANNEL_PUBLIC_ID=
|
||||||
KAKAO_LINK_CODE_TTL_MIN=10
|
KAKAO_LINK_CODE_TTL_MIN=10
|
||||||
KAKAO_LINK_MAX_ATTEMPTS=5
|
KAKAO_LINK_MAX_ATTEMPTS=5
|
||||||
|
|||||||
@ -169,9 +169,11 @@
|
|||||||
`services/*` 를 통과한다. `collect_service.store_facts` 가 크롤러에 걸어 둔 그 문이다.
|
`services/*` 를 통과한다. `collect_service.store_facts` 가 크롤러에 걸어 둔 그 문이다.
|
||||||
- **카카오 채널 발화자는 우리 `user_id` 가 아니다** — 채널 단위 익명 키다.
|
- **카카오 채널 발화자는 우리 `user_id` 가 아니다** — 채널 단위 익명 키다.
|
||||||
`owner_kakao_links` 매핑 없이 발화자를 믿으면 **채널 진입점만 소유자 범위 밖**에 놓인다.
|
`owner_kakao_links` 매핑 없이 발화자를 믿으면 **채널 진입점만 소유자 범위 밖**에 놓인다.
|
||||||
- **에이전트 화면은 2026-09-21 기준 감춰져 있다** — `AGENT_CHAT_ENABLED=0`(기본) ·
|
- **에이전트 대화창은 스위치와 LLM 키를 둘 다 본다**(`AGENT_CHAT_ENABLED`, 기본 `1`).
|
||||||
`KAKAO_CHANNEL_PUBLIC_ID` 빔. 카카오톡 채널이 보류돼서이고 **코드는 멀쩡하다**.
|
키만 보면 "잠시 닫아 두기" 가 키를 지우는 일이 되어 소개문·사진분류까지 꺼지고,
|
||||||
"기능이 없다" 고 판단해 지우지 않는다([AGENT.md](docs/AGENT.md)).
|
스위치만 보면 키 없는 환경에 **눌러도 안 되는 입구**가 생긴다.
|
||||||
|
카카오 연결 카드는 `KAKAO_CHANNEL_PUBLIC_ID` 가 비면 감춰진다 —
|
||||||
|
웹훅(4단계)이 없어 코드를 보내도 연결이 완성되지 않기 때문이다([AGENT.md](docs/AGENT.md)).
|
||||||
- **에이전트 등급을 모델이 정하게 두지 않는다** — 확인이 필요한 행위인지는 `services/agent/tools.py`
|
- **에이전트 등급을 모델이 정하게 두지 않는다** — 확인이 필요한 행위인지는 `services/agent/tools.py`
|
||||||
레지스트리가 못 박는다. 응답 스키마에 그 칸을 만들면 프롬프트에 끼어든 한 줄이 확인 절차를 건너뛴다.
|
레지스트리가 못 박는다. 응답 스키마에 그 칸을 만들면 프롬프트에 끼어든 한 줄이 확인 절차를 건너뛴다.
|
||||||
- **실행 결과 문구를 LLM 이 쓰게 두지 않는다** — 모델은 **하지 않은 일을 했다고 말할 수 있고**,
|
- **실행 결과 문구를 LLM 이 쓰게 두지 않는다** — 모델은 **하지 않은 일을 했다고 말할 수 있고**,
|
||||||
|
|||||||
@ -7,22 +7,24 @@
|
|||||||
지금까지 만든 것은 **1단계(신원 연결)** 와 **2단계(도구·런타임·빌더 채팅창)** 다.
|
지금까지 만든 것은 **1단계(신원 연결)** 와 **2단계(도구·런타임·빌더 채팅창)** 다.
|
||||||
카카오 채널 웹훅은 아직 없다.
|
카카오 채널 웹훅은 아직 없다.
|
||||||
|
|
||||||
## ★ 지금은 화면에서 감춰져 있다 (2026-09-21 보류)
|
## 화면 스위치
|
||||||
|
|
||||||
카카오톡 채널 개설이 **법인폰 본인인증**에 걸려 보류됐다. 채널이 없으면 이 기능은
|
| 화면 | 여는 조건 | 지금 |
|
||||||
사장님에게 **어디에도 닿지 않는 입구**다 — 열어 두면 "되는 기능" 으로 오해한다.
|
|---|---|---|
|
||||||
|
| 대화창(`AgentChatDock`) | `AGENT_CHAT_ENABLED=1`(기본) **그리고** LLM 키 | 열림 |
|
||||||
|
| 연결 카드(`KakaoChannelCard`) | `KAKAO_CHANNEL_PUBLIC_ID` 가 채워짐 | 채널 ID 미설정 |
|
||||||
|
|
||||||
| 화면 | 감추는 조건 |
|
★ 스위치와 키를 **둘 다** 본다(`runtime.is_configured`). 키만 보면 "잠시 닫아 두기" 를 키를
|
||||||
|---|---|
|
지워서 해야 하고 그러면 소개문·사진분류까지 같이 꺼진다. 스위치만 보면 키 없는 환경에서
|
||||||
| 대화창(`AgentChatDock`) | `AGENT_CHAT_ENABLED=0` (기본값) |
|
**눌러도 안 되는 입구**가 생긴다.
|
||||||
| 연결 카드(`KakaoChannelCard`) | `KAKAO_CHANNEL_PUBLIC_ID` 가 빔 (기본값) |
|
|
||||||
|
|
||||||
**코드는 그대로 두고 설정으로만 닫았다.** 채널이 준비되면 값 둘을 채우고 다시 띄우면 된다 —
|
★ 2026-09-21 에 카카오 채널 개설이 법인폰 본인인증에 걸려 한 번 닫았고,
|
||||||
되돌릴 때 커밋을 되짚지 않는다. 서버도 함께 닫힌다(`runtime.is_configured()` 가 스위치를
|
인증이 끝나 2026-09-22 에 다시 열었다. **그때도 코드는 지우지 않고 값만 바꿨다** —
|
||||||
보므로, 화면을 우회해 API 를 직접 불러도 `AGENT_NOT_CONFIGURED` 다).
|
닫고 여는 일이 커밋을 되짚는 일이 되면 안 된다.
|
||||||
|
|
||||||
★ Threads 카드는 반대로 '자리는 두고 버튼만 죽이는' 쪽이다. 저쪽은 사장님이 **곧 쓸 수 있는**
|
★ 연결 카드를 '감추는' 쪽으로 둔 것은 Threads 카드('자리는 두고 버튼만 죽인다')와 반대
|
||||||
기능이라 존재를 알려야 했고, 이쪽은 언제 열릴지 말해 줄 수 없다. 판단이 갈린 이유가 그것이다.
|
판단인데 의도한 차이다. 저쪽은 사장님이 곧 쓸 수 있는 기능이라 존재를 알려야 했고,
|
||||||
|
이쪽은 웹훅(4단계)이 없어 아직 연결이 **완성되지 않는다**.
|
||||||
|
|
||||||
## 왜 신원 연결이 먼저인가
|
## 왜 신원 연결이 먼저인가
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,20 @@
|
|||||||
# 개발 일지
|
# 개발 일지
|
||||||
|
|
||||||
|
## 2026-09-22 — 에이전트 대화창 다시 염(기본 켜짐)
|
||||||
|
|
||||||
|
카카오톡 채널의 통신사 인증이 끝나 보류를 푼다(사장님 지시). `AGENT_CHAT_ENABLED` 기본값을
|
||||||
|
`0` → `1` 로 돌렸다. **코드는 어제도 오늘도 그대로다** — 닫고 여는 일이 커밋을 되짚는 일이
|
||||||
|
되면 안 된다는 어제 판단이 하루 만에 값을 쳤다.
|
||||||
|
|
||||||
|
★ 기본을 켜도 **LLM 키가 없으면 안 열린다**(`runtime.is_configured` 가 스위치와 키를 둘 다
|
||||||
|
본다). 키 없는 환경에서 켜 둔 채 잊어도 "눌러도 안 되는 입구" 가 생기지 않는다.
|
||||||
|
|
||||||
|
★ 카카오 연결 카드는 아직 감춰져 있다 — `KAKAO_CHANNEL_PUBLIC_ID` 미설정.
|
||||||
|
채우면 코드는 발급되지만 **소비할 웹훅(4단계)이 없어 연결이 완성되지 않는다.**
|
||||||
|
채널 '채팅' 과 '챗봇(오픈빌더 스킬)' 은 다른 기능이고, 웹훅이 붙는 쪽은 후자다.
|
||||||
|
|
||||||
|
**검증** — `test_agent_runtime`(스위치 테스트를 새 기본값에 맞춰 갱신)·`test_kakao_link` 34 passed.
|
||||||
|
|
||||||
## 2026-09-21 — 에이전트 화면 보류: 설정으로 닫는다(코드는 그대로)
|
## 2026-09-21 — 에이전트 화면 보류: 설정으로 닫는다(코드는 그대로)
|
||||||
|
|
||||||
카카오톡 채널 개설이 **법인폰 본인인증**에 걸려 보류됐다(사장님 지시: "이 작업은 여기서 딱
|
카카오톡 채널 개설이 **법인폰 본인인증**에 걸려 보류됐다(사장님 지시: "이 작업은 여기서 딱
|
||||||
|
|||||||
@ -23,10 +23,12 @@ class AgentConfig(BaseSettings):
|
|||||||
# 코드가 짧아서(사람이 손으로 친다) 무차별 대입이 가능하다. 시도 수로 끊는다.
|
# 코드가 짧아서(사람이 손으로 친다) 무차별 대입이 가능하다. 시도 수로 끊는다.
|
||||||
KAKAO_LINK_MAX_ATTEMPTS: int = 5
|
KAKAO_LINK_MAX_ATTEMPTS: int = 5
|
||||||
|
|
||||||
# ★ 기본 꺼짐. 카카오톡 채널 개설이 법인폰 본인인증에 걸려 보류됐고(2026-09-21),
|
# 빌더 화면의 대화창. 2026-09-21 에 한 번 닫았다가(카카오 채널 보류) 채널 인증이
|
||||||
# 채널 없이 대화창만 띄우면 사장님에게는 **어디에도 닿지 않는 입구**가 된다.
|
# 끝나 다시 열었다(2026-09-22).
|
||||||
# 코드는 그대로 두고 이 값으로만 연다 — 되돌릴 때 커밋을 되짚지 않아도 된다.
|
# ★ 이 값이 "1" 이어도 **LLM 키가 없으면 안 열린다**(runtime.is_configured 가 둘 다 본다) —
|
||||||
AGENT_CHAT_ENABLED: str = "0"
|
# 키 없는 환경에서 켜 둔 채 잊어도 "눌러도 안 되는 입구" 가 생기지 않는다.
|
||||||
|
# 다시 닫을 일이 생기면 이 값만 "0" 으로 되돌린다. 코드를 되짚지 않는다.
|
||||||
|
AGENT_CHAT_ENABLED: str = "1"
|
||||||
|
|
||||||
|
|
||||||
def get(name, default=""):
|
def get(name, default=""):
|
||||||
|
|||||||
@ -45,11 +45,10 @@ class AgentError(RuntimeError):
|
|||||||
def is_configured() -> bool:
|
def is_configured() -> bool:
|
||||||
"""대화창을 열 수 있나 — 스위치와 LLM 키를 **둘 다** 본다.
|
"""대화창을 열 수 있나 — 스위치와 LLM 키를 **둘 다** 본다.
|
||||||
|
|
||||||
★ `AGENT_CHAT_ENABLED` 가 기본 꺼짐이다(config/agent_config). 카카오톡 채널이 준비되기
|
★ 스위치(`AGENT_CHAT_ENABLED`)와 키를 **둘 다** 보는 이유: 키만 보면 "잠시 닫아 두기" 를
|
||||||
전에는 대화창을 띄우지 않는다 — 코드는 다 있지만 사장님 입장에서는 어디에도 닿지 않는
|
키를 지워서 해야 하는데 그러면 소개문·사진분류까지 같이 꺼진다. 스위치만 보면
|
||||||
입구이고, 열려 있으면 "되는 기능" 으로 오해한다.
|
키 없는 환경에서 **눌러도 안 되는 입구**가 생긴다.
|
||||||
이건 Threads 카드처럼 '자리는 두고 버튼만 죽이는' 경우와 다르다. 저쪽은 사장님이
|
실제로 2026-09-21 에 카카오 채널 보류로 한 번 닫았고, 채널 인증이 끝나 다시 열었다."""
|
||||||
**곧 쓸 수 있는** 기능이라 존재를 알려야 했고, 이쪽은 아직 제품이 아니다."""
|
|
||||||
return config.chat_enabled() and provider.active().is_configured()
|
return config.chat_enabled() and provider.active().is_configured()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -227,20 +227,22 @@ def test_읽기_도구는_확인을_요구하지_않는다():
|
|||||||
|
|
||||||
# ── 보류 스위치 ─────────────────────────────────────────────────────────
|
# ── 보류 스위치 ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def test_스위치가_꺼져_있으면_키가_있어도_안_열린다(monkeypatch):
|
def test_스위치와_키를_둘_다_본다(monkeypatch):
|
||||||
"""★ 기본이 꺼짐이다. 카카오톡 채널이 준비되기 전에는 대화창을 띄우지 않는다 —
|
"""★ 키만 보면 '잠시 닫아 두기' 를 키를 지워서 해야 하고, 그러면 소개문·사진분류까지
|
||||||
코드는 다 있지만 사장님에게는 어디에도 닿지 않는 입구다."""
|
같이 꺼진다. 스위치만 보면 키 없는 환경에서 **눌러도 안 되는 입구**가 생긴다."""
|
||||||
monkeypatch.setattr(runtime.provider, "active", lambda: SimpleNamespace(is_configured=lambda: True))
|
monkeypatch.setattr(runtime.provider, "active", lambda: SimpleNamespace(is_configured=lambda: True))
|
||||||
monkeypatch.delenv("AGENT_CHAT_ENABLED", raising=False)
|
monkeypatch.delenv("AGENT_CHAT_ENABLED", raising=False)
|
||||||
assert runtime.is_configured() is False
|
assert runtime.is_configured() is True # 기본은 켜짐(2026-09-22)
|
||||||
monkeypatch.setenv("AGENT_CHAT_ENABLED", "1")
|
|
||||||
assert runtime.is_configured() is True
|
|
||||||
monkeypatch.setenv("AGENT_CHAT_ENABLED", "0")
|
monkeypatch.setenv("AGENT_CHAT_ENABLED", "0")
|
||||||
assert runtime.is_configured() is False
|
assert runtime.is_configured() is False # 스위치로 닫을 수 있다
|
||||||
|
|
||||||
|
monkeypatch.setenv("AGENT_CHAT_ENABLED", "1")
|
||||||
|
monkeypatch.setattr(runtime.provider, "active", lambda: SimpleNamespace(is_configured=lambda: False))
|
||||||
|
assert runtime.is_configured() is False # 켜 뒀어도 키가 없으면 안 열린다
|
||||||
|
|
||||||
|
|
||||||
async def test_꺼진_동안_대화_요청은_거절된다(client, auth_headers, monkeypatch, db_engine):
|
async def test_닫아_두면_대화_요청은_거절된다(client, auth_headers, monkeypatch, db_engine):
|
||||||
monkeypatch.delenv("AGENT_CHAT_ENABLED", raising=False)
|
monkeypatch.setenv("AGENT_CHAT_ENABLED", "0")
|
||||||
h, pid = await seed(client, auth_headers)
|
h, pid = await seed(client, auth_headers)
|
||||||
res = await client.post(f"/v1/agent/chat/{pid}", headers=h, json={"message": "안녕"})
|
res = await client.post(f"/v1/agent/chat/{pid}", headers=h, json={"message": "안녕"})
|
||||||
assert res.status_code == 409
|
assert res.status_code == 409
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user