Repository navigation
Expand file tree
/
Copy pathagent-loop-viz.html
More file actions
1674 lines (1623 loc) · 68.9 KB
/
Copy pathagent-loop-viz.html
File metadata and controls
1674 lines (1623 loc) · 68.9 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
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Agent Loop 深度理解 — 从 ReAct 到 Harness</title>
<style>
/* ============ viz-framework.css (inlined) ============ */
:root {
--viz-bg: #0f1117;
--viz-card: #1a1d28;
--viz-border: #2a2d3a;
--viz-accent: #6c63ff;
--viz-green: #00d2a0;
--viz-orange: #ff9f43;
--viz-red: #ff6b6b;
--viz-blue: #4ecdc4;
--viz-text: #e4e6eb;
--viz-dim: #8b8fa3;
--viz-radius: 16px;
--viz-radius-sm: 8px;
--viz-font: -apple-system, "PingFang SC", "Microsoft YaHei", "Segoe UI", sans-serif;
}
*,*::before,*::after { margin: 0; padding: 0; box-sizing: border-box; }
body.viz-body {
font-family: var(--viz-font);
background: var(--viz-bg);
color: var(--viz-text);
line-height: 1.7;
overflow-x: hidden;
}
.viz-h1 { font-size: 36px; margin-bottom: 8px; }
.viz-h1 span, .viz-h1 em { color: var(--viz-accent); font-style: normal; }
.viz-h2 {
font-size: 26px; margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid var(--viz-accent);
display: inline-block;
}
.viz-subtitle { color: var(--viz-dim); font-size: 16px; margin-bottom: 40px; }
.viz-desc { color: var(--viz-dim); font-size: 15px; margin-bottom: 24px; max-width: 680px; }
.viz-hint { color: var(--viz-dim); font-size: 13px; margin-top: 16px; text-align: center; }
.viz-section { max-width: 960px; margin: 0 auto; padding: 100px 24px 60px; }
.viz-section + .viz-section { padding-top: 60px; }
.viz-nav {
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
background: rgba(15,17,23,0.92);
backdrop-filter: blur(12px);
border-bottom: 1px solid var(--viz-border);
display: flex; align-items: center; gap: 8px;
padding: 0 24px; height: 56px;
overflow-x: auto;
}
.viz-nav a {
color: var(--viz-dim); text-decoration: none; font-size: 14px;
padding: 8px 14px; border-radius: var(--viz-radius-sm);
white-space: nowrap; transition: all .2s;
}
.viz-nav a:hover, .viz-nav a.active { color: var(--viz-text); background: var(--viz-border); }
.viz-btn {
padding: 8px 20px; border-radius: var(--viz-radius-sm); border: none;
font-size: 14px; cursor: pointer; font-weight: 600;
font-family: var(--viz-font); transition: all .2s;
}
.viz-btn-primary { background: var(--viz-accent); color: #fff; }
.viz-btn-primary:hover { filter: brightness(1.2); }
.viz-btn-outline { background: transparent; border: 1px solid var(--viz-border); color: var(--viz-text); }
.viz-btn-outline:hover { border-color: var(--viz-accent); }
.viz-card-row { display: flex; gap: 20px; flex-wrap: wrap; margin-bottom: 32px; }
.viz-card {
flex: 1; min-width: 280px;
background: var(--viz-card); border: 1px solid var(--viz-border);
border-radius: var(--viz-radius); padding: 28px;
transition: border-color .3s;
}
.viz-card:hover { border-color: var(--viz-accent); }
.viz-card h3 { font-size: 18px; margin-bottom: 6px; }
.viz-card p { color: var(--viz-dim); font-size: 14px; }
.viz-tag {
display: inline-block; font-size: 12px;
padding: 2px 10px; border-radius: 20px; margin-bottom: 14px;
}
.viz-tag-accent { background: rgba(108,99,255,.2); color: var(--viz-accent); }
.viz-tag-green { background: rgba(0,210,160,.2); color: var(--viz-green); }
.viz-tag-orange { background: rgba(255,159,67,.2); color: var(--viz-orange); }
.viz-tag-red { background: rgba(255,107,107,.2); color: var(--viz-red); }
.viz-tag-blue { background: rgba(78,205,196,.2); color: var(--viz-blue); }
.viz-demo {
background: var(--viz-card); border-radius: var(--viz-radius);
padding: 32px; border: 1px solid var(--viz-border);
margin-bottom: 32px;
}
.viz-demo-header {
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 20px; flex-wrap: wrap; gap: 12px;
}
.viz-demo-header h3 { font-size: 16px; }
.viz-race-lanes { display: flex; gap: 40px; flex-wrap: wrap; }
.viz-race-lane { flex: 1; min-width: 200px; }
.viz-race-lane h4 { font-size: 14px; color: var(--viz-dim); margin-bottom: 12px; text-align: center; }
.viz-race-grid { display: flex; flex-wrap: wrap; gap: 4px; justify-content: center; min-height: 80px; }
.viz-race-worker { width: 28px; height: 28px; border-radius: 6px; transition: background .3s; }
.viz-race-worker.idle { background: var(--viz-border); }
.viz-race-worker.working { animation: vizPulse .5s ease-in-out infinite alternate; }
.viz-race-worker.done { background: var(--viz-green); }
.viz-progress { margin-top: 16px; height: 8px; border-radius: 4px; background: var(--viz-border); overflow: hidden; }
.viz-progress-fill { height: 100%; border-radius: 4px; width: 0%; transition: width .1s linear; }
.viz-timer { text-align: center; margin-top: 8px; font-size: 13px; color: var(--viz-dim); }
@keyframes vizPulse { from { background: var(--viz-accent); } to { background: #8b7fff; } }
.viz-capacity-btns { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.viz-capacity-btns .viz-btn { font-size: 13px; padding: 6px 14px; }
.viz-capacity-area { display: flex; gap: 24px; flex-wrap: wrap; }
.viz-container {
flex: 1; min-width: 260px;
border: 2px dashed var(--viz-border); border-radius: 12px;
padding: 16px; position: relative;
min-height: 180px; display: flex; flex-direction: column;
}
.viz-container-label {
position: absolute; top: -12px; left: 16px;
background: var(--viz-card); padding: 0 8px;
font-size: 13px; color: var(--viz-dim);
}
.viz-container-items { flex: 1; display: flex; flex-wrap: wrap; gap: 6px; align-content: flex-start; padding-top: 8px; }
.viz-capacity-block {
height: 32px; border-radius: 6px; display: flex;
align-items: center; justify-content: center;
font-size: 11px; font-weight: 600; color: #fff;
transition: all .4s ease;
}
.viz-container-footer {
margin-top: 12px; padding-top: 8px;
border-top: 1px solid var(--viz-border);
font-size: 12px; color: var(--viz-dim);
display: flex; justify-content: space-between;
}
.viz-overflow-msg { color: var(--viz-red); font-size: 13px; margin-top: 12px; min-height: 20px; }
.viz-conveyor-lanes { display: flex; gap: 32px; flex-wrap: wrap; }
.viz-conveyor-lane { flex: 1; min-width: 260px; text-align: center; }
.viz-conveyor-lane h4 { font-size: 14px; margin-bottom: 12px; }
.viz-conveyor {
height: 48px; border-radius: var(--viz-radius-sm);
background: #1e2030; position: relative; overflow: hidden;
border: 1px solid var(--viz-border);
}
.viz-conveyor-packet {
position: absolute; top: 50%; transform: translateY(-50%);
width: 24px; height: 24px; border-radius: 4px;
font-size: 10px; display: flex; align-items: center; justify-content: center;
color: #fff; font-weight: 700;
}
.viz-conveyor-stat { margin-top: 8px; font-size: 13px; color: var(--viz-dim); }
.viz-pipe-pairs { display: flex; gap: 20px; flex-wrap: wrap; }
.viz-pipe-box {
flex: 1; min-width: 280px; padding: 20px;
border: 1px solid var(--viz-border); border-radius: 12px; text-align: center;
}
.viz-pipe-pair { display: flex; align-items: center; justify-content: center; gap: 12px; margin: 16px 0; }
.viz-pipe-chip {
width: 72px; height: 56px; border-radius: 10px;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
font-size: 12px; font-weight: 700; color: #fff;
}
.viz-pipe-chip span { font-size: 10px; font-weight: 400; color: rgba(255,255,255,.7); }
.viz-pipe-line { flex: 1; max-width: 100px; height: 12px; border-radius: 6px; position: relative; overflow: hidden; }
.viz-pipe-line-inner { position: absolute; top: 0; left: -40px; width: 40px; height: 100%; border-radius: 6px; }
.viz-pipe-line.slow { background: #2a3a2a; }
.viz-pipe-line.slow .viz-pipe-line-inner { background: var(--viz-green); animation: vizPipeFlow 2s linear infinite; }
.viz-pipe-line.fast { background: #2a2a4a; }
.viz-pipe-line.fast .viz-pipe-line-inner { background: var(--viz-accent); animation: vizPipeFlow .3s linear infinite; }
@keyframes vizPipeFlow { to { left: 100%; } }
.viz-speed-compare { display: flex; align-items: center; gap: 12px; margin-top: 12px; font-size: 13px; }
.viz-speed-bar { height: 10px; border-radius: 5px; }
.viz-tree { overflow-x: auto; }
.viz-tree-node {
background: #1e2030; border: 1px solid var(--viz-border);
border-radius: 12px; padding: 16px 20px;
text-align: center; margin: 0 auto;
max-width: 420px; position: relative;
transition: border-color .3s;
}
.viz-tree-node:hover { border-color: var(--viz-accent); }
.viz-tree-node.question { border-color: var(--viz-orange); }
.viz-tree-node.answer { border-color: var(--viz-green); background: rgba(0,210,160,.08); }
.viz-tree-lines { height: 24px; position: relative; }
.viz-tree-lines::before {
content: ''; position: absolute;
top: 0; left: 50%; width: 1px; height: 100%;
background: var(--viz-border);
}
.viz-tree-fork { display: flex; justify-content: center; gap: 24px; flex-wrap: wrap; }
.viz-tree-branch { text-align: center; min-width: 160px; position: relative; padding-top: 24px; }
.viz-tree-branch::before {
content: ''; position: absolute;
top: 0; left: 50%; width: 1px; height: 24px;
background: var(--viz-border);
}
.viz-tree-branch-label { font-size: 13px; color: var(--viz-dim); margin-bottom: 8px; }
.viz-table {
width: 100%; border-collapse: collapse;
background: var(--viz-card); border-radius: var(--viz-radius);
overflow: hidden; margin-bottom: 32px;
}
.viz-table th, .viz-table td {
padding: 14px 18px; text-align: left;
border-bottom: 1px solid var(--viz-border);
font-size: 14px;
}
.viz-table th {
background: #1e2030; color: var(--viz-dim);
font-weight: 600; font-size: 13px;
text-transform: uppercase; letter-spacing: .5px;
}
.viz-table tr:last-child td { border-bottom: none; }
.viz-table .highlight { color: var(--viz-green); font-weight: 600; }
.viz-fade-in { opacity: 0; transform: translateY(24px); transition: opacity .6s ease, transform .6s ease; }
.viz-fade-in.visible { opacity: 1; transform: translateY(0); }
.viz-footer { text-align: center; padding: 40px 24px 60px; color: var(--viz-dim); font-size: 13px; }
@media (max-width: 640px) {
.viz-section { padding: 80px 16px 40px; }
.viz-h1 { font-size: 26px; }
.viz-h2 { font-size: 20px; }
.viz-race-lanes, .viz-capacity-area, .viz-conveyor-lanes, .viz-pipe-pairs { flex-direction: column; }
.viz-nav { padding: 0 12px; }
.viz-tree-fork { gap: 12px; }
}
/* ============ page-specific ============ */
.hero {
padding-top: 140px; padding-bottom: 40px;
text-align: center; max-width: 720px; margin: 0 auto;
}
.hero .viz-h1 { font-size: 48px; margin-bottom: 16px; }
.hero .viz-subtitle { font-size: 18px; }
.timeline {
display: flex; flex-direction: column; gap: 20px; position: relative;
padding-left: 32px;
}
.timeline::before {
content: ''; position: absolute; left: 12px; top: 0; bottom: 0;
width: 2px; background: var(--viz-border);
}
.timeline-item {
position: relative; background: var(--viz-card);
border: 1px solid var(--viz-border); border-radius: var(--viz-radius);
padding: 20px 24px;
}
.timeline-item::before {
content: ''; position: absolute; left: -26px; top: 26px;
width: 12px; height: 12px; border-radius: 50%;
background: var(--viz-accent); box-shadow: 0 0 0 4px var(--viz-bg);
}
.timeline-year {
display: inline-block; font-size: 12px; color: var(--viz-accent);
font-weight: 700; letter-spacing: .5px; margin-bottom: 6px;
}
.timeline-item h3 { font-size: 16px; margin-bottom: 4px; }
.timeline-item p { font-size: 14px; color: var(--viz-dim); }
.loop-diagram {
display: flex; align-items: center; justify-content: center;
gap: 8px; flex-wrap: wrap; padding: 40px 0;
}
.loop-step {
padding: 14px 20px; border-radius: 12px;
background: var(--viz-card); border: 1px solid var(--viz-border);
font-size: 14px; min-width: 110px; text-align: center;
}
.loop-step.think { border-color: var(--viz-accent); }
.loop-step.act { border-color: var(--viz-orange); }
.loop-step.obs { border-color: var(--viz-green); }
.loop-arrow { color: var(--viz-dim); font-size: 20px; }
.loop-back {
width: 100%; text-align: center;
color: var(--viz-dim); font-size: 12px;
margin-top: 12px;
}
.quote {
border-left: 3px solid var(--viz-accent);
padding: 4px 16px; color: var(--viz-dim);
font-style: italic; margin: 20px 0; font-size: 14px;
}
/* Ancestry cards — 右边框"血脉"样式 */
.ancestry-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-top: 24px;
}
.ancestry-card {
background: var(--viz-card);
border: 1px solid var(--viz-border);
border-right: 4px solid var(--viz-accent);
border-radius: var(--viz-radius);
padding: 24px 28px;
position: relative;
transition: all .3s;
}
.ancestry-card:hover {
border-right-width: 6px;
transform: translateX(-2px);
}
.ancestry-card.c-accent { border-right-color: var(--viz-accent); }
.ancestry-card.c-orange { border-right-color: var(--viz-orange); }
.ancestry-card.c-green { border-right-color: var(--viz-green); }
.ancestry-card.c-blue { border-right-color: var(--viz-blue); }
.ancestry-card.c-red { border-right-color: var(--viz-red); }
.ancestry-era {
font-size: 11px; color: var(--viz-dim);
text-transform: uppercase; letter-spacing: 1px;
margin-bottom: 8px;
}
.ancestry-card h3 {
font-size: 17px; margin-bottom: 4px;
color: var(--viz-text);
}
.ancestry-who {
font-size: 12px; color: var(--viz-dim);
font-style: italic; margin-bottom: 12px;
}
.ancestry-card p {
font-size: 14px; color: var(--viz-dim);
line-height: 1.75; margin-bottom: 10px;
}
.ancestry-loop {
display: inline-block;
font-family: ui-monospace, "SF Mono", Consolas, monospace;
font-size: 12px;
background: rgba(108,99,255,0.08);
color: var(--viz-accent);
padding: 4px 10px;
border-radius: 6px;
margin-top: 6px;
}
.ancestry-card.c-orange .ancestry-loop { background: rgba(255,159,67,0.08); color: var(--viz-orange); }
.ancestry-card.c-green .ancestry-loop { background: rgba(0,210,160,0.08); color: var(--viz-green); }
.ancestry-card.c-blue .ancestry-loop { background: rgba(78,205,196,0.08); color: var(--viz-blue); }
.ancestry-card.c-red .ancestry-loop { background: rgba(255,107,107,0.08); color: var(--viz-red); }
/* 累加式 loop 展示 */
.loop-accum-wrap {
background: var(--viz-card);
border: 1px solid var(--viz-border);
border-radius: var(--viz-radius);
padding: 28px;
margin-bottom: 24px;
}
.loop-accum-controls {
display: flex; gap: 10px; flex-wrap: wrap;
margin-bottom: 20px; align-items: center;
}
.loop-accum-counter {
font-family: ui-monospace, "SF Mono", Consolas, monospace;
font-size: 14px; color: var(--viz-dim);
margin-left: auto;
}
.loop-accum-counter b { color: var(--viz-accent); font-size: 18px; }
.loop-accum-windows {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}
.loop-accum-win {
border: 1px solid var(--viz-border);
border-radius: 10px;
padding: 14px;
background: #1e2030;
position: relative;
}
.loop-accum-win h5 {
font-size: 13px; color: var(--viz-dim);
margin-bottom: 8px; font-weight: 600;
}
.loop-accum-bar-bg {
height: 24px; border-radius: 6px;
background: rgba(255,255,255,0.05);
overflow: hidden; position: relative;
}
.loop-accum-bar {
height: 100%; border-radius: 6px;
transition: width .4s ease, background .4s ease;
display: flex; align-items: center; justify-content: flex-end;
padding-right: 8px; color: #fff; font-size: 11px; font-weight: 700;
white-space: nowrap;
}
.loop-accum-status {
margin-top: 8px; font-size: 12px;
display: flex; justify-content: space-between;
}
.loop-accum-status .good { color: var(--viz-green); }
.loop-accum-status .warn { color: var(--viz-orange); }
.loop-accum-status .danger { color: var(--viz-red); }
/* 工具粒度对比 */
.tool-compare-wrap {
background: var(--viz-card);
border: 1px solid var(--viz-border);
border-radius: var(--viz-radius);
padding: 28px;
margin-bottom: 24px;
}
.tool-task-banner {
background: #1e2030;
border: 1px dashed var(--viz-border);
border-radius: 10px;
padding: 14px 18px;
margin-bottom: 20px;
font-size: 14px;
color: var(--viz-text);
}
.tool-task-banner b { color: var(--viz-accent); }
.tool-lanes {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 20px;
margin-bottom: 16px;
}
.tool-lane {
border: 1px solid var(--viz-border);
border-radius: 12px;
padding: 20px;
background: #1e2030;
}
.tool-lane h4 {
font-size: 15px; margin-bottom: 4px;
}
.tool-lane .lane-sub {
font-size: 12px; color: var(--viz-dim);
margin-bottom: 14px;
}
.tool-steps {
display: flex; flex-direction: column; gap: 6px;
margin-bottom: 14px;
min-height: 180px;
}
.tool-step {
display: flex; align-items: center; gap: 10px;
padding: 8px 12px;
background: rgba(255,255,255,0.03);
border-radius: 6px;
font-family: ui-monospace, "SF Mono", Consolas, monospace;
font-size: 12px;
opacity: 0; transform: translateX(-10px);
transition: all .3s ease;
}
.tool-step.visible { opacity: 1; transform: translateX(0); }
.tool-step .tool-step-num {
width: 22px; height: 22px; border-radius: 50%;
background: var(--viz-border); color: var(--viz-dim);
display: flex; align-items: center; justify-content: center;
font-size: 11px; font-weight: 700; flex-shrink: 0;
}
.tool-step.done .tool-step-num {
background: var(--viz-green); color: #fff;
}
.tool-step .tool-step-cmd { color: var(--viz-text); }
.tool-lane-summary {
font-size: 13px; padding-top: 10px;
border-top: 1px solid var(--viz-border);
color: var(--viz-dim);
}
.tool-lane-summary b { font-size: 18px; }
.tool-lane.fine b { color: var(--viz-red); }
.tool-lane.coarse b { color: var(--viz-green); }
/* 学习路径 —— 课程大纲样式 */
.study-path {
display: flex; flex-direction: column; gap: 20px;
margin-top: 24px;
}
.study-step {
display: grid;
grid-template-columns: 88px 1fr;
gap: 28px;
background: var(--viz-card);
border: 1px solid var(--viz-border);
border-radius: var(--viz-radius);
padding: 28px;
transition: all .3s;
position: relative;
}
.study-step:hover {
border-color: var(--viz-accent);
transform: translateY(-2px);
}
.study-num {
font-size: 56px; font-weight: 800;
color: var(--viz-accent);
line-height: 1;
font-family: ui-monospace, "SF Mono", Consolas, monospace;
opacity: 0.35;
}
.study-head { margin-bottom: 14px; }
.study-head h3 {
font-size: 19px; margin-bottom: 6px;
color: var(--viz-text);
}
.study-head .study-goal {
font-size: 13px; color: var(--viz-dim);
margin-bottom: 10px; font-style: italic;
}
.study-meta {
display: flex; gap: 8px; flex-wrap: wrap;
}
.study-meta span {
padding: 3px 10px; border-radius: 4px;
background: rgba(108,99,255,0.12); color: var(--viz-accent);
font-size: 11px; font-weight: 600; letter-spacing: .3px;
}
.study-meta .time-tag {
background: rgba(255,159,67,0.12); color: var(--viz-orange);
}
.study-sections {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 14px;
margin-top: 16px;
}
.study-sec {
background: #1e2030;
border-radius: 10px;
padding: 14px 16px;
border-left: 3px solid var(--viz-border);
}
.study-sec.read { border-left-color: var(--viz-blue); }
.study-sec.do { border-left-color: var(--viz-orange); }
.study-sec.out { border-left-color: var(--viz-green); }
.study-sec-label {
font-size: 10px; font-weight: 700;
letter-spacing: 1.2px; color: var(--viz-dim);
margin-bottom: 10px; text-transform: uppercase;
display: flex; align-items: center; gap: 6px;
}
.study-sec.read .study-sec-label { color: var(--viz-blue); }
.study-sec.do .study-sec-label { color: var(--viz-orange); }
.study-sec.out .study-sec-label { color: var(--viz-green); }
.study-sec ul { list-style: none; padding: 0; margin: 0; }
.study-sec li {
font-size: 13px; color: var(--viz-text);
padding: 4px 0; line-height: 1.55;
position: relative; padding-left: 16px;
}
.study-sec.read li::before {
content: "📖"; position: absolute; left: 0; top: 4px; font-size: 10px;
}
.study-sec.do li::before {
content: "🔨"; position: absolute; left: 0; top: 4px; font-size: 10px;
}
.study-sec.out li::before {
content: "✓"; position: absolute; left: 0; color: var(--viz-green);
font-weight: 700;
}
.study-sec li code {
background: rgba(255,255,255,0.06);
padding: 1px 6px; border-radius: 4px;
font-size: 11px; color: var(--viz-accent);
}
.study-final {
margin-top: 24px;
background: linear-gradient(135deg, rgba(108,99,255,0.08), rgba(0,210,160,0.04));
border: 1px solid var(--viz-border);
border-radius: var(--viz-radius);
padding: 24px 28px;
font-size: 14px; color: var(--viz-text); line-height: 1.85;
}
.study-final b { color: var(--viz-accent); }
@media (max-width: 640px) {
.study-step { grid-template-columns: 1fr; gap: 12px; padding: 20px; }
.study-num { font-size: 36px; }
}
</style>
</head>
<body class="viz-body">
<nav class="viz-nav" id="nav"></nav>
<!-- Hero -->
<section class="viz-section hero" id="intro">
<h1 class="viz-h1">Agent Loop <span>深度理解</span></h1>
<p class="viz-subtitle">20 行代码的循环,为什么是 LLM 时代的发动机?</p>
<div class="loop-diagram">
<div class="loop-step think">🧠 Think</div>
<div class="loop-arrow">→</div>
<div class="loop-step act">🔧 Act</div>
<div class="loop-arrow">→</div>
<div class="loop-step obs">👁 Observe</div>
<div class="loop-back">↑ 循环,直到目标达成 ↑</div>
</div>
</section>
<!-- 为什么是 loop -->
<section class="viz-section" id="why">
<h2 class="viz-h2">为什么必须是 loop?</h2>
<p class="viz-desc">LLM 本身是无状态的一次性函数,而真实任务是"边做边看"的过程。loop 是粘合这两者的唯一方式 —— 五个底层原因:</p>
<div id="why-cards"></div>
</section>
<!-- 历史演化 -->
<section class="viz-section" id="history">
<h2 class="viz-h2">loop 是被谁"发现"的?</h2>
<p class="viz-desc">没有某一个人发明。这是一条多源汇流的演化线 —— 从机器人到认知科学,最后在 2022 年的 ReAct 论文定型。</p>
<div class="timeline">
<div class="timeline-item">
<div class="timeline-year">1960s — 1990s · 远古思想源</div>
<h3>Sense → Plan → Act 的几十年铺垫</h3>
<p>从 Shakey 机器人到强化学习,"用循环解决序列决策"在 AI 界早已是常识。下一节会详细讲这段血脉。</p>
</div>
<div class="timeline-item">
<div class="timeline-year">2021.12</div>
<h3>WebGPT (OpenAI)</h3>
<p>最早让 LLM 在浏览器里循环执行动作,拉开 LLM agent 的序幕。</p>
</div>
<div class="timeline-item">
<div class="timeline-year">2022.05</div>
<h3>MRKL Systems (AI21)</h3>
<p>提出 LLM + 外部模块路由的范式,Karpas 等人给出概念框架。</p>
</div>
<div class="timeline-item">
<div class="timeline-year">2022.10 ⭐ 里程碑</div>
<h3>ReAct — Shunyu Yao 等 (Princeton + Google)</h3>
<p>第一次清晰提出 Thought → Action → Observation 交替循环。这被公认为现代 agent loop 的教科书形态。</p>
</div>
<div class="timeline-item">
<div class="timeline-year">2022.10 — 2023.03</div>
<h3>工程化爆发</h3>
<p>LangChain(Harrison Chase)把 ReAct 变成人人可调;AutoGPT(Toran Richards)让大众第一次看到全自动 loop;BabyAGI(Yohei Nakajima)把 loop 拆成任务队列。</p>
</div>
<div class="timeline-item">
<div class="timeline-year">2024.12 — 至今</div>
<h3>Harness 沉淀</h3>
<p>Anthropic 《Building Effective Agents》区分 workflow vs agent;Claude Code、Cursor、aider 把 loop 做成基础设施。loop 从论文走进生产。</p>
</div>
</div>
</section>
<!-- 远古思想源详解 -->
<section class="viz-section" id="ancestry">
<h2 class="viz-h2">远古思想源:loop 的六条血脉</h2>
<p class="viz-desc">
今天的 agent loop 不是 2022 年凭空发明的。从 1960 年代的机器人到 1990 年代的强化学习,"感知→规划→行动"这个结构被反复验证过六次 —— ReAct 只是把它搬到了 LLM 上。理解这六条源流,才能看清 loop 的本质不是"循环调用",而是<b style="color:var(--viz-accent);">带反馈的决策过程</b>。
</p>
<div class="ancestry-grid">
<div class="ancestry-card c-accent">
<div class="ancestry-era">1966 — 1972 · Stanford Research Institute</div>
<h3>Shakey 机器人 · 世界第一台"思考型"移动机器人</h3>
<div class="ancestry-who">Nils Nilsson, Charles Rosen 等</div>
<p>拿着摄像头在走廊里推箱子,第一次把"感知-建模-规划-执行"做成可运行系统。它用的 <b>STRIPS 规划器</b>(前置条件 + 动作 + 后置效果)至今仍是所有 AI 规划的语法基础。</p>
<p style="margin-top:8px;">Shakey 一次完整任务内部就是一个大 loop:拍照 → 更新世界模型 → 求解 STRIPS → 执行动作 → 再拍照。</p>
<span class="ancestry-loop">perceive → model → plan → act → perceive ...</span>
</div>
<div class="ancestry-card c-orange">
<div class="ancestry-era">1970s · 经典 AI 范式</div>
<h3>Sense-Plan-Act (SPA) 三段论</h3>
<div class="ancestry-who">经典人工智能学派的通用骨架</div>
<p>把智能体拆成三个独立阶段:<b>Sense</b>(传感器读入)→ <b>Plan</b>(符号推理生成动作序列)→ <b>Act</b>(执行器输出)。每一轮结束后,新感知反哺模型,下一轮重新规划。</p>
<p style="margin-top:8px;">这是现代 agent loop 的直系祖先。ReAct 的 Thought/Action/Observation 本质上就是 Plan/Act/Sense 换了个马甲。</p>
<span class="ancestry-loop">sense → plan → act → (loop)</span>
</div>
<div class="ancestry-card c-green">
<div class="ancestry-era">1986 · MIT CSAIL</div>
<h3>Subsumption Architecture · 反 SPA 的叛逆</h3>
<div class="ancestry-who">Rodney Brooks (iRobot 创始人)</div>
<p>Brooks 的著名论文 <i>"Intelligence Without Reason"</i> 抨击 SPA 太慢太脆 —— 机器人还没想完,老鼠已经跑了。他提出<b>反应式分层架构</b>:多个感知-动作 loop 并行运行,底层反射快,高层规划慢,高层压制低层。</p>
<p style="margin-top:8px;">这对今天多 agent、subagent、并行 loop 的架构思想影响深远。</p>
<span class="ancestry-loop">多个 sense→act loop 并行 · 分层压制</span>
</div>
<div class="ancestry-card c-blue">
<div class="ancestry-era">1983 — 至今 · CMU</div>
<h3>SOAR · 统一认知架构</h3>
<div class="ancestry-who">Allen Newell, John Laird, Paul Rosenbloom</div>
<p>图灵奖得主 Newell 的毕生心血:把所有认知活动统一为一个 <b>decide cycle</b>(决策周期)。每个 cycle 包含:阐述状态 → 提议算子 → 评估 → 选择 → 应用。目标栈遇到僵局就自动生成子目标 —— <b>这就是 subagent 的原型</b>。</p>
<span class="ancestry-loop">elaborate → propose → decide → apply → (impasse → subgoal)</span>
</div>
<div class="ancestry-card c-red">
<div class="ancestry-era">1993 — 至今 · CMU</div>
<h3>ACT-R · 产生式规则的循环触发</h3>
<div class="ancestry-who">John R. Anderson</div>
<p>认知心理学建模的标杆。核心是<b>产生式规则</b>(IF pattern THEN action)不断匹配工作记忆并触发。每一次触发就是一轮 loop,触发结果更新工作记忆,引发下一轮匹配。</p>
<p style="margin-top:8px;">ACT-R 明确区分<b>程序性记忆</b>(规则)与<b>陈述性记忆</b>(事实)—— 这正是今天 agent 的"工具" vs "上下文"。</p>
<span class="ancestry-loop">match → select → fire → update memory → (loop)</span>
</div>
<div class="ancestry-card c-accent">
<div class="ancestry-era">1998 · 强化学习奠基作</div>
<h3>Agent-Environment Loop · loop 的数学定义</h3>
<div class="ancestry-who">Richard Sutton & Andrew Barto</div>
<p>《Reinforcement Learning: An Introduction》把 agent 抽象为数学对象:<br>
每个 timestep t,agent 观察状态 <code>sₜ</code>,选择动作 <code>aₜ</code>,环境反馈奖励 <code>rₜ₊₁</code> 和新状态 <code>sₜ₊₁</code>。目标是最大化累积奖励。</p>
<p style="margin-top:8px;">这是今天所有 agent loop 的<b>数学骨架</b>。当你把 LLM 的 "Thought/Action/Observation" 映射到 "policy/action/reward",它们其实是同一个东西。</p>
<span class="ancestry-loop">sₜ → π(aₜ|sₜ) → env → rₜ₊₁, sₜ₊₁ → (loop)</span>
</div>
</div>
<div class="quote" style="margin-top: 32px;">
Yao 等人 2022 写 ReAct 的时候,并不是"发明"了一个新的循环。他们只是把一个已经跑了 60 年的结构,第一次用自然语言 prompt 表达出来,让 LLM 也能加入这个古老的游戏。
</div>
</section>
<!-- 控制流 -->
<section class="viz-section" id="flow">
<h2 class="viz-h2">控制流:loop 里流动的是什么?</h2>
<p class="viz-desc">每轮 loop 把 <code>assistant turn + tool_result</code> 追加进对话历史,再整个喂回模型。状态 = messages 数组,不是变量。</p>
<div class="viz-demo">
<div class="viz-demo-header"><h3>消息流:越转越长的对话历史</h3></div>
<div id="flow-conveyor"></div>
</div>
<div class="quote">模型只负责"想下一步",不负责"把下一步跑起来"。harness 做调度、LLM 做决策。</div>
</section>
<!-- 上下文工程 -->
<section class="viz-section" id="context">
<h2 class="viz-h2">上下文工程:loop 每转一圈就变贵一次</h2>
<p class="viz-desc">
关键不是"窗口多大",而是<b style="color:var(--viz-accent);">每一轮 loop 都会把上一轮的 tool_result 追加进来,context 单调递增</b>。一次调用的成本 = 当前累积 token × 单价。所以 loop 跑得越深,单步越贵、模型越容易开始"遗忘目标"。
</p>
<div class="loop-accum-wrap">
<div class="loop-accum-controls">
<button class="viz-btn viz-btn-primary" id="loop-step-btn">▶ 再跑一轮 loop</button>
<button class="viz-btn viz-btn-outline" id="loop-reset-btn">重置</button>
<div class="loop-accum-counter">已跑 <b id="loop-round">0</b> 轮 · 累积 <b id="loop-tokens">0</b> tokens</div>
</div>
<div class="loop-accum-windows" id="loop-windows"></div>
</div>
<p class="viz-hint">每点一次按钮 = loop 再转一轮:prompt + assistant + tool_result 追加到历史。看四种模型分别在第几轮撑爆。</p>
</section>
<!-- 工具粒度 -->
<section class="viz-section" id="tools">
<h2 class="viz-h2">工具设计:给什么工具 ≈ 决定 loop 有多长</h2>
<p class="viz-desc">
"工具粒度决定 loop 长度" 想说的是:<b style="color:var(--viz-accent);">同一个任务能不能一步到位,完全取决于 harness 给 LLM 暴露了什么 API</b>。工具太碎,LLM 要跑十几轮拼装;工具太粗,LLM 又容易失控。这是 harness 设计最重要的 API 决策,直接决定了成本、延迟、可靠性。
</p>
<div class="tool-compare-wrap">
<div class="tool-task-banner">
任务:<b>"把 config.json 里的 port 从 3000 改成 8080"</b> — 两套工具 API,loop 长度相差 5 倍。
</div>
<div class="tool-lanes">
<div class="tool-lane fine" id="tool-lane-fine">
<h4>🧩 细粒度工具集</h4>
<div class="lane-sub">list_dir · read_file · edit_text · write_file · run_test</div>
<div class="tool-steps" id="fine-steps"></div>
<div class="tool-lane-summary">共 <b>5</b> 轮 loop · 每轮都带全部历史回模型</div>
</div>
<div class="tool-lane coarse" id="tool-lane-coarse">
<h4>🔨 粗粒度工具</h4>
<div class="lane-sub">run_bash (任意 shell 命令)</div>
<div class="tool-steps" id="coarse-steps"></div>
<div class="tool-lane-summary">共 <b>1</b> 轮 loop · 一条命令搞定</div>
</div>
</div>
<button class="viz-btn viz-btn-primary" id="tool-play-btn">▶ 播放对比</button>
</div>
<div class="quote">
粗工具不是总赢:<b>run_bash</b> 可以一步改文件,也可以一步 <code>rm -rf /</code>。粒度 = 效率 vs 安全的平衡点。这就是 Claude Code 为什么默认给细粒度工具 + 可选 bash。
</div>
</section>
<!-- 子 agent 与管道 -->
<section class="viz-section" id="subagent">
<h2 class="viz-h2">子 agent:嵌套 loop 的通信</h2>
<p class="viz-desc">主 loop 调子 loop,是隔离 context 污染、实现并行的关键模式。Claude Code 的 Agent tool 就是这么做的。</p>
<div class="viz-demo">
<div id="subagent-pipe"></div>
</div>
</section>
<!-- 失败模式 -->
<section class="viz-section" id="failure">
<h2 class="viz-h2">失败模式:loop 会在哪里死?</h2>
<p class="viz-desc">必须亲手观察过这些病症,才算真正懂 loop。</p>
<div id="failure-cards"></div>
</section>
<!-- 决策树:何时用 loop -->
<section class="viz-section" id="decision">
<h2 class="viz-h2">何时该用 agent loop?</h2>
<p class="viz-desc">不是所有任务都适合 loop。Anthropic 的建议:能用预编排 workflow 解决的,不要动 agent。</p>
<div id="decision-tree" class="viz-demo"></div>
</section>
<!-- 对比表 -->
<section class="viz-section" id="compare">
<h2 class="viz-h2">Workflow vs Agent:一眼看清差异</h2>
<p class="viz-desc">两者都用 LLM,但控制权归属完全不同。选错模式 = 要么束手束脚、要么失控烧钱。</p>
<div id="compare-table"></div>
</section>
<!-- 学习路线 -->
<section class="viz-section" id="roadmap">
<h2 class="viz-h2">学习路线:6 步打透 loop(约 3 周)</h2>
<p class="viz-desc">
"只读不动"学不会 agent loop。每一步都给了<b style="color:var(--viz-blue);">要读的材料</b>、<b style="color:var(--viz-orange);">要动手做的事</b>、<b style="color:var(--viz-green);">验收产出</b>。按顺序走,每步产出叠加到下一步,到 Step 6 你手里就有一个能跑 SWE-bench 的完整 agent。
</p>
<div class="study-path">
<!-- Step 1 -->
<div class="study-step">
<div class="study-num">01</div>
<div class="study-body">
<div class="study-head">
<h3>入门 · 亲手实现 ReAct</h3>
<div class="study-goal">目标:从 0 写出一个能 Think→Act→Observe 的 loop,体会"状态 = messages 数组"</div>
<div class="study-meta">
<span>难度 · 初</span>
<span class="time-tag">⏱ 1–2 天</span>
</div>
</div>
<div class="study-sections">
<div class="study-sec read">
<div class="study-sec-label">读</div>
<ul>
<li>ReAct 原论文 <code>arxiv 2210.03629</code>(重点 §3-4)</li>
<li>Anthropic Cookbook · Tool Use 章节</li>
<li>LangChain 官方 ReAct agent quickstart</li>
</ul>
</div>
<div class="study-sec do">
<div class="study-sec-label">做</div>
<ul>
<li>用 Python + Anthropic SDK 写 <code>~60 行</code>的 ReAct loop</li>
<li>提供两个假工具:<code>calculator</code>、<code>search</code>(mock 数据即可)</li>
<li>让它答:"《三体》作者出生那年中国 GDP 多少"</li>
</ul>
</div>
<div class="study-sec out">
<div class="study-sec-label">产出</div>
<ul>
<li>一个 <code>react_loop.py</code>,能看到 Thought/Action/Observation 交替</li>
<li>能打印完整 messages 历史</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Step 2 -->
<div class="study-step">
<div class="study-num">02</div>
<div class="study-body">
<div class="study-head">
<h3>工程 · 解剖真实 harness</h3>
<div class="study-goal">目标:看懂从 LLM 输出到工具执行到 result 回填的完整链路</div>
<div class="study-meta">
<span>难度 · 中</span>
<span class="time-tag">⏱ 3–5 天</span>
</div>
</div>
<div class="study-sections">
<div class="study-sec read">
<div class="study-sec-label">读</div>
<ul>
<li>Anthropic《Building Effective Agents》2024.12</li>
<li>MCP 官方规范 <code>modelcontextprotocol.io</code></li>
<li>Simon Willison 关于 agentic coding 的系列博客</li>
</ul>
</div>
<div class="study-sec do">
<div class="study-sec-label">做</div>
<ul>
<li>clone <code>aider</code> 或 <code>sweep</code> 任一开源 harness,本地跑通</li>
<li>在主循环打断点,追一次 tool call 的完整生命周期</li>
<li>自己实现一个最小 MCP server(暴露 1 个读文件工具)</li>
</ul>
</div>
<div class="study-sec out">
<div class="study-sec-label">产出</div>
<ul>
<li>一张主循环伪代码图(500 字以内)</li>
<li>可用的 MCP server 能被 Claude Code 调用</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Step 3 -->
<div class="study-step">
<div class="study-num">03</div>
<div class="study-body">
<div class="study-head">
<h3>上下文 · 对抗 context rot</h3>
<div class="study-goal">目标:亲自测出"loop 越长越笨",并用工程手段救回来</div>
<div class="study-meta">
<span>难度 · 中</span>
<span class="time-tag">⏱ 2–3 天</span>
</div>
</div>
<div class="study-sections">
<div class="study-sec read">
<div class="study-sec-label">读</div>
<ul>
<li>Chroma Research《Context Rot》实验报告</li>
<li>MemGPT / Letta 论文 <code>arxiv 2310.08560</code></li>
<li>Anthropic Prompt Caching 文档(5 分钟 TTL)</li>
</ul>
</div>
<div class="study-sec do">
<div class="study-sec-label">做</div>
<ul>
<li>给 Step 1 的 loop 加一个 summarization:历史 > 5 轮就压缩前文</li>
<li>开启 prompt caching,测 TTFB 和成本差异</li>
<li>做 A/B:无压缩 vs 有压缩 跑 20 个多步任务</li>
</ul>
</div>
<div class="study-sec out">
<div class="study-sec-label">产出</div>
<ul>
<li>一张 token × 成功率 对比图</li>
<li>一段 200 字结论:什么时候该压、什么时候该 off-load</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Step 4 -->
<div class="study-step">
<div class="study-num">04</div>
<div class="study-body">
<div class="study-head">
<h3>规划 · 从 reactive 升级到 reflective</h3>
<div class="study-goal">目标:让 agent 从失败中学习,而不是反复踩同一个坑</div>
<div class="study-meta">
<span>难度 · 中高</span>
<span class="time-tag">⏱ 2–3 天</span>
</div>
</div>
<div class="study-sections">
<div class="study-sec read">
<div class="study-sec-label">读</div>
<ul>
<li>Reflexion <code>arxiv 2303.11366</code></li>
<li>Tree of Thoughts <code>arxiv 2305.10601</code></li>
<li>Voyager (Minecraft agent) <code>arxiv 2305.16291</code></li>
</ul>
</div>
<div class="study-sec do">
<div class="study-sec-label">做</div>
<ul>
<li>在 loop 里加"反思步":失败后让模型写一条 lesson,存到 memory</li>
<li>下一次开局把 memory 里相关 lesson 拼到 system prompt</li>
<li>观察同样任务第 2 次尝试的成功率提升</li>
</ul>
</div>
<div class="study-sec out">
<div class="study-sec-label">产出</div>
<ul>
<li>一个能自我修正的 agent demo</li>
<li>一张"反思前/后"成功率对比表</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Step 5 -->
<div class="study-step">
<div class="study-num">05</div>
<div class="study-body">
<div class="study-head">
<h3>安全 · 给自己的 agent 红队攻击</h3>
<div class="study-goal">目标:亲眼看到 prompt injection 怎么让 loop 失控</div>
<div class="study-meta">
<span>难度 · 中</span>
<span class="time-tag">⏱ 2–3 天</span>
</div>
</div>
<div class="study-sections">
<div class="study-sec read">
<div class="study-sec-label">读</div>
<ul>
<li>Simon Willison · Prompt Injection 系列(按时间顺序)</li>
<li>"Lethal Trifecta" 文章</li>
<li>Anthropic Responsible Scaling Policy</li>
</ul>
</div>
<div class="study-sec do">
<div class="study-sec-label">做</div>
<ul>
<li>设计 3 个恶意工具结果:泄密型、提权型、外发型</li>
<li>跑你自己 Step 1-4 的 agent,看它在哪种 payload 下上当</li>
<li>加一层 output sanitizer + 权限白名单,重跑</li>
</ul>
</div>
<div class="study-sec out">
<div class="study-sec-label">产出</div>
<ul>
<li>一份红队报告:10 个 payload × 防御前后对比</li>
<li>知道 lethal trifecta 在你场景里具体怎么触发</li>
</ul>
</div>