- Two-Layer Architecture๋ CLI tool ๊ฒฐ๊ณผ๋ฅผ LLM์ ์ ๋ฌํ๊ธฐ ์ ๋ ๊ณ์ธต(Execution / Presentation)์ผ๋ก ๋ถ๋ฆฌํ๋ ์ค๊ณ ํจํด
- Layer 1์ ์์ Unix ์๋ฏธ๋ก , Layer 2๋ LLM ์ธ์ง ์ ์ฝ์ ๋ง์ถ ๋ณํ์ ๋ด๋นํ๋ ์ฑ ์ ๋ถ๋ฆฌ ๊ตฌ์กฐ
- ๋ฐ์ด๋๋ฆฌ ๊ฐ๋ยท์ค๋ฒํ๋ก์ฐยท๋ฉํ ํธํฐยทstderr ์ฒจ๋ถ 4๊ฐ์ง ๋ฉ์ปค๋์ฆ์ผ๋ก ๊ตฌ์ฑ๋ LLM-์นํ์ ์ถ๋ ฅ ๋ณํ ๊ณ์ธต
- ํ์ดํ ์๋ฏธ ๋ณด์กด๊ณผ ์ปจํ ์คํธ ๋ณดํธ๋ฅผ ๋์์ ๋ฌ์ฑํ๋ agent tool ์ค๊ณ์ ํต์ฌ ์์น
ํด๋น ๊ฐ๋ ์ด ํ์ํ ์ด์
- LLM์ ํ ์คํธ๋ง ์ฒ๋ฆฌ ๊ฐ๋ฅ โ ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ์ง์ ์ฃผ์ ํ๋ฉด ํ ํฌ๋์ด์ ๊ฐ ์๋ฏธ ์๋ ๊ณ ์ํธ๋กํผ ํ ํฐ ์์ฑ
- Context window๊ฐ ์ ํํด 5000์ค ๋ก๊ทธ ๊ฐ์ ๋์ฉ๋ ์ถ๋ ฅ์ ์ด์ ๋ํ๋ฅผ ๋ฐ์ด๋ด๊ณ ์ถ๋ก ํ์ง์ ์ ํ
- Layer 1์์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ง์ ๋ถ์ฐฉํ๋ฉด ๋ค์ ํ์ดํ(
grep)์ ๊ฒ์ ๋์์ ์์ฌ Unix ์๋ฏธ๋ก ์ด ๊นจ์ง - ๋ช ๋ น์ด ์คํจ ์ stderr๋ฅผ ๋๋ฝํ๋ฉด agent๊ฐ โ์ ์คํจํ๋์งโ ๋ชจ๋ฅธ ์ฑ ๊ฐ์ ์๋๋ฅผ ๋ฐ๋ณต
AS-IS โ ๋จ์ผ ๊ณ์ธต, raw ์ถ๋ ฅ ์ง์ ์ฃผ์
LLM์ด cat photo.png์ ํธ์ถํ๋ฉด raw PNG ๋ฐ์ดํธ๊ฐ ๊ทธ๋๋ก ์ปจํ
์คํธ์ ๋ค์ด๊ฐ๋ค.
sequenceDiagram autonumber participant A as Agent participant T as run() Tool participant LLM A->>T: run("cat photo.png") T->>T: PNG ๋ฐ์ด๋๋ฆฌ ๊ทธ๋๋ก stdout T-->>A: 182KB raw bytes A->>LLM: context์ raw bytes ์ฃผ์ Note over LLM: ํ ํฌ๋์ด์ ๊ฐ ์๋ฏธ ์๋<br/>ํ ํฐ ์์ฒ ๊ฐ ์์ฑ<br/>์ฃผ์๋ ฅ ๋ถ์ฐ, ์ถ๋ก ํ์ง ์ ํ LLM-->>A: ํผ๋์ค๋ฌ์ด ์๋ต<br/>(20๋ฒ ์ฌ์๋ ์ฌ๋ก)
TO-BE โ 2๊ณ์ธต ๋ถ๋ฆฌ, LLM์ ์์ ํ ์ถ๋ ฅ๋ง ์ ๋ฌ
sequenceDiagram autonumber participant A as Agent participant L1 as Layer 1<br/>(Execution) participant L2 as Layer 2<br/>(Presentation) participant LLM A->>L1: run("cat photo.png") L1->>L1: cat ์คํ, raw bytes ์์ฑ L1->>L2: stdout/stderr/exit code ์ ๋ฌ Note over L2: ๋ฐ์ด๋๋ฆฌ ๊ฐ์ง<br/>์ค๋ฒํ๋ก์ฐ ๊ฒ์ฌ<br/>๋ฉํ ํธํฐ ๋ถ์ฐฉ<br/>stderr ์ฒจ๋ถ L2-->>A: "[error] binary image (182KB).<br/>Use: see photo.png<br/>[exit:1 | 8ms]" A->>LLM: ๊ฐ๊ณต๋ ํ ์คํธ๋ง ์ ๋ฌ LLM-->>A: "see photo.png ํธ์ถ"
๋ ๊ณ์ธต์ ์ฑ ์ ๋ถ๋ฆฌ
๊ฐ ๊ณ์ธต์ ์ฑ ์ ๋ฒ์์ ๊ธ์ง ์ฌํญ์ด ๋ช ํํ ๊ฐ๋ฆฐ๋ค.
| ๊ณ์ธต | ์ฑ ์ | ๊ธ์ง |
|---|---|---|
| Layer 1 (Execution) | ๋ช ๋ น์ด ๋ผ์ฐํ , ํ์ดํ/์ฒด์ธ ์ฒ๋ฆฌ, exit code ์์ฑ | ๋ฉํ๋ฐ์ดํฐ ๋ถ์ฐฉ, LLM ์นํ ๊ฐ๊ณต, ์ถ๋ ฅ ๋ณํ |
| Layer 2 (Presentation) | ๋ฐ์ด๋๋ฆฌ ๊ฐ๋, ์ค๋ฒํ๋ก์ฐ ์ฒ๋ฆฌ, ๋ฉํ ํธํฐ, stderr ์ฒจ๋ถ | ํ์ดํ ์ค๊ฐ ๋จ๊ณ ๊ฐ์ , ๋ช ๋ น์ด ์คํ |
์ ๋ ๊ณ์ธต์ ์์ผ๋ฉด ์ ๋๋๊ฐ
cat bigfile.txt | grep error | head 10 ์คํ์ ์๋ก ๋ ๋ค.
Layer 1์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ์ ๋ ๋ฐ์ํ๋ ๋ฌธ์ :
1. cat bigfile.txt โ "๋ด์ฉ...\n[exit:0 | 100ms]" โ ๋ฉํ ๋ถ์ฐฉ
2. grep error โ "[exit:0 | 100ms]" ๋ ๊ฒ์ ๋์์ ํฌํจ๋จ
3. ์๋ชป๋ ๋งค์น ๋ฐ์, ์๋ฏธ๋ก ํ๊ดด
Layer 1์์ ์๋์ ๋ ๋ฐ์ํ๋ ๋ฌธ์ :
1. cat bigfile.txt โ ์ฒซ 200์ค๋ก ์๋ฆ
2. grep error โ ์๋ฅธ 200์ค์์๋ง ๊ฒ์
3. ์ฌ์ฉ์๊ฐ ์ํ "์ ์ฒด ํ์ผ์์ error ์ฐพ๊ธฐ"๊ฐ ๊นจ์ง
๋ฐ๋ผ์ Layer 1์ ์์ํด์ผ ํ๊ณ , Layer 2๋ ์ต์ข ์ถ๋ ฅ ์ง์ ์๋ง ๊ฐ์ ํด์ผ ํ๋ค.
Layer 2์ 4๊ฐ์ง ๋ฉ์ปค๋์ฆ
1. ๋ฐ์ด๋๋ฆฌ ๊ฐ๋ (Binary Guard)
LLM ํ ํฌ๋์ด์ ๋ ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ฏ๋ก, ๋ฐ์ด๋๋ฆฌ ๊ฐ์ง ์ ์ฆ์ ์ฐจ๋จํ๊ณ ๋์ ๋ช ๋ น์ด๋ฅผ ์๋ดํ๋ค.
๊ฐ์ง ํด๋ฆฌ์คํฑ:
- Null byte ํฌํจ
- UTF-8 ๊ฒ์ฆ ์คํจ
- ์ ์ด ๋ฌธ์ ๋น์จ 10% ์ด๊ณผ
์ถ๋ ฅ ํํ:
[error] cat: binary image file (182KB). Use: see photo.png
[error] cat: binary file (1.2MB). Use: cat -b file.bin
ํต์ฌ: ์๋ฌ ๋ฉ์์ง๊ฐ ๋ค์ ํ๋์ ์ ํํ ์ง์ํ๋ค (Agent Heuristic Design์ โError as navigationโ ์์น).
2. ์ค๋ฒํ๋ก์ฐ ๋ชจ๋ (Overflow Mode)
์ถ๋ ฅ์ด 200์ค ๋๋ 50KB๋ฅผ ์ด๊ณผํ๋ฉด ์๋ผ์ ํ์ผ์ ๋ณด๊ดํ๊ณ , ํ์ ๋ช ๋ น์ด๋ฅผ ํจ๊ป ์ ๊ณตํ๋ค.
์ฒ๋ฆฌ ํ๋ฆ:
- ์ฒซ 200์ค๋ง LLM์ ๋ฐํ (UTF-8 ์์ ์ ๋จ)
- ์ ์ฒด ์ถ๋ ฅ์
/tmp/cmd-output/cmd-{n}.txt์ ์ ์ฅ - ํ์ ๊ฐ๋ฅํ ํ์ ๋ช ๋ น์ด ์๋ด
์ถ๋ ฅ ์์:
[์ฒซ 200์ค ๋ด์ฉ]
--- output truncated (5000 lines, 245.3KB) ---
Full output: /tmp/cmd-output/cmd-3.txt
Explore: cat /tmp/cmd-output/cmd-3.txt | grep <pattern>
cat /tmp/cmd-output/cmd-3.txt | tail 100
[exit:0 | 1.2s]
ํต์ฌ ์ธ์ฌ์ดํธ: LLM์ ์ด๋ฏธ grep/head/tail ์ฌ์ฉ๋ฒ์ ์๋ฏ๋ก, โ๋์ฉ๋ ๋ฐ์ดํฐ ํ์โ์ด agent์ ๊ธฐ์กด ๊ธฐ์ ๋ก ์๋ ๋ณํ๋๋ค.
3. ๋ฉํ๋ฐ์ดํฐ ํธํฐ (Metadata Footer)
๋งค ํธ์ถ์ ๋ง์ง๋ง ์ค์ exit code์ ์คํ ์๊ฐ์ ๋ถ์ฐฉํ๋ค.
์ค์ ์ถ๋ ฅ ๋ด์ฉ
[exit:0 | 1.2s]
๋ถ์ฐฉ ์ ๋ณด์ ์๋ฏธ:
| ํ๋ | ์๋ฏธ | LLM ํ์ต ํจ๊ณผ |
|---|---|---|
exit:0 | ์ฑ๊ณต | Unix ํ์ค, LLM ์ฌ์ ์ง์ ํ์ฉ |
exit:1 | ์ผ๋ฐ ์คํจ | ์ฌ์๋ ์ ํธ |
exit:127 | ๋ช ๋ น์ด ์์ | ๋ค๋ฅธ ๋ช ๋ น์ด ์๋ ์ ํธ |
12ms | ์ ๋ ด | ์์ ๋กญ๊ฒ ํธ์ถ |
3.2s | ์ค๊ฐ | ์ ์คํ ์ฌ์ฉ |
45s | ๋น์ | ํธ์ถ ์ต์ํ |
๋ฐ๋ณต ๋ ธ์ถ์ ํตํด agent๊ฐ ์๊ฐ๊ณผ ๋น์ฉ ํจํด์ ๋ด์ฌํ โ ์๊ฐ์ด ๊ฐ์๋ก ๋ ํจ์จ์ ์ธ ํธ์ถ.
4. stderr ์ฒจ๋ถ (Stderr Attachment)
๋ช ๋ น์ด ์คํจ ์ stdout์ด ๋น์ด์์ง ์๋๋ผ๋ stderr๋ฅผ ํญ์ ์ฒจ๋ถํ๋ค.
[stdout ๋ด์ฉ (์์ผ๋ฉด)]
[stderr] bash: pip: command not found
[exit:127 | 8ms]
์ ์ค์ํ๊ฐ: stderr ๋๋ฝ ์ agent๋ โ์คํจโ๋ง ์๊ณ โ์ ์คํจํ๋์งโ ๋ชจ๋ฅธ ์ฑ ๊ฐ์ ์๋๋ฅผ ๋ฐ๋ณต (์คํจ ์ฌ๋ก 2๋ฒ ์ฐธ๊ณ ).
์คํจ ์ฌ๋ก์์ ๋์ถ๋ ๋ฉ์ปค๋์ฆ
๊ฐ ๋ฉ์ปค๋์ฆ์ ์ค์ ์ด์ ์ค ๋ฐ๊ฒฌ๋ ์ํฐํจํด์ ์ง์ ์ ํด๊ฒฐ์ฑ ์ด๋ค.
์ฌ๋ก 1 โ ๋ฐ์ด๋๋ฆฌ ๊ฐ๋ ๋์
์ฌ์ฉ์๊ฐ PNG ์
๋ก๋ โ agent๊ฐ cat์ผ๋ก ์ฝ์ โ 182KB raw ๋ฐ์ดํธ๊ฐ LLM context๋ก โ ํ ํฌ๋์ด์ ์๋ฏธ ์๋ ํ ํฐ ์์ฑ โ agent ํผ๋ โ cat -f, cat --format, cat --type image ๋ฑ 20๋ฒ ์ํ์ฐฉ์ค ํ ๊ฐ์ ์ข
๋ฃ.
์์ธ: ๋ฐ์ด๋๋ฆฌ ๊ฐ์ง ๋ก์ง ๋ถ์ฌ ๊ตํ: ๋๊ตฌ ๊ฒฐ๊ณผ๋ agent์ ๋์ด๋ค. ์ฐ๋ ๊ธฐ๋ฅผ ๋ฐํํ๋ฉด agent๊ฐ ์๋งน(blind) ์ํ๊ฐ ๋๋ค.
์ฌ๋ก 2 โ stderr ์ฒจ๋ถ ๋์
pip install pymupdf ์คํ โ exit 127 โ stderr โpip: command not foundโ ๋๋ฝ โ agent๋ โ์คํจโ๋ง ๋ด โ python3 -m pip, uv pip install, pip3 install, sudo apt install ๋ฑ 10๋ฒ ๋งน๋ชฉ์ ์ฌ์๋ ํ์์ผ uv run --with pymupdf ๋ฐ๊ฒฌ.
์์ธ: stdout์ด ๋น์ด์์ง ์์ผ๋ฉด stderr๋ฅผ ์กฐ์ฉํ ๋ฒ๋ฆฌ๋ ๋ก์ง ๊ตํ: stderr๋ agent๊ฐ ๊ฐ์ฅ ํ์๋ก ํ๋ ์ ๋ณด๋ค. ์ ํํ ๋ช ๋ น์ด๊ฐ ์คํจํ ๊ทธ ์๊ฐ์.
์ฌ๋ก 3 โ ์ค๋ฒํ๋ก์ฐ ๋ชจ๋ ๋์
agent๊ฐ 5,000์ค ๋ก๊ทธ๋ฅผ ๋ถ์ํ๋ ค๊ณ cat huge.log ํธ์ถ โ ์ฝ 200KB ํ
์คํธ๊ฐ ๊ทธ๋๋ก ์ปจํ
์คํธ์ ์ฑ์์ง โ LLM ์ฃผ์๋ ฅ ๊ณผ๋ถํ, ์๋ต ํ์ง ๊ธ๋ฝ, ์ด์ ๋ํ ์ปจํ
์คํธ ๋ฐ๋ ค๋จ.
์ค๋ฒํ๋ก์ฐ ๋ชจ๋ ์ ์ฉ ํ: ์ฒซ 200์ค๋ก ๊ตฌ์กฐ ํ์ โ grep์ผ๋ก ๋ฌธ์ ์์น ํน์ โ ์ด 3ํธ์ถ, 2KB ์ปจํ ์คํธ๋ก ๋์ผ ์์ ์๋ฃ.
๊ตํ: agent์๊ฒ โ์ ์ฒด ์ํ โ ๋์ โ์ง๋โ๋ฅผ ์ค ๋ ๊ฐ์ฅ ํจ์จ์ ์ด๋ค.
์ ์ฉ ์ ์ฒดํฌ๋ฆฌ์คํธ
- Layer 1 ์ฝ๋์ ๋ฉํ๋ฐ์ดํฐ ๋ถ์ฐฉ์ด ์์ฌ ์์ง ์์๊ฐ
- ๋ฐ์ด๋๋ฆฌ ๊ฐ์ง๊ฐ ๋ชจ๋ stdout ๊ฒฝ๋ก๋ฅผ ์ปค๋ฒํ๋๊ฐ
- ์ถ๋ ฅ ์๊ณ๊ฐ(์ค ์, ๋ฐ์ดํธ ์)์ด LLM ์ปจํ ์คํธ ํฌ๊ธฐ์ ๋ง์ถฐ์ ธ ์๋๊ฐ
- ์์ ํ์ผ ๊ฒฝ๋ก(
/tmp/cmd-output/...)๊ฐ agent์์ ์ผ๊ด๋๊ฒ ๋ ธ์ถ๋๋๊ฐ - ๋ช ๋ น์ด ์คํจ ์ stderr๊ฐ ๋๋ฝ๋์ง ์๋๊ฐ
- exit code์ duration์ด ๋ชจ๋ ์๋ต์ ์ผ๊ด๋๊ฒ ๋ถ๋๊ฐ
๊ด๋ จ ๊ฐ๋
- CLI-based Tool Calling โ ์ด ํจํด์ด ์ ์ฉ๋๋ ์์ ๋๊ตฌ ๋ชจ๋ธ(๋ฉ์ธ ๊ฐ๋ )
- Agent Heuristic Design โ Layer 2์ ์๋ฌ ๋ฉ์์ง ์ค๊ณ๊ฐ ๋ฐ๋ฅด๋ ์์น ์งํฉ
- delta โ ์คํธ๋ฆฌ๋ฐ ๋ฉํ๋ฐ์ดํฐ ์ผ๋ฐ ๊ฐ๋