Repository navigation
Expand file tree
/
Copy pathweek-01.html
More file actions
619 lines (540 loc) · 45.8 KB
/
Copy pathweek-01.html
File metadata and controls
619 lines (540 loc) · 45.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Agentic AI Week 01: 에이전트란 무엇인가</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=IBM+Plex+Mono:wght@400;500&family=Noto+Serif+KR:wght@500;600&display=swap" rel="stylesheet">
<style>
:root{
--paper:#FFFFFF;
--ink:#1C1917;
--body:#44403C;
--muted:#78716C;
--faint:#A8A29E;
--line:#E7E5E4;
--wash:#FAFAF9;
--link:#2563EB;
--mono:'IBM Plex Mono', ui-monospace, monospace;
--sans:'Pretendard Variable', Pretendard, -apple-system, sans-serif;
--serif:Fraunces, 'Noto Serif KR', Georgia, serif;
--maxw:680px;
--r:8px;
}
*{margin:0;padding:0;box-sizing:border-box}
body{
background:var(--paper);
color:var(--body);
font-family:var(--sans);
font-weight:400;
line-height:1.8;
font-size:15.5px;
word-break:keep-all;
overflow-wrap:break-word;
-webkit-font-smoothing:antialiased;
}
::selection{background:var(--ink);color:var(--paper)}
a{color:var(--link);text-decoration:none}
a:hover{text-decoration:underline}
/* ---------- layout ---------- */
.sheet{max-width:1040px;margin:0 auto;padding:0 24px}
.col{max-width:var(--maxw);margin:0 auto;position:relative}
/* ---------- header ---------- */
header.doc{padding:40px 0 0}
.topnav{font-family:var(--mono);font-size:11px;letter-spacing:.04em;margin-bottom:56px;display:flex;justify-content:space-between;gap:16px}
.masthead{padding-bottom:64px;border-bottom:1px solid var(--line)}
.masthead .wk{
font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;
color:var(--faint);margin-bottom:16px;
}
h1.title{
font-family:var(--serif);font-weight:500;
font-size:clamp(30px,4.6vw,44px);line-height:1.2;
letter-spacing:-0.01em;color:var(--ink);text-wrap:balance;
}
h1.title .en{display:block;font-family:var(--mono);font-size:12px;font-weight:400;color:var(--muted);letter-spacing:.06em;margin-top:14px}
.lede{
margin-top:26px;max-width:560px;font-size:16px;line-height:1.85;color:var(--muted);
}
.lede .q{font-weight:600;color:var(--ink)}
/* ---------- section scaffolding ---------- */
section{padding:56px 0 8px}
.secmark{
display:flex;align-items:baseline;gap:14px;margin-bottom:32px;
border-top:1px solid var(--line);padding-top:20px;
}
.secmark .no{
font-family:var(--mono);font-weight:500;font-size:10.5px;color:var(--faint);
letter-spacing:.12em;white-space:nowrap;text-transform:uppercase;
}
.secmark h2{font-family:var(--serif);font-weight:500;font-size:clamp(21px,2.8vw,26px);line-height:1.3;letter-spacing:-0.005em;color:var(--ink);text-wrap:balance}
h3{font-family:var(--serif);font-weight:500;font-size:18px;margin:44px 0 14px;color:var(--ink)}
h3 .tag{font-family:var(--mono);font-size:10px;color:var(--faint);letter-spacing:.12em;display:block;margin-bottom:6px;font-weight:500}
p{margin-bottom:20px}
strong{font-weight:600;color:var(--ink)}
em{font-style:normal;font-weight:600;color:var(--ink);box-shadow:inset 0 -0.35em 0 rgba(28,25,23,.07)}
.small{font-size:13.5px;color:var(--muted)}
.nb{white-space:nowrap}
/* part banner */
.part{
margin:72px 0 8px;border-top:2px solid var(--ink);
padding:24px 0 6px;
}
.part .lbl{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;color:var(--muted);font-weight:500;margin-bottom:10px;text-transform:uppercase}
.part h2{font-family:var(--serif);font-weight:500;font-size:clamp(20px,2.6vw,25px);line-height:1.35;color:var(--ink)}
.part .meta{font-family:var(--mono);font-size:10.5px;color:var(--faint);margin-top:10px;letter-spacing:.03em}
/* marginalia */
.note{
font-family:var(--mono);font-size:11px;line-height:1.75;color:var(--faint);
border-left:2px solid var(--line);padding-left:12px;margin:26px 0;
}
@media(min-width:1120px){
.note{position:absolute;width:190px;left:calc(50% + var(--maxw)/2 + 36px);margin:0;transform:translateY(-100%)}
}
.note b{color:var(--muted);font-weight:500;display:block;margin-bottom:4px;letter-spacing:.08em}
/* pull quote */
.pull{
margin:40px 0;padding:2px 0 2px 24px;border-left:2px solid var(--ink);
font-family:var(--serif);font-size:19px;line-height:1.65;font-weight:500;color:var(--ink);
}
.pull .src{display:block;font-family:var(--mono);font-size:10.5px;color:var(--faint);font-weight:400;margin-top:10px;letter-spacing:.03em}
/* definition */
.define{margin:48px 0;background:var(--wash);border:1px solid var(--line);border-radius:var(--r);padding:32px 32px 26px;position:relative}
.define::before{
content:"DEFINITION";position:absolute;top:14px;left:32px;
font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;color:var(--faint);font-weight:500;
}
.define p{margin:16px 0 0;font-family:var(--serif);font-size:clamp(16px,2.1vw,19px);line-height:1.7;font-weight:500;color:var(--ink)}
.define .sub{font-family:var(--sans);font-size:12.5px;font-weight:400;color:var(--muted);margin-top:14px}
.define ul{margin:14px 0 0 22px;padding:0}
.define li{font-family:var(--serif);font-size:clamp(15px,2vw,17px);line-height:1.9;font-weight:500;color:var(--ink)}
@media(max-width:640px){.define{padding:28px 20px 22px}.define::before{left:20px}}
/* instructor */
.bio{margin:8px 0 0;border:1px solid var(--line);border-radius:var(--r);padding:26px 28px 20px}
.bio{display:flex;gap:28px;align-items:flex-start}
.bio .photo{flex:0 0 210px;width:210px;height:262px;object-fit:cover;object-position:38% 12%;border-radius:6px;display:block}
.bio .info{flex:1 1 auto;min-width:0}
.bio .name{font-family:var(--serif);font-weight:500;font-size:19px;color:var(--ink);margin-bottom:2px}
.bio .role{font-family:var(--mono);font-size:10.5px;color:var(--muted);letter-spacing:.1em;margin-bottom:14px;text-transform:uppercase}
.bio p{font-size:14px;line-height:1.85;color:var(--body);margin-bottom:12px}
.bio .links{font-family:var(--mono);font-size:11.5px;letter-spacing:.02em}
.bio .links a{white-space:nowrap}
.bio .links span{color:var(--faint);margin:0 8px}
@media(max-width:640px){.bio{flex-direction:column}.bio .photo{width:100%;height:200px;flex:none}.bio{padding:22px 18px 16px}}
/* table */
.tbl-wrap{margin:28px 0;overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:13.5px;line-height:1.7}
th{
font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;text-align:left;text-transform:uppercase;
border-bottom:1px solid var(--ink);
padding:10px 14px;font-weight:500;color:var(--muted);
}
td{padding:13px 14px;border-bottom:1px solid var(--line);vertical-align:top}
td.stage{font-weight:600;color:var(--ink);white-space:nowrap;font-size:13px}
td .m{font-family:var(--mono);font-size:11.5px;color:var(--muted)}
/* figure */
.fig{margin:40px 0;border:1px solid var(--line);border-radius:var(--r);padding:26px 22px 14px}
.fig .cap{
font-family:var(--mono);font-size:10.5px;letter-spacing:.04em;color:var(--faint);
margin-top:12px;display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;
}
.fig .cap b{color:var(--muted);font-weight:500}
.fig svg{width:100%;height:auto;display:block}
.fig img{width:100%;height:auto;display:block}
svg text{font-family:var(--mono)}
/* code */
.code{
margin:28px 0;background:var(--wash);color:var(--ink);
font-family:var(--mono);font-size:12.5px;line-height:1.7;
padding:20px 22px;overflow-x:auto;border:1px solid var(--line);border-radius:var(--r);
}
.code .file{
display:block;font-size:10px;letter-spacing:.1em;color:var(--muted);
margin-bottom:14px;font-weight:500;text-transform:uppercase;
}
.code pre{font-family:inherit;white-space:pre;margin:0}
.code .cm{color:var(--faint)}
.code .kw{color:#1D4ED8}
.code .st{color:#15803D}
code.inline{
font-family:var(--mono);font-size:.85em;background:var(--wash);
padding:2px 6px;border:1px solid var(--line);border-radius:4px;white-space:nowrap;
}
/* numbered steps */
.pre{counter-reset:pre;margin:24px 0}
.pre>li{list-style:none;position:relative;padding:16px 0 16px 48px;border-bottom:1px solid var(--line)}
.pre>li:first-child{border-top:1px solid var(--line)}
.pre>li::before{
counter-increment:pre;content:counter(pre);
position:absolute;left:4px;top:18px;width:24px;height:24px;
border:1px solid var(--faint);border-radius:50%;color:var(--muted);
font-family:var(--mono);font-weight:500;font-size:11.5px;
display:flex;align-items:center;justify-content:center;
}
.pre b.lead{font-weight:600;color:var(--ink)}
/* discussion */
.open{border:1px solid var(--line);border-radius:var(--r);padding:26px 28px;margin:40px 0;background:var(--wash)}
.open .lbl{font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;color:var(--muted);font-weight:500;margin-bottom:14px;text-transform:uppercase}
.open ol{margin-left:20px}
.open li{margin-bottom:12px;line-height:1.8}
@media(max-width:640px){.open{padding:20px 18px}}
/* checkpoint */
.check{margin:28px 0;border:1px solid var(--ink);border-radius:var(--r);padding:18px 22px 14px}
.check .lbl{font-family:var(--mono);font-size:10px;letter-spacing:.14em;color:var(--paper);background:var(--ink);border-radius:4px;display:inline-block;padding:3px 9px;font-weight:500;margin-bottom:12px}
.check ul{margin-left:20px}
.check li{margin-bottom:8px;line-height:1.75}
/* recorder metrics */
.recorder{margin:32px 0;border-top:1px solid var(--ink)}
.recorder>div{display:flex;gap:18px;padding:13px 0;border-bottom:1px solid var(--line)}
.recorder .k{font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;color:var(--muted);font-weight:500;flex:0 0 120px;padding-top:3px;text-transform:uppercase}
.recorder .v{font-size:13.5px;line-height:1.7;color:var(--body)}
@media(max-width:640px){.recorder>div{flex-direction:column;gap:4px}}
/* notice */
.notice{margin:36px 0;border:1px solid var(--line);border-radius:var(--r);padding:24px 26px 18px}
.notice .lbl{font-family:var(--mono);font-size:10px;letter-spacing:.12em;color:var(--muted);font-weight:500;margin-bottom:14px;text-transform:uppercase}
.notice p{margin-bottom:13px;font-size:14px}
.notice ul{margin:0 0 13px 22px}
.notice li{margin-bottom:8px;font-size:13.5px;line-height:1.75}
@media(max-width:640px){.notice{padding:20px 18px 14px}}
/* homework */
.hw{margin:40px 0;border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.hw .head{
border-bottom:1px solid var(--line);background:var(--wash);padding:11px 22px;
font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;font-weight:500;color:var(--muted);text-transform:uppercase;
}
.hw .body{padding:22px 24px 8px}
.hw .due{font-family:var(--mono);font-size:11px;color:var(--faint);letter-spacing:.05em;margin-bottom:13px;font-weight:500}
/* readings */
.readings{margin:24px 0}
.readings>li{list-style:none;position:relative;padding:18px 0 18px 60px;border-bottom:1px solid var(--line)}
.readings>li:first-child{border-top:1px solid var(--line)}
.readings .badge{
position:absolute;left:0;top:20px;
font-family:var(--mono);font-weight:500;font-size:10px;letter-spacing:.06em;
padding:3px 8px;border-radius:4px;
}
.readings .badge.req{background:var(--ink);color:var(--paper)}
.readings .badge.opt{border:1px solid var(--faint);color:var(--faint)}
.readings b.lead{font-weight:600;color:var(--ink)}
.readings .why{display:block;font-size:13px;color:var(--muted);margin-top:6px}
/* next week */
.next{margin:64px 0 0;border-top:2px solid var(--ink);padding-top:22px}
.next .lbl{font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;color:var(--muted);font-weight:500;margin-bottom:12px;text-transform:uppercase}
.next p{font-size:14px;color:var(--body)}
/* footer */
footer{
margin-top:64px;border-top:1px solid var(--line);
padding:20px 0 56px;display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
font-family:var(--mono);font-size:10.5px;color:var(--faint);letter-spacing:.03em;
}
footer .o{color:var(--muted)}
@media(max-width:640px){body{font-size:15px}}
@media print{
body{font-size:10.5pt}
.topnav{display:none}
}
</style>
</head>
<body>
<div class="sheet">
<header class="doc">
<div class="col">
<div class="topnav"><a href="index.html">← COURSE HOME</a><a href="week-01-en.html">EN</a></div>
<div class="masthead">
<div class="wk">WEEK 01</div>
<h1 class="title">에이전트란 무엇인가
<span class="en">What Is an Agent?</span>
</h1>
<p class="lede"><span class="q">ChatGPT는 에이전트인가?</span> 오늘은 1995년의 정의부터 확인하고, 지금의 도구들이 그 기준에 맞는지 따져 본다.</p>
</div>
</div>
</header>
<!-- ============ 강사 소개 ============ -->
<section>
<div class="col">
<div class="secmark"><span class="no">00</span><h2>Introduction</h2></div>
<div class="bio">
<img class="photo" src="assets/speaker-lecture.jpeg" alt="강의 중인 이재규">
<div class="info">
<div class="name">이재규 <span style="font-weight:400;color:var(--faint)">Jaegyu Lee</span></div>
<div class="role">SOFTWARE ENGINEER / OPEN SOURCE MAINTAINER</div>
<p>10년차 소프트웨어 엔지니어로, 지금은 ZEP에 있다. 이 수업이 열리는 서울과학기술대학교 대학원에서 석사를 마쳤고, 데이터 파이프라인과 분산 시스템을 연구해 BIGCOMP와 Frontiers in Big Data에 논문을 냈다.</p>
<p>ZEP에서는 400만 MAU 규모의 WebRTC 클러스터를 운영한다. LiveKit Cloud에 있던 이 클러스터를 OCI 자체 운영으로 옮기며 인프라 비용을 60% 줄였고, 그 과정을 Oracle Digital Native Roundtable에서 발표했다.</p>
<p>오픈소스 Agent OS인 Ouroboros를 만들고 있다. 인터뷰로 요구사항을 Seed로 확정하고, 실행 결과를 deterministic gate로 검증하는 에이전트 프레임워크다. ZEP QUIZ(월 60만 건 이상의 퀴즈)에는 도구를 스스로 개선하는 에이전트가 있다. 이 구조로 ICML 2026 AI×Education 워크숍에서 발표했다.</p>
<div class="links"><a href="https://wpti.dev">wpti.dev</a><span>/</span><a href="https://github.com/Q00">github</a><span>/</span><a href="https://www.linkedin.com/in/q00">linkedin</a><span>/</span><a href="https://www.youtube.com/@Q00_Dev">youtube</a><span>/</span><a href="https://x.com/Jqonly">x</a><span>/</span><a href="mailto:jaegyu.lee@ourolabs.ai">jaegyu.lee@ourolabs.ai</a></div>
</div>
</div>
</div>
</section>
<!-- ============ 구성 ============ -->
<section>
<div class="col">
<div class="secmark"><span class="no">01</span><h2>오늘의 구성</h2></div>
<div class="tbl-wrap">
<table>
<tr><th>구분</th><th>내용</th></tr>
<tr><td class="stage">A1</td><td>에이전트 정의의 역사</td></tr>
<tr><td class="stage">A2</td><td>40년 계보: Contract Net에서 A2A까지</td></tr>
<tr><td class="stage">A3</td><td>LLM 에이전트 해부</td></tr>
<tr><td class="stage">토론</td><td>The Bitter Lesson</td></tr>
<tr><td class="stage">LAB</td><td>첫 에이전트 구축, 저장소 포크와 첫 PR</td></tr>
</table>
</div>
</div>
</section>
<!-- ============ PART A ============ -->
<div class="col">
<div class="part">
<div class="lbl">PART A: LECTURE</div>
<h2>에이전트란 무엇인가, 정의의 역사와 오늘의 재검증</h2>
<div class="meta">A1 정의의 역사, A2 40년 계보, A3 LLM 에이전트 해부, 토론</div>
</div>
</div>
<section>
<div class="col">
<div class="secmark"><span class="no">A1</span><h2>에이전트 정의의 역사: 1995년의 두 가지 개념</h2></div>
<p>오늘날 ‘에이전트’라는 말은 챗봇에도, 자동화 스크립트에도, 백그라운드 데몬에도 붙는다. 같은 단어로 서로 다른 것을 이야기하고 있으니, 어떤 시스템을 에이전트라고 부를지 판정할 기준부터 세워야 한다. 그 기준의 출발점은 Michael Wooldridge와 Nicholas Jennings가 1995년에 발표한 논문 “Intelligent Agents: Theory and Practice”다. 이 논문은 그때까지 마구 섞여 쓰이던 ‘에이전트’라는 용어를 두 개의 명확한 개념으로 정리했다. 이 구분은 30년이 지난 지금도 그대로 쓰인다.</p>
<p>첫 번째를 저자들은 <strong><span class="nb">약한 개념(weak notion)</span></strong>이라 부른다. 어떤 시스템을 에이전트라고 부르려면 최소한 네 가지 성질을 가져야 한다는 것이다.</p>
<div class="define">
<p>약한 개념의 에이전트는 네 속성을 만족한다.</p>
<ul>
<li><span class="nb">자율성(autonomy)</span></li>
<li><span class="nb">반응성(reactivity)</span></li>
<li><span class="nb">사전능동성(pro-activeness)</span></li>
<li><span class="nb">사회성(social ability)</span></li>
</ul>
<p class="sub">M. Wooldridge & N. Jennings, “Intelligent Agents: Theory and Practice” (1995)</p>
</div>
<p><strong>자율성</strong>이란 인간이나 다른 존재의 직접적 개입 없이 스스로 동작하고, 자기 행동과 내부 상태를 어느 정도 통제한다는 뜻이다. 매 단계 사람이 버튼을 눌러 줘야 움직이는 것은 도구이지 에이전트가 아니다. <strong>반응성</strong>은 환경을 지각하고 그 변화에 시의적절하게 응답하는 능력이다. 환경은 계속 변하므로, 미리 짜 둔 순서만 재생하는 시스템은 반응적이라 할 수 없다. <strong>사전능동성</strong>은 그 반대 방향의 성질이다. 단지 자극에 반응하는 데 그치지 않고 스스로 목표를 세우고 주도적으로 그 목표를 향해 행동하는 능력이다. 반응성만 있으면 수동적 반사에 머물고, 사전능동성만 있으면 환경 변화를 놓친다. 마지막으로 <strong>사회성</strong>은 다른 에이전트나 인간과 통신 언어로 상호작용하는 능력이다.</p>
<p>두 번째는 <strong><span class="nb">강한 개념(strong notion)</span></strong>이다. 주로 인공지능 연구자들이 쓰는 이 개념은, 위의 네 속성에 더해 인간에게나 어울릴 법한 정신적 속성들을 시스템에 부여한다. 대표적인 것이 <span class="nb">믿음(belief)</span>, <span class="nb">욕구(desire)</span>, <span class="nb">의도(intention)</span>로 이루어진 이른바 BDI 모델이다. 에이전트가 세계에 대한 믿음을 가지고, 이루고자 하는 욕구를 품으며, 그중 실제로 추구하기로 정한 의도를 갖는다고 보는 것이다. 여기에 지식, 나아가 감정 같은 속성을 얹기도 한다. 강한 개념은 에이전트를 하나의 <span class="nb">지향적 시스템(intentional system)</span>으로 다룬다. 즉 그 행동을 ‘저 시스템은 X를 믿기 때문에 Y를 하려 한다’는 식으로 설명하는 것이 유용해지는 대상으로 본다.</p>
<p>Wooldridge와 Jennings는 이 지향적 어휘를 <strong>설계와 분석의 도구</strong>로 쓰자고 강조했다. 복잡한 시스템의 행동을 물리적 수준이나 코드 수준에서 낱낱이 추적하는 대신, ‘믿음’과 ‘의도’라는 상위 어휘로 기술하면 예측과 설명이 훨씬 간결해진다. 우리가 LLM에게 “너는 사용자가 급하다고 판단했으니 가장 빠른 방법을 택하라”고 프롬프트를 쓸 때, 우리는 바로 그 지향적 어휘로 시스템을 설계하고 있다. 30년 전에는 이 어휘를 코드로 억지로 구현해야 했지만, 지금은 모델이 그 어휘를 이미 알아듣는다.</p>
<p>세 개념의 경계를 분명히 하기 위해, 저자들이 든 대조를 우리 식으로 확장해 보자. <strong>프로그램</strong>은 입력을 받아 정해진 절차대로 출력을 낸다. 자율성도 반응성도 요구되지 않는다. 함수를 호출하면 값을 내놓을 뿐, 부르지 않는 한 아무것도 하지 않는다. <strong><span class="nb">객체(object)</span></strong>는 여기서 한 걸음 나아가 상태와 행위를 캡슐화하고 메시지를 주고받지만, 그 메시지에 응할지 말지를 스스로 정하지 못한다. 다른 객체가 공개 메서드를 호출하면 객체는 그 요청을 수행해야 한다. 통제권이 호출하는 쪽에 있다. 반면 에이전트는 요청을 받고도 자기 목표에 비추어 응할지 거절할지를 판단한다. 이 차이를 저자들의 표현을 빌려 요약하면 다음과 같다.</p>
<div class="pull">객체는 공짜로 한다. 에이전트는 원해서 한다.<span class="src">“Objects do it for free; agents do it because they want to.” Wooldridge, 에이전트와 객체의 차이를 정리한 문장</span></div>
<p>어떤 시스템을 놓고 “이것은 요청받았기 때문에 하는가, 아니면 자기 목표에 부합한다고 판단했기 때문에 하는가”를 물으면, 그 시스템이 객체의 세계에 있는지 에이전트의 세계에 있는지가 드러난다. 오늘 실습에서 만드는 코드가 이 경계에 있다. while 루프 하나가 이 코드를 객체에서 에이전트로 바꾼다.</p>
<div class="note"><b>WEAK VS STRONG</b>이 수업에서는 대체로 weak notion으로 채점한다. strong notion(belief, desire, intention)은 유용한 설계 어휘이되, 시스템이 실제로 그것을 ‘가졌다’고 증명할 길은 없기 때문이다. 우리는 관찰 가능한 행동으로 판정한다.</div>
</div>
</section>
<section>
<div class="col">
<div class="secmark"><span class="no">A2</span><h2>40년 계보: Contract Net에서 A2A까지</h2></div>
<p>에이전트 통신의 역사는 대략 40년에 걸쳐 있다. 1980년대와 1990년대에는 야심찬 프로토콜들이 쏟아졌다. 2000년대에는 표준화가 진행되면서 오히려 조용해졌다. 2022년 이후에는 대형 언어모델과 함께 같은 문제가 다른 이름으로 다시 나타났다.</p>
<p>출발점은 1980년, Reid G. Smith의 <strong>Contract Net Protocol</strong>이다. 여러 처리 노드가 흩어진 분산 문제 해결 상황에서, 일을 어떻게 나눌 것인가라는 물음에 내놓은 답이었다. 관리자 역할의 노드가 할 일을 <span class="nb">공고(task announcement)</span>하면, 능력 있는 노드들이 <span class="nb">입찰(bid)</span>하고, 관리자가 <span class="nb">낙찰(award)</span>한다. 시장의 은유를 계산 자원 할당에 끌어들였다. 관리자와 계약자 역할은 태스크마다 동적으로 바뀐다. 이 프로토콜은 3주차 실습에서 LLM 에이전트로 재현한다.</p>
<p>1990년대에는 통신의 <strong>형식</strong>을 표준화하려는 시도가 무르익었다. KQML(Knowledge Query and Manipulation Language)과 이어진 FIPA-ACL(Agent Communication Language)이 그 결실이다. 이들은 언어철학의 <span class="nb">화행 이론(speech act theory)</span>에 기대어, 메시지에 ‘알림’, ‘요청’, ‘제안’ 같은 <span class="nb">수행적 유형(performative)</span>을 붙였다. 그러나 이 시도는 실패했고, 그 원인과 LLM이 그중 무엇을 해결하는지는 4주차에서 다룬다.</p>
<p>2000년대는 역설적으로 조용한 시기다. 표준 문서는 정교해졌지만 정작 널리 쓰이는 에이전트 생태계는 오지 않았다. 프로토콜은 있었으나 그 프로토콜을 채울 만큼 똑똑한 에이전트가 없었다.</p>
<p>전환점은 2022년, Yao 등이 제안한 <strong>ReAct</strong>다. <span class="nb">추론(reasoning)</span>과 <span class="nb">행동(acting)</span>을 언어모델 안에서 엮어, 모델이 생각하고 도구를 쓰고 결과를 관찰한 뒤 다시 생각하는 루프를 만들었다. 이어 2024년 <strong>MCP</strong>(Model Context Protocol)는 모델과 에이전트가 도구와 컨텍스트에 연결되는 규격을 표준화했고, 2025년 <strong>A2A</strong>(Agent2Agent)는 자율 에이전트 사이의 발견과 태스크 위임을, <strong>ACP</strong>(Agent Client Protocol)는 코드 편집기와 코딩 에이전트 사이의 세션, 프롬프트, 도구 호출, diff, 권한 상호작용을 표준화하려 했다.</p>
<div class="fig" id="fig1">
<svg viewBox="0 0 680 300" role="img" aria-label="Forty-year timeline of agent communication protocols: from Contract Net in 1980 to A2A and the Agent Client Protocol in 2025">
<line x1="40" y1="150" x2="640" y2="150" stroke="#1C1917" stroke-width="1.5"/>
<path d="M628 144 L642 150 L628 156" fill="none" stroke="#1C1917" stroke-width="1.5"/>
<rect x="250" y="120" width="150" height="60" fill="none" stroke="#A8A29E" stroke-width="1" stroke-dasharray="4 4"/>
<text x="325" y="112" text-anchor="middle" fill="#A8A29E" font-size="10">2000s: standards and silence</text>
<g>
<circle cx="70" cy="150" r="5" fill="#1C1917"/>
<circle cx="200" cy="150" r="5" fill="#78716C"/>
<circle cx="325" cy="150" r="5" fill="#A8A29E"/>
<circle cx="440" cy="150" r="5" fill="#1C1917"/>
<circle cx="530" cy="150" r="5" fill="#78716C"/>
<circle cx="620" cy="150" r="5" fill="#1C1917"/>
</g>
<g font-size="12" fill="#78716C" text-anchor="middle">
<text x="70" y="180" font-weight="600">1980</text>
<text x="70" y="196" font-size="10" fill="#78716C">Contract Net</text>
<text x="200" y="128" font-weight="600">1990s</text>
<text x="200" y="112" font-size="10" fill="#78716C">KQML / FIPA</text>
<text x="440" y="180" font-weight="600">2022</text>
<text x="440" y="196" font-size="10" fill="#78716C">ReAct</text>
<text x="530" y="128" font-weight="600">2024</text>
<text x="530" y="112" font-size="10" fill="#78716C">MCP</text>
<text x="620" y="180" font-weight="600">2025</text>
<text x="620" y="196" font-size="10" fill="#78716C">A2A / ACP</text>
</g>
<text x="355" y="245" font-size="10" fill="#1C1917" text-anchor="middle">Twenty years of protocols with no agents to use them</text>
</svg>
<div class="cap"><span><b>FIG. 01</b> Forty years of agent communication</span><span>1980 → 2025</span></div>
</div>
<p>A2A의 agent card는 FIPA가 풀려던 발견 문제를 되살리고, ACP는 IDE마다 코딩 에이전트를 따로 통합해야 하는 N×M 문제를 공통 client-agent 경계로 줄인다.</p>
</div>
</section>
<section>
<div class="col">
<div class="secmark"><span class="no">A3</span><h2>LLM 에이전트 해부</h2></div>
<p>“ChatGPT는 에이전트인가?”에 답하려면 먼저 LLM 에이전트가 실제로 무엇으로 이루어져 있는지 봐야 한다.</p>
<p>LLM 에이전트는 세 부분으로 이루어진다. 첫째는 <strong>모델</strong>이다. 텍스트를 받아 다음 텍스트를 내놓는 함수로, 그 자체로는 상태도 기억도 없고 외부 세계에 영향을 주지도 못한다. 둘째는 <strong>컨텍스트</strong>다. 모델에게 매 호출마다 건네는 입력 전체, 곧 시스템 프롬프트, 지금까지의 대화, 관찰된 결과, 사용 가능한 도구의 목록과 설명을 말한다. 모델은 컨텍스트에 들어 있는 것만 본다. 셋째는 <strong>도구 루프</strong>다. 모델이 “이 도구를 이런 인자로 부르겠다”고 출력하면, 바깥의 프로그램이 실제로 그 도구를 실행하고, 결과를 다시 컨텍스트에 얹어 모델을 또 부른다. 이 부르고 실행하고 되먹이는 순환이 멈출 때까지 반복된다.</p>
<div class="define">
<p>LLM 에이전트 = 모델 + 컨텍스트 + 도구 루프.</p>
<p class="sub">이 수업의 작업 정의. W&J의 네 속성을 이 세 부품으로 구현한 것</p>
</div>
<p><em>자율성은 모델이 아니라 루프에서 나온다.</em> 모델 한 번의 호출은 그저 프로그램이다. 입력을 넣으면 출력이 나온다. 그러나 그 출력을 받아 도구를 실행하고 결과를 되먹여 다시 부르는 while 루프를 씌우는 순간, 시스템은 스스로 다음 행동을 정하고, 관찰에 반응하며, 목표에 도달할 때까지 멈추지 않는 무언가가 된다. 이 루프는 실습에서 스무 줄로 직접 쓴다.</p>
<p>이제 W&J의 네 속성으로 LLM 에이전트를 채점해 보자. <strong>자율성</strong>: 루프가 도는 동안에는 사람이 매 단계 개입하지 않는다. 다만 루프의 시작과 종료, 그리고 위험한 행동의 승인은 여전히 사람이 쥐고 있는 경우가 많다. <strong>반응성</strong>: 도구 실행 결과가 컨텍스트로 되먹여지고, 모델은 그에 따라 다음 수를 바꾼다. <strong>사전능동성</strong>: 목표를 프롬프트로 주면 모델은 중간 단계를 스스로 세운다. 이것이 ReAct가 준 능력이다. 다만 주어진 목표를 분해할 뿐, 새 목표를 세우지는 못한다. <strong>사회성</strong>: LLM 에이전트끼리 신뢰할 수 있게 발견하고, 위임하고, 검증하며 대화하는 표준은 아직 완성되지 않았다.</p>
<div class="tbl-wrap">
<table>
<tr><th>W&J 1995 속성</th><th>LLM 에이전트</th><th>판정</th></tr>
<tr><td class="stage">자율성</td><td>루프가 도는 동안 개입 없음. 단 시작, 종료, 승인은 인간이 보유</td><td><span class="m">부분 충족</span></td></tr>
<tr><td class="stage">반응성</td><td>도구 결과가 컨텍스트로 되먹여져 다음 수를 바꿈</td><td><span class="m">충족</span></td></tr>
<tr><td class="stage">사전능동성</td><td>주어진 목표를 스스로 중간 단계로 분해 (ReAct)</td><td><span class="m">대체로 충족</span></td></tr>
<tr><td class="stage">사회성</td><td>에이전트 간 발견, 위임, 검증 표준 미완성</td><td><span class="m">미충족 (이 수업의 주제)</span></td></tr>
</table>
</div>
<p>채팅창 안에서 사용자의 말에만 응답하는 기본 형태의 ChatGPT는, 엄밀히 말하면 반응적이지만 자율적이지도 사전능동적이지도 않다. 매 턴 사람의 입력을 기다리므로 루프의 주인이 사람이다. 이것은 대화 시스템이지 에이전트라고 부르기엔 미달이다. 그러나 같은 모델에 도구와 while 루프를 씌워, 즉 컨텍스트를 스스로 갱신하며 목표에 도달할 때까지 돌게 하면 약한 개념의 에이전트 자격을 대체로 갖추게 된다.</p>
</div>
</section>
<!-- ============ 토론 ============ -->
<section>
<div class="col">
<div class="open">
<div class="lbl">DISCUSSION: THE BITTER LESSON</div>
<p class="small" style="margin-bottom:16px">Richard Sutton은 2019년 에세이 “The Bitter Lesson”에서, AI의 70년 역사를 돌아보면 인간의 지식을 손으로 심어 넣은 방법들은 번번이 계산과 데이터의 <span class="nb">규모(scale)</span>를 앞세운 일반적 방법에 밀려났다고 주장했다. 탐색과 학습, 그리고 그것을 뒷받침하는 스케일이 결국 이긴다는 것이다. 이 주장은 이 수업의 전제와 정면으로 부딪힌다. 만약 스케일이 결국 모든 것을 해결한다면, 프로토콜과 계약과 검증을 공들여 연구하는 일은 시간 낭비가 아닌가?</p>
<ol>
<li>Sutton의 Bitter Lesson이 옳다면, 에이전트 사이의 통신 프로토콜(FIPA, MCP, A2A)도 결국 ‘손으로 심은 지식’에 불과해 더 큰 모델에 흡수될 운명인가? 아니면 프로토콜은 학습으로 대체될 수 없는 다른 종류의 문제인가?</li>
<li>신뢰, 부인 방지, 권한 위임의 범위 같은 것들은 ‘더 똑똑해지면’ 사라지는 문제인가, 아니면 아무리 똑똑한 에이전트라도 서로를 믿을 근거가 필요한 <em>구조적</em> 문제인가? 스케일로 지능은 키울 수 있어도 신뢰는 키울 수 없다면, 그 경계는 어디인가?</li>
<li>Bitter Lesson을 이 수업의 ‘반면교사’가 아니라 ‘설계 원칙’으로 받아들인다면, 우리의 재현 실험은 무엇을 ‘손으로 심지 말아야’ 하는가? 프로토콜의 어느 부분을 모델의 상식에 맡기고, 어느 부분을 명시적 규칙으로 남겨야 하는가?</li>
</ol>
</div>
</div>
</section>
<!-- ============ PART B ============ -->
<div class="col">
<div class="part">
<div class="lbl">PART B: LAB</div>
<h2>첫 에이전트: while 루프 + 도구 두 개</h2>
<div class="meta">GOAL: write the twenty-line loop that turns a model into an agent, fork the course repo, open your first PR</div>
</div>
</div>
<section>
<div class="col">
<div class="secmark"><span class="no">LAB</span><h2>루프가 에이전트를 만든다</h2></div>
<p>자율성은 모델이 아니라 루프에서 나온다는 것을 실습으로 확인한다. 계산기와 파일 읽기라는 도구 두 개를 모델에 쥐어 주고, 모델이 스스로 도구를 골라 부르고 결과를 관찰하며 답에 도달할 때까지 도는 while 루프를 만든다. 준비물은 Python 3.10 이상, <code class="inline">anthropic</code> 또는 <code class="inline">openai</code> 패키지, 그리고 API 키 하나다. 아래 예제는 표준 라이브러리와 <code class="inline">anthropic</code> 패키지만 쓴다.</p>
<ol class="pre">
<li><b class="lead">도구 두 개를 파이썬 함수로 정의한다.</b> 계산기는 문자열 수식을 받아 수를 돌려주고, 파일 읽기는 경로를 받아 내용을 돌려준다. 도구의 ‘설명’이 곧 모델이 읽는 인터페이스다.</li>
<li><b class="lead">모델에게 도구 목록을 컨텍스트로 건넨다.</b> 각 도구의 이름, 설명, 인자 스키마를 넘긴다. 모델은 이 목록에 있는 도구만 안다.</li>
<li><b class="lead">while 루프를 씌운다.</b> 모델이 도구를 부르면 실행해 결과를 되먹이고, 모델이 최종 답을 내면 루프를 끝낸다.</li>
<li><b class="lead">종료 조건과 안전장치를 넣는다.</b> 무한 루프를 막는 최대 반복 횟수, 그리고 파일 읽기 경로 제한 같은 최소한의 방어를 둔다.</li>
</ol>
<div class="code"><span class="file">first_agent.py</span><pre><span class="kw">import</span> os, ast, operator, anthropic
<span class="cm"># ---- 도구 1: 계산기 (eval 없이 안전하게) ----</span>
_OPS = {ast.Add: operator.add, ast.Sub: operator.sub,
ast.Mult: operator.mul, ast.Div: operator.truediv,
ast.Pow: operator.pow, ast.USub: operator.neg}
<span class="kw">def</span> _ev(node):
<span class="kw">if</span> isinstance(node, ast.Constant): <span class="kw">return</span> node.value
<span class="kw">if</span> isinstance(node, ast.BinOp):
<span class="kw">return</span> _OPS[type(node.op)](_ev(node.left), _ev(node.right))
<span class="kw">if</span> isinstance(node, ast.UnaryOp):
<span class="kw">return</span> _OPS[type(node.op)](_ev(node.operand))
<span class="kw">raise</span> ValueError(<span class="st">"허용되지 않은 식"</span>)
<span class="kw">def</span> calculator(expression: str) -> str:
<span class="st">"""수식 문자열을 계산한다. 예: '3 * (4 + 5)'"""</span>
<span class="kw">return</span> str(_ev(ast.parse(expression, mode=<span class="st">"eval"</span>).body))
<span class="cm"># ---- 도구 2: 파일 읽기 (작업 폴더 밖 접근 차단) ----</span>
<span class="kw">def</span> read_file(path: str) -> str:
<span class="st">"""텍스트 파일의 내용을 돌려준다."""</span>
full = os.path.abspath(path)
<span class="kw">if</span> <span class="kw">not</span> full.startswith(os.getcwd()):
<span class="kw">return</span> <span class="st">"거부: 작업 폴더 밖 경로"</span>
<span class="kw">with</span> open(full, encoding=<span class="st">"utf-8"</span>) <span class="kw">as</span> f:
<span class="kw">return</span> f.read()[:4000]
TOOLS_IMPL = {<span class="st">"calculator"</span>: calculator, <span class="st">"read_file"</span>: read_file}
<span class="cm"># ---- 모델에게 건넬 도구 스키마 (설명 = 인터페이스) ----</span>
TOOLS = [
{<span class="st">"name"</span>: <span class="st">"calculator"</span>,
<span class="st">"description"</span>: <span class="st">"산술 수식을 계산한다."</span>,
<span class="st">"input_schema"</span>: {<span class="st">"type"</span>: <span class="st">"object"</span>,
<span class="st">"properties"</span>: {<span class="st">"expression"</span>: {<span class="st">"type"</span>: <span class="st">"string"</span>}},
<span class="st">"required"</span>: [<span class="st">"expression"</span>]}},
{<span class="st">"name"</span>: <span class="st">"read_file"</span>,
<span class="st">"description"</span>: <span class="st">"작업 폴더의 텍스트 파일을 읽는다."</span>,
<span class="st">"input_schema"</span>: {<span class="st">"type"</span>: <span class="st">"object"</span>,
<span class="st">"properties"</span>: {<span class="st">"path"</span>: {<span class="st">"type"</span>: <span class="st">"string"</span>}},
<span class="st">"required"</span>: [<span class="st">"path"</span>]}},
]
<span class="kw">def</span> run(goal: str, max_steps: int = 8):
client = anthropic.Anthropic() <span class="cm"># ANTHROPIC_API_KEY 사용</span>
messages = [{<span class="st">"role"</span>: <span class="st">"user"</span>, <span class="st">"content"</span>: goal}]
<span class="kw">for</span> step <span class="kw">in</span> range(max_steps): <span class="cm"># ← 이 루프가 에이전트를 만든다</span>
resp = client.messages.create(
model=<span class="st">"claude-sonnet-4-5"</span>, max_tokens=1024,
tools=TOOLS, messages=messages)
messages.append({<span class="st">"role"</span>: <span class="st">"assistant"</span>, <span class="st">"content"</span>: resp.content})
<span class="kw">if</span> resp.stop_reason != <span class="st">"tool_use"</span>: <span class="cm"># 최종 답 → 종료</span>
<span class="kw">return</span> <span class="st">""</span>.join(b.text <span class="kw">for</span> b <span class="kw">in</span> resp.content
<span class="kw">if</span> b.type == <span class="st">"text"</span>)
results = []
<span class="kw">for</span> block <span class="kw">in</span> resp.content: <span class="cm"># 도구 호출 실행 → 관찰</span>
<span class="kw">if</span> block.type == <span class="st">"tool_use"</span>:
out = TOOLS_IMPL[block.name](**block.input)
print(<span class="st">f" [도구] </span>{block.name}<span class="st">(</span>{block.input}<span class="st">) → </span>{out}<span class="st">"</span>)
results.append({<span class="st">"type"</span>: <span class="st">"tool_result"</span>,
<span class="st">"tool_use_id"</span>: block.id, <span class="st">"content"</span>: str(out)})
messages.append({<span class="st">"role"</span>: <span class="st">"user"</span>, <span class="st">"content"</span>: results})
<span class="kw">return</span> <span class="st">"중단: 최대 반복 초과"</span> <span class="cm"># 종료 조건 = 안전장치</span>
<span class="kw">if</span> __name__ == <span class="st">"__main__"</span>:
print(run(<span class="st">"notes.txt를 읽고, 거기 적힌 숫자들의 합을 구해줘."</span>))</pre></div>
<p>이 코드의 핵심은 <code class="inline">for step in range(max_steps)</code> 한 줄이다. 이 루프를 지우고 <code class="inline">messages.create</code>를 한 번만 부르면, 그 순간 시스템은 다시 프로그램이 된다. 도구를 부르겠다는 텍스트만 남고, 어떤 도구도 실제로 실행되지 않는다. <code class="inline">notes.txt</code>에 숫자 몇 개를 적어 두고 직접 돌려 보라. 모델이 먼저 <code class="inline">read_file</code>을 부르고, 그 결과를 보고 나서 <code class="inline">calculator</code>를 부른다. 이 두 번의 호출이 콘솔에 그대로 찍힌다.</p>
<h3><span class="tag">SUBMIT</span>저장소 포크와 첫 PR</h3>
<p>이 수업의 모든 과제는 수업 저장소를 포크해 PR로 제출한다. 마감 판정은 PR을 연 시각 기준이다. 이 실습에서는 포크하고 첫 PR을 연다.</p>
<ol class="pre">
<li><b class="lead">수업 저장소를 포크하고 클론한다.</b> 저장소의 README와 <code class="inline">AGENTS.md</code>에 규칙 전부가 있다. 코딩 에이전트를 쓴다면 <code class="inline">AGENTS.md</code>부터 읽히고 시작한다.</li>
<li><b class="lead">roster에 자기 파일을 추가한다.</b> <code class="inline">roster/<학번>.md</code>를 만들어 자기 GitHub 아이디를 적는다.</li>
<li><b class="lead">upstream으로 PR을 열고 자동 검사를 확인한다.</b> Actions가 파일명과 GitHub 아이디를 대조한다. 검사가 통과하면 수업 중에 바로 머지한다. 이후 매주 <code class="inline">submissions/<학번>/</code> 제출 검사는 이 파일의 아이디와 대조한다.</li>
</ol>
<div class="check">
<div class="lbl">CHECKPOINT</div>
<ul>
<li><code class="inline">first_agent.py</code>가 <code class="inline">read_file</code> → <code class="inline">calculator</code>를 스스로 이어 호출하며 정답을 낸다.</li>
<li>루프를 제거하면 도구가 실제로 실행되지 않음을 직접 확인했다.</li>
<li>포크에서 연 roster PR이 자동 검사를 통과했다.</li>
<li>최대 반복 횟수와 파일 경로 제한이 실제로 동작함을 확인했다.</li>
</ul>
</div>
<p>제출 규칙은 매주 같다.</p>
<div class="recorder">
<div><span class="k">커밋</span><span class="v">squash 금지. 실패한 시도의 커밋도 채점 근거다.</span></div>
<div><span class="k">로그</span><span class="v">에이전트 실행 콘솔 출력을 <code class="inline">logs/</code>에 파일로 커밋한다.</span></div>
<div><span class="k">API 키</span><span class="v">커밋 금지. 환경변수로만 쓴다.</span></div>
</div>
<div class="notice">
<div class="lbl">LLM 사용 규정</div>
<p>LLM과 에이전트 도구는 모든 과제에서 자유롭게 써도 좋다. 단, 무엇을 시켰고 무엇을 버렸는지는 커밋 히스토리와 로그에 남아야 한다.</p>
<p style="margin-bottom:0">과제로 만든 코드와 프로젝트의 저작권은 만든 학생에게 있다.</p>
</div>
</div>
</section>
<!-- ============ 과제 ============ -->
<section>
<div class="col">
<div class="secmark"><span class="no">HW</span><h2>과제</h2></div>
<div class="hw">
<div class="head">ASSIGNMENT: WEEK 01</div>
<div class="body">
<div class="due">DUE: 다음 주 수업 시작 전</div>
<p><strong>제출물</strong>: 실습에서 만든 첫 에이전트에 도구를 <strong>하나 더</strong> 추가하고, 그 에이전트로 실제 태스크를 해결한다. 새 도구는 무엇이든 좋다. 웹에서 텍스트를 가져오는 fetch, 현재 시각을 알려주는 clock, 간단한 메모를 파일에 쓰는 write_note 같은 것들이다. 도구가 하나 늘었을 때 모델의 도구 선택 행동이 어떻게 달라지는지 관찰한다.</p>
<p><strong>형식</strong>: 포크의 <code class="inline">submissions/<학번>/week-01/</code>에 커밋하고 upstream으로 PR을 연다. (1) 실행되는 <code class="inline">first_agent.py</code>(도구 3개), (2) 새 도구를 왜 그렇게 설명했는지 한 문단(<code class="inline">TOOLS.md</code>), (3) 에이전트 실행 로그(<code class="inline">logs/</code>).</p>
<p><strong>채점 기준</strong>: 코드가 실제로 돌아가는가(재현성)가 절반이다. 다른 사람이 여러분의 코드와 설정만으로 같은 결과를 낼 수 있어야 한다. API 키를 제외한 모든 설정(모델명, 도구 스키마, 실행 방법)을 명시하라. 나머지 절반은 무엇을 시도하고 무엇을 버렸는지가 커밋 히스토리와 로그에 솔직하게 남아 있는가다.</p>
</div>
</div>
</div>
</section>
<!-- ============ 읽기자료 ============ -->
<section>
<div class="col">
<div class="secmark"><span class="no">READ</span><h2>읽기자료</h2></div>
<ul class="readings">
<li><span class="badge req">필수</span><b class="lead">M. Wooldridge & N. Jennings, “Intelligent Agents: Theory and Practice” (1995)</b><span class="why">이 강의의 원전. weak notion의 네 속성과 strong notion의 구분을 원문으로 확인하고, 이 네 속성으로 스스로 LLM 에이전트를 다시 채점해 보기 위해.</span></li>
<li><span class="badge req">필수</span><b class="lead">R. Sutton, “The Bitter Lesson” (2019)</b><span class="why">토론 준비 자료. ‘스케일이 이긴다’는 주장을 직접 읽고, 그렇다면 프로토콜 연구는 왜 하는가에 스스로 답을 정해 오기 위해.</span></li>
</ul>
<div class="next">
<div class="lbl">NEXT: WEEK 02</div>
<p><strong>같은 모델인데 왜 결과가 다른가</strong>. 다음 주는 이 질문에서 시작한다. 결과의 차이는 루프의 설계, ‘하네스’에서 나온다. ReAct(Yao et al. 2022)를 읽고 컨텍스트 관리, 도구 granularity, 종료 조건, 에러 복구, 인간 개입 지점을 익힌다. 실습에서는 같은 태스크에 하네스 변형 두 가지를 A/B로 붙여 직접 측정한다.</p>
</div>
</div>
</section>
<footer class="sheet">
<span>AGENTIC AI: <span class="o">에이전트 시스템의 이론과 구축</span></span>
<span>SEOULTECH 2026 FALL, WEEK 01/15</span>
</footer>
</div>
</body>
</html>