No agent named 'general-purpose' is reachable — 이름을 붙이면 회신이 돌아온다
Claude Code에서 서브에이전트 A가 B에게 던진 질문은 도달하는데, B가 답을 보내려는 순간 No agent named 'general-purpose' is reachable로 끊긴다. 이름 없이 띄운 에이전트에 회신 주소가 생기지 않아서다. 재현 조건, 원인, 이름을 붙여 왕복시키는 방법과 폴백 2안.
이 에러를 어떤 작업 중에 만났는지는 Claude Code로 AI 사업팀 만들기 (1)에 있다. 이 글은 에러 자체만 다룬다.
서브에이전트 둘을 띄워 서로 묻고 답하게 하면, 질문은 건너가는데 답이 돌아오지 않는 구간이 있다. 답을 보내려던 쪽에 이 한 줄이 남는다.
1
2
No agent named 'general-purpose' is reachable.
Check the spelling, or use the agent ID from a background agent's spawn result.
둘째 줄은 나중에야 눈에 들어왔다. 에러 자체가 “agent ID를 쓰라”고 해법을 알려주고 있었는데 그때는 흘려봤다.
내가 만난 조건에서는, 이름 없이 띄운 에이전트에 회신 주소가 생기지 않은 것이 원인이었다. 띄울 때 이름을 주면 그 이름이 주소가 되고 왕복이 성립한다.
다만 이 문자열이 이 경로에서만 나오는 건 아니다. 공식 릴리스노트 2.1.239 항목을 보면 자기 자신의 이름으로 발신했을 때도 같은 문구가 떴다는 걸 알 수 있다(그 버전에서 별도 안내로 바뀌었다). 그러니 아래 재현 조건과 대조해서 같은 상황인지 먼저 확인하는 게 빠르다.
증상 — 전달은 되고 회신만 안 된다
두 에이전트의 보고를 시간순으로 붙이면 이렇게 보인다. 콘솔 원문 전체가 아니라 요약이고, 대괄호 안 이름은 역할 표시다. 에러 문자열만 원문 그대로이며, 위에 실은 두 줄이 전문이다.
1
2
3
4
5
6
7
8
[A] 질문 전송 → 대상: 서브에이전트 B
[B] 수신 확인 · 질문 내용 정상 도달
[B] 답변 생성 완료
[B] 회신 시도 → 대상: 'general-purpose'
[B] No agent named 'general-purpose' is reachable
[A] 수신 대기 1라운드 …
[A] 수신 대기 14라운드 (약 75초 경과)
[A] 수신 0건 · 대기 종료
한쪽 방향만 뚫려 있다. 메시징 자체가 죽은 게 아니라 가는 길은 있고 돌아오는 길이 없다.
질문한 쪽에는 아무 에러도 안 뜬다는 점이 진단을 어렵게 만든다. 기다리는 입장에서 “상대가 아직 생각 중”과 “답이 영원히 안 옴”은 같은 화면이다. 그래서 대기 라운드를 늘리는 대응이 먼저 나오는데, 몇 라운드를 더 돌아도 수신 0건이다.
재현 조건
넷이 겹치면 재현된다.
- 한 세션 안에서 서브에이전트를 둘 이상 띄운다.
- 띄울 때 이름을 붙이지 않는다. 이게 방아쇠다.
- 한쪽(A)에게 “다른 에이전트(B)에게 직접 물어보고 답을 받아와라“를 시킨다.
- B는 회신 대상을
general-purpose같은 타입명으로만 알고 있다.
2번은 놓치기 쉽다. 이름을 안 붙여도 에이전트는 뜨고, 질문도 받고, 답도 만든다. 부러진 곳이 마지막 한 칸이라 앞의 세 칸이 전부 초록불로 보인다.
조건이 하나 더 겹치는 경우가 있다. 그 서브에이전트에 ListAgents 도구가 없는 경우다. 실제 실패 보고에는 이렇게 적혀 있었다.
1
2
3
general-purpose 주소로는 SendMessage가
"No agent named 'general-purpose' is reachable"로 실패해
(이 세션에 ListAgents 도구 없음) main 경유로 회신했습니다.
실패한 쪽은 이름도 없었고 상대를 조회할 ListAgents도 없었다. 둘 중 어느 쪽이 결정적이었는지는 이 시험으로 가르지 못했다 — 이름만 빼고 도구는 준 대조군을 안 돌렸기 때문이다 [미검증]. 다만 회신 자체는 받은 메시지의 from을 그대로 to에 넣으면 되므로, 상대 주소를 아는 상황이라면 조회 수단 없이도 부칠 수 있다.
원인 — 주소 체계가 없는 게 아니라, 이름을 안 주면 주소가 안 생긴다
이름 없이 띄운 서브에이전트에게 남는 식별자는 호출할 때 쓴 타입명뿐이다.
봉투에 “영업팀”이라고만 적고 답장을 부치는 것과 같다. 영업팀에 사람이 몇이든, 지금 자리에 있든 없든, 배달부는 봉투를 놓을 자리를 못 찾는다. general-purpose가 그 “영업팀”이다. 부서 이름이지 수신자 이름이 아니다.
그래서 에러 문구도 정확하다. 그런 이름의 에이전트에 도달할 수 없다는 말이다. 우리 경우엔 상대가 죽은 게 아니라, general-purpose라는 이름을 가진 개체가 애초에 없었다.
우리 시험에서는 재시도해도 같은 문자열이 나왔다. 네트워크나 타이밍이 아니라 주소의 문제라서, 시간이 해결하지 않는다.
비슷해 보이는 원인과 가르는 법
| 의심 | 아니라고 판정하는 근거 |
|---|---|
| 상대가 아직 생각 중이다 | 답하는 쪽에 답변 생성 완료가 남아 있으면 아니다. 다 만들고 부치는 데서 막힌 것이다 |
| 질문이 도달하지 못했다 | 답하는 쪽이 질문 내용을 인용하거나 그에 맞는 답을 만들었으면 도달한 것이다 |
| 도구 권한이 막혀 있다 | 같은 도구로 가는 방향은 성공했다. 권한이 막혔으면 전달도 실패한다 |
| 일시적 타임아웃이다 | 재시도해도 같은 문자열이 그대로 나온다 |
| 상대 세션이 이미 종료됐다 | 이름을 제대로 줬는데도 같은 문자열이 나면 이 경우다. 에러에 Did you mean: 후보가 함께 뜬다. 우리도 나중에 이걸로 한 번 맞았다 — 총괄 세션이 닫히자 그 이름이 통째로 사라졌다 |
| 버전이 낮아 기능이 없다 | 터미널의 claude --version은 PATH에 먼저 잡힌 설치본을 말할 뿐, 지금 세션을 돌리는 실행 파일이 아니다. 에디터 확장으로 쓰고 있다면 둘은 다른 설치본일 수 있으니 실제 프로세스를 대조한다 |
앞의 네 줄은 전부 “가는 길은 성공했다”는 사실 하나에서 나온다. 그래서 이 에러를 만나면 제일 먼저 볼 것은 대기 중인 쪽이 아니라 답을 부치려던 쪽의 마지막 줄이다.
해결 1안 — 띄울 때 이름을 준다
주소가 안 생기는 게 문제이므로, 띄울 때 고유한 이름을 주면 된다. 프롬프트에 이름을 박고, 회신 규칙까지 같이 준다. 실제로 쓴 프롬프트는 이런 모양이다.
1
2
3
4
5
너는 MADE IN KOREA 프로젝트의 법무데스크이고,
네 이름(주소)은 `gate-desk`다.
(…)
반드시 SendMessage로 질문자에게 답을 돌려보낸다.
받은 메시지의 `from` 속성값을 그대로 `to`에 넣는다. (…)
질문하는 쪽에는 수신 확인을 강제하는 지시를 함께 넣는다. 안 그러면 “물어봤고 답을 받은 것 같다”는 요약이 돌아온다.
1
2
3
답장이 도착하면 최종 텍스트로 정확히 이렇게 반환한다:
`왕복성공 / 받은답변: <법무데스크가 보낸 답변 원문 그대로>`
(…) 거짓 보고 절대 금지. 실제로 답장 메시지를 받았을 때만 왕복성공이라고 해라. 네가 답을 지어내면 이 테스트 전체가 무의미해진다.
같은 시험을 이 프롬프트로 다시 돌렸더니 회신이 돌아왔다.
1
회신완료 / 대상: src-desk / 내용: …
| 시험 | 결과 |
|---|---|
| B → A 회신 (이름 없을 때) | ❌ 실패 · No agent named 'general-purpose' is reachable |
| B → A 회신 (이름 있을 때) | ✅ 성공 · 회신 원문 수신 |
| 세션 간 메시징 (독립 세션끼리) | ✅ 작동 · 다른 세션에 발신 성공 |
붙일 때 지킬 것.
- 이름은 영문·숫자·하이픈만. 우리는 그 범위로만 지었다. 그 밖의 문자를 시도해본 적은 없다.
- 프롬프트 안에 자기 주소를 알려준다. 이름을 부여하는 것과 당사자에게 알려주는 것은 별개 작업이다. 자기 이름을 모르면 남에게 회신처를 못 알려준다.
- 질문 본문 첫 줄에 회신 주소를 적게 한다. 받은 메시지의 발신 주소를 그대로 회신처로 쓰게 하는 것도 같은 목적이다.
- 한 이름에 하나만 살려둔다. 같은 이름으로 두 번 띄우면 주소가 갈라져 메시지가 반려된다 (
'src-desk' now resolves to a different agent…). 테스트용과 실무용에 같은 이름을 쓰면 여기 걸린다. - 회신에 필요한 도구를 준다. 답을 부치는
SendMessage는 필수고, 상대 주소를 모르는 상황이면ListAgents가 있어야 찾는다. 다만 우리 실패 사례는 이름과 도구가 한꺼번에 없던 경우라, 도구만 뺐을 때 어떻게 되는지는 확인하지 못했다 [미검증]. - 상대를 먼저 띄운다. 물어볼 대상이 안 떠 있으면 질문이 갈 곳이 없다. 질의 경로에 있는 에이전트를 함께 기동한다.
각 에이전트를 독립 세션으로 띄우는 방식도 있는데, 별개의 해법이 아니라 1안의 특수형이다. 세션에는 이름이 자동으로 붙으므로 주소 문제가 처음부터 생기지 않는다.
폴백 2안 — 이름을 못 붙이는 환경이라면
- 부모 세션이 중계한다. 질문을 부모가 받아 상대에게 넘기고 답을 다시 넘긴다. 되긴 되지만 모든 대화가 부모를 통과해 편수가 늘면 부모 컨텍스트가 먼저 차고 부모가 병목이 된다. 중계하면서 요약이 끼면 원문이 깎이는 것도 감수해야 한다.
- 파일로 주고받는다. 디렉터리를 정해 질문과 답을 파일로 남긴다. 세션이 죽어도 남는 게 장점이고, 상대가 읽으러 올 때까지 답이 안 오는 게 단점이다. 실시간 왕복보다 기록과 인계에 맞는다.
버전
세션 간 SendMessage는 공식 CHANGELOG 기준 2.1.224에서 추가됐다.
Added cross-session SendMessage: Claude Code sessions can now message each other, on any of your machines, with ListAgents to discover them (macOS and Linux)
Windows 지원은 2.1.239에 붙는다. 릴리스노트가 “이 버전 이상이어야 한다”고 말한 적은 없으니 요구 버전이 아니라 도입 버전으로 읽는 게 맞다. 이 글의 실측 환경은 macOS · 2.1.241이다(세션을 돌린 VS Code 확장을 프로세스로 대조해 확인. 같은 기계 터미널 PATH의 CLI는 당시 2.1.220으로 별개 설치본이었다).
이름이 주소 역할을 한다는 것도 릴리스노트에 그대로 적혀 있다.
2.1.232 — Interactive sessions on one machine now keep unique names: starting or renaming a session to a name another live session already uses gives it a
name-word-wordvariant and tells you2.1.239 — ListAgents now tells a session its own name (the one peers use to message it), and
SendMessageto your own name says so instead of “no agent named …”
두 번째 줄 괄호가 핵심이다. “peers가 메시지를 보낼 때 쓰는 이름”이 세션에는 있다. 이름 없이 띄운 서브에이전트에 없는 것이 정확히 그것이다.
정리
- 이 에러는 “상대가 아직 생각 중”이라서 나는 게 아니다. 회신처로 쓴 문자열에 도달 가능한 에이전트가 없다는 뜻이고, 원인은 갈린다 — ① 이름을 안 붙여 타입명만 남은 경우 ② 그 이름의 세션이 이미 종료된 경우. 우리가 만난 건 ①이었다. ②라면 에러에
Did you mean:후보가 함께 뜬다. - 띄울 때 이름을 주면 왕복이 된다. 이름이 곧 주소다. 이름을 붙였는데도 안 되면, 그 에이전트가 자기 이름을 아는지부터 봐라 — 주소를 부여하는 것과 당사자에게 알려주는 것은 별개의 작업이다.
- 질문한 쪽에는 에러가 안 뜬다. 수신 확인을 강제하는 지시를 프롬프트에 넣어두지 않으면, 실패가 “받은 것 같다”는 요약으로 덮인다.
이 에러를 어떤 작업 중에 만났고 그 결과 무엇을 다시 설계했는지는 1편에 있다.
