• 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๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด ์ž˜๋ผ์„œ ํŒŒ์ผ์— ๋ณด๊ด€ํ•˜๊ณ , ํƒ์ƒ‰ ๋ช…๋ น์–ด๋ฅผ ํ•จ๊ป˜ ์ œ๊ณตํ•œ๋‹ค.

์ฒ˜๋ฆฌ ํ๋ฆ„:

  1. ์ฒซ 200์ค„๋งŒ LLM์— ๋ฐ˜ํ™˜ (UTF-8 ์•ˆ์ „ ์ ˆ๋‹จ)
  2. ์ „์ฒด ์ถœ๋ ฅ์„ /tmp/cmd-output/cmd-{n}.txt์— ์ €์žฅ
  3. ํƒ์ƒ‰ ๊ฐ€๋Šฅํ•œ ํ›„์† ๋ช…๋ น์–ด ์•ˆ๋‚ด

์ถœ๋ ฅ ์˜ˆ์‹œ:

[์ฒซ 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์˜ ๊ธฐ์กด ๊ธฐ์ˆ ๋กœ ์ž๋™ ๋ณ€ํ™˜๋œ๋‹ค.

๋งค ํ˜ธ์ถœ์˜ ๋งˆ์ง€๋ง‰ ์ค„์— 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 โ€” ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ผ๋ฐ˜ ๊ฐœ๋…

์ฐธ๊ณ  ๋ฌธ์„œ