Lompat ke konten
dokumentasi.id
Commit 51864a8
v1
Star1,9 rb

Kamu membaca versi lama. Halaman ini hanya bisa dibaca.

7

Sistem Multi-Agen

Guardian tidak menjalankan satu model besar, melainkan empat agen dengan peran sempit yang berbagi satu objek PentestMemory. WorkflowEngine membuat keempat agen itu sekali di awal sesi dan memberi mereka satu GeminiClient serta satu memory yang sama core/workflow.py:41-50. Semua agen mewarisi BaseAgent, yang mewajibkan execute dan menyediakan dua mode penalaran core/agent.py:16-36.

Halaman ini membahas lapisan agen dan memori. Orkestrasi langkah workflow, termasuk pemilihan type dan agent per langkah, ada di Engine Workflow DSL v2. Pemilihan tool beserta registry dan kelas risiko ada di Integrasi Tool dan Pemilihan Tool.

BaseAgent dan dua mode penalaran

think adalah satu ronde panggilan ke gemini.generate_with_usage, lalu hasilnya dicatat lewat _record_usage_and_step dan dikembalikan apa adanya core/agent.py:40-56. think_deeply menjalankan hingga max_rounds ronde: ronde pertama menjawab, ronde berikutnya mengkritik jawaban sebelumnya dan meminta perbaikan core/agent.py:62-91. Jika judge_model tersedia, satu provider terpisah membaca seluruh transkrip dan memilih ronde terbaik; jawaban yang dipilih menggantikan response, sementara ronde yang kalah tetap disimpan di thinking_chain untuk audit, dan total_tokens ikut menghitung panggilan judge core/agent.py:142-172.

Setiap panggilan menulis empat jejak sekaligus lewat _record_usage_and_step: satu TokenUsage ke token_ledger, satu ThinkingStep ke thinking_chain, satu entri ai_decisions, dan satu baris audit log berisi potongan prompt, token, biaya, model, serta nomor ronde core/agent.py:267-301.

⚠️ think dan think_deeply menagih setiap panggilan model. think_deeply dengan max_rounds besar plus judge pass berarti biaya berlipat pada satu keputusan; angka total_cost_usd baru terlihat setelah semua ronde selesai.

Perpindahan peran dari rencana sampai temuan tersimpan

Diagram berikut menunjukkan satu putaran kerja penuh. Perhatikan bahwa PentestMemory menjadi satu-satunya penghubung antar agen: PlannerAgent dan ToolAgent tidak saling memanggil, keduanya membaca dan menulis ke memori yang sama.

sequenceDiagram
  participant P as PlannerAgent
  participant T as ToolAgent
  participant A as AnalystAgent
  participant D as DebateTriage
  participant R as ReporterAgent
  participant M as PentestMemory
  P->>M: get_context_for_ai
  P->>P: decide_next_action
  P->>M: add_ai_decision + add_thinking_step
  T->>M: baca tool_executions sebelumnya
  T->>T: execute objective dan target
  A->>A: interpret_output tool dan output
  A->>M: add_finding
  D->>M: baca findings dengan fp prob MEDIUM
  D->>D: triage red lalu blue lalu judge
  D->>M: tulis ulang severity dan false_positive
  R->>M: get_findings_summary
  R->>R: execute format markdown html json
%% fig: Siklus satu putaran kerja empat agen
%% desc: PlannerAgent memutuskan langkah, ToolAgent memilih tool, AnalystAgent menyimpan temuan, triase menyesuaikan temuan, lalu ReporterAgent membaca hasil akhir dari PentestMemory yang sama.
Fig. 1: Siklus satu putaran kerja empat agenPlannerAgent memutuskan langkah, ToolAgent memilih tool, AnalystAgent menyimpan temuan, triase menyesuaikan temuan, lalu ReporterAgent membaca hasil akhir dari PentestMemory yang sama.

Empat agen inti

AgenKelas dan metode masukMasukan utamaKeluaran
PerencanaPlannerAgent.decide_next_action dan analyze_resultsmemory.get_context_for_ai, ringkasan finding, aksi per fasenext_action, parameters, expected_outcome, reasoning
Pemilih toolToolAgent.execute dan configure_toolobjective, target, tipe target, safe_mode, rate_limit, tool_timeouttool, arguments, expected_output, reasoning
AnalisAnalystAgent.interpret_output, correlate_findings, check_false_positiveoutput mentah tool, temuan sebelumnya, teknologi terdeteksidaftar Finding, summary, reasoning
PelaporReporterAgent.executeget_findings_summary, temuan per severity, thinking_chainkonten laporan markdown, html, atau json

PlannerAgent menyusun prompt dari konteks sesi, membungkus ringkasan finding, attack surface, dan teknologi dengan wrap_untrusted karena berasal dari output tool, lalu memanggil think dan mem-parse hasilnya core/planner.py:29-69. Daftar aksi yang boleh dipilih dibatasi per fase, misalnya reconnaissance hanya menawarkan subdomain_enumeration, dns_enumeration, technology_detection, dan port_scanning core/planner.py:113-144.

ToolAgent mencoba ranker offline lebih dulu. Jika ranker yakin, agen langsung mengembalikan pilihan tanpa memanggil model sama sekali core/tool_agent.py:239-263. Jika ranker abstain, agen menyusun prompt pemilihan tool dari registry yang terpasang dan batasan konfigurasi, lalu memanggil think core/tool_agent.py:283-309. Instans tool diimpor secara lazy dari spesifikasi module:Class core/tool_agent.py:157-162, dan registry digabung dengan plugin yang mendaftar di entry point guardian.tools; nama in-tree menang atas plugin core/tool_agent.py:169-205.

AnalystAgent.interpret_output memotong output yang melebihi 5000 karakter, menyertakan sepuluh temuan terakhir dan teknologi terdeteksi, membungkus output tool sebagai data tak terpercaya, lalu memanggil think core/analyst_agent.py:58-104. Setiap Finding hasil parsing beserta execution_id dan potongan output mentah langsung ditambahkan ke memori core/analyst_agent.py:106-117. Perilaku ini dituntun system prompt yang menetapkan peran analis sebagai gerbang mutu: temuan wajib bersandar pada kutipan bukti, severity mengikuti CVSS 3.1, dan heuristik false positive harus diterapkan ai/prompt_templates/analyst.py:11-19.

ReporterAgent.execute membangun empat bagian berurutan, yaitu executive summary, technical findings, remediation plan, dan AI trace, lalu merakitnya sesuai format; format di luar tiga pilihan yang dikenal memunculkan ValueError core/reporter_agent.py:27-76. Rating risiko keseluruhan bukan hasil model, melainkan turunan hitungan temuan: ada critical maka CRITICAL, lebih dari tiga high maka HIGH, ada high atau lebih dari lima medium maka MEDIUM, sisanya LOW core/reporter_agent.py:78-117. Bagian AI trace dibangun dari ai_decisions dan thinking_chain core/reporter_agent.py:148-169.

PentestMemory sebagai satu-satunya state

PentestMemory diinisialisasi dengan target dan session_id, lalu menyiapkan fase, completed_actions, tiga penyimpanan inti (findings, tool_executions, ai_decisions), serta token_ledger dan thinking_chain core/memory.py:85-121.

Kelompok stateFieldPenulis
Temuanfindings berisi Findingadd_finding
Eksekusi tooltool_executions berisi ToolExecutionadd_tool_execution
Keputusanai_decisionsadd_ai_decision
Biayatoken_ledger berisi TokenUsageadd_token_usage
Penalaranthinking_chain berisi ThinkingStepadd_thinking_step
Kontekscontext, threat_model, attack_surfaceupdate_context, set_threat_model, add_attack_surface_entry

Mutator untuk ledger, rantai penalaran, threat model, dan attack surface tercantum lengkap di core/memory.py:144-159. get_token_summary menjumlahkan token dan biaya, lalu mengelompokkannya per provider, per model, dan per agent dengan menghitung jumlah panggilan core/memory.py:163-202. get_context_for_ai merakit blok teks yang dibaca semua agen: target, fase, aksi selesai, ringkasan finding per severity, aset yang ditemukan, attack surface, potongan threat model maksimum 600 karakter, tiga langkah penalaran terakhir, dan pemakaian token sejauh ini core/memory.py:257-325. save_state menulis seluruh state termasuk token_summary ke JSON, sehingga sesi bisa dilanjutkan core/memory.py:329-350.

Schema Pydantic dan jalur penolakan

Schema di core/schemas.py menggantikan parser string yang rapuh: agen yang menghasilkan keluaran terstruktur harus lolos validasi, dan yang tidak sesuai ditolak, bukan dipaksa cocok core/schemas.py:31-38.

ModelDipakai olehAturan yang menolak keluaran
PlannerDecisionPlannerAgent._parse_decisionnext_action wajib ada, maksimum 64 karakter, dan harus termasuk KNOWN_ACTIONS
ToolSelectionToolAgent.executetool harus ada di TOOL_REGISTRY
FindingModelAnalystAgent.interpret_outputseverity salah satu dari lima nilai, cvss_score antara 0.0 dan 10.0
AnalysisResulthasil agregat satu eksekusi toolfindings, summary, missed_checks
FalsePositiveVerdictevaluasi false positiveconfidence 0 sampai 100, recommendation salah satu dari KEEP, DISCARD, VERIFY_MANUALLY

PlannerDecision memvalidasi next_action lewat validator yang menurunkan huruf dan mencocokkannya dengan whitelist core/schemas.py:52-72, sedangkan whitelist aksi sendiri didefinisikan sekali di core/schemas.py:31-38. ToolSelection mengambil nama tool yang sah langsung dari TOOL_REGISTRY core/schemas.py:75-92. FindingModel membatasi cvss_score pada rentang 0.0 sampai 10.0 dan menormalkan severity ke huruf kecil core/schemas.py:95-119. parse_or_none mengembalikan objek tervalidasi atau None tanpa melempar exception, sehingga pemanggil bisa mencoba ulang dengan prompt lebih ketat core/schemas.py:148-165. schema_for_prompt membuang kunci title agar schema bisa dipakai sebagai response_format, response_schema, atau input_schema core/schemas.py:168-176.

PlannerAgent._parse_decision mencoba JSON ketat lebih dulu; bila gagal, ia jatuh ke ekstraksi header NEXT_ACTION:, PARAMETERS:, dan EXPECTED_OUTCOME: dengan pembersihan karakter kontrol dan pencocokan whitelist core/planner.py:146-202.

Triase debat: tiga peran untuk temuan ambigu

Triase debat hanya menyentuh temuan yang ditandai false_positive_probability bernilai MEDIUM. Temuan yang sudah yakin, yaitu LOW dianggap nyata dan HIGH dianggap false positive, melewati debat dan mengembalikan DebateVerdict dengan triggered=False core/agents/debate_triage.py:91-110.

graph LR
  F["Finding dari AnalystAgent"] --> X["_extract_fp_probability"]
  X -->|LOW| R1["REAL, triggered=false"]
  X -->|HIGH| R2["FALSE_POSITIVE, triggered=false"]
  X -->|MEDIUM| RA["_RedAdvocate.think"]
  RA --> BA["_BlueAdvocate.think"]
  BA --> J["_Judge.think"]
  J --> V["_parse_verdict"]
  V -->|JSON valid| OK["verdict + adjusted_severity"]
  V -->|JSON tidak terbaca| VM["VERIFY_MANUALLY, confidence=50"]
  style F fill:#8b5cf6,color:#fff
  style R1 fill:#2d7d46,color:#fff
  style R2 fill:#dc2626,color:#fff
  style VM fill:#f59e0b,color:#000
  style OK fill:#2d7d46,color:#fff
%% fig: Percabangan triase debat
%% desc: Hanya temuan berprobabilitas false positive MEDIUM yang masuk debat red, blue, dan judge; verdict yang tidak terbaca turun ke VERIFY_MANUALLY.
Fig. 2: Percabangan triase debatHanya temuan berprobabilitas false positive MEDIUM yang masuk debat red, blue, dan judge; verdict yang tidak terbaca turun ke VERIFY_MANUALLY.

Tiga peran dijalankan berurutan dengan think terpisah tetapi satu client yang sama: red advocate membela bahwa temuan nyata, blue advocate membela bahwa temuan false positive, lalu judge menerima kedua argumen yang dibungkus wrap_untrusted dan mengeluarkan verdict beserta severity yang disesuaikan core/agents/debate_triage.py:111-166. Hasilnya adalah dataclass DebateVerdict berisi finding_id, verdict, adjusted_severity, rationale, confidence, kedua argumen, dan penanda triggered core/agents/debate_triage.py:44-55.

Sinyal pra-debat dibaca dari baris False_Positive: <LOW|MEDIUM|HIGH> di deskripsi finding; bila tidak terbaca, nilainya MEDIUM sehingga debat tetap dijalankan core/agents/debate_triage.py:170-183. Verdict judge divalidasi terhadap himpunan nilai yang sah, dan bila JSON tidak terbaca hasilnya VERIFY_MANUALLY dengan confidence 50 karena menaikkan ke manusia lebih baik daripada menebak core/agents/debate_triage.py:202-241.

Di dalam workflow, langkah analysis dengan agent: debate mengumpulkan semua finding MEDIUM, menjalankan triage satu per satu, lalu menerapkan hasilnya ke finding di memori: FALSE_POSITIVE menyalakan false_positive, severity diganti, dan rationale ditambahkan ke description core/workflow.py:338-377.

⚠️ Satu langkah debat memanggil model tiga kali untuk setiap finding MEDIUM. Pada sesi dengan banyak temuan ambigu, langkah ini menjadi sumber biaya terbesar setelah analisis awal.

Triase visual: bukti gambar untuk temuan

VisualTriage memperkaya temuan dengan deskripsi yang berasal dari gambar, bukan menggantinya. Alur kerjanya berhenti lebih awal bila syaratnya tidak terpenuhi.

graph TD
  A["_active_provider"] --> B{"supports_vision?"}
  B -->|tidak| S1["skipped_reason: active provider has no vision support"]
  B -->|ya| C["_collect_screenshots"]
  C --> D{"ada screenshot?"}
  D -->|tidak| S2["skipped_reason: no screenshots in memory"]
  D -->|ya| E["_best_finding_for_url"]
  E -->|tidak cocok| SKIP["screenshot dilewati"]
  E -->|cocok| F["_enrich_one"]
  F --> G["_apply_enrichment"]
  G --> H["description + raw_evidence"]
  style S1 fill:#f59e0b,color:#000
  style S2 fill:#f59e0b,color:#000
  style SKIP fill:#dc2626,color:#fff
  style H fill:#336791,color:#fff
%% fig: Alur triase visual
%% desc: Provider tanpa dukungan vision atau memori tanpa screenshot membuat langkah ini dilewati tanpa kehilangan temuan tekstual, sedangkan temuan yang cocok menerima tambahan deskripsi dan path gambar.
Fig. 3: Alur triase visualProvider tanpa dukungan vision atau memori tanpa screenshot membuat langkah ini dilewati tanpa kehilangan temuan tekstual, sedangkan temuan yang cocok menerima tambahan deskripsi dan path gambar.

triage_findings mengembalikan {"enrichments": [], "skipped_reason": ...} ketika provider aktif tidak mendukung vision atau ketika tidak ada screenshot di memori; pemanggil mencatat alasan itu dan melanjutkan core/agents/visual_triage.py:59-100. Provider aktif dicari dengan memeriksa atribut provider, active_provider, dan _provider pada client, lalu jatuh ke client itu sendiri bila ia mengimplementasikan supports_vision core/agents/visual_triage.py:104-119.

Pencocokan gambar ke temuan berlangsung dua tahap: host URL dicocokkan dengan finding.target, dan bila tidak ada yang cocok, temuan pertama dari tool web seperti httpx, nuclei, atau whatweb dipakai core/agents/visual_triage.py:152-183. _apply_enrichment menambahkan blok [Visual Triage — page_type=..., supports=..., conf=...] beserta indikator yang terlihat ke description, lalu menambahkan baris screenshot: ke raw_evidence agar lampiran laporan tetap menyimpan path gambar core/agents/visual_triage.py:234-248. Langkah ini terpasang di workflow sebagai langkah analysis dengan agent: visual core/workflow.py:379-397.

Biaya dan keterlacakan

Karena setiap panggilan think menulis ke token_ledger dan thinking_chain, dua hal bisa dijawab tanpa instrumentasi tambahan. Pertama, get_token_summary memberi total token dan biaya per provider, model, dan agen core/memory.py:163-202. Kedua, ReporterAgent.generate_ai_trace merangkum ai_decisions dan thinking_chain menjadi bagian laporan yang bisa diaudit, termasuk nomor langkah, agen, dan nomor ronde core/reporter_agent.py:148-169. Efek sampingnya, semua ronde think_deeply dan panggilan judge ikut terlihat di laporan, sehingga keputusan yang mahal tidak tersembunyi.