ai-agents-for-beginners

Watch the lesson video: Menyediakan Ejen AI dengan Resit Kriptografi

(Video pelajaran dan gambar kecil akan ditambah oleh pasukan kandungan Microsoft selepas penggabungan, mengikut corak pelajaran 14 / 15.)

Menyediakan Ejen AI dengan Resit Kriptografi

Pengenalan

Pelajaran ini akan merangkumi:

Matlamat Pembelajaran

Selepas menamatkan pelajaran ini, anda akan tahu cara untuk:

Masalah: Jejak Audit Ejen Anda

Bayangkan anda telah mengerahkan ejen AI untuk Contoso Travel. Ejen membaca permintaan pelanggan, memanggil API penerbangan untuk mencari pilihan, dan menempah tempat duduk bagi pihak pelanggan. Suku terakhir lalu, ejen memproses 50,000 tempahan.

Hari ini seorang juruaudit tiba. Mereka bertanya soalan mudah: “Tunjukkan apa yang ejen anda lakukan.”

Anda menyerahkan fail log anda. Juruaudit melihatnya dan bertanya soalan yang lebih sukar: “Bagaimana saya tahu log ini tidak diedit?”

Ini adalah masalah jejak audit. Kebanyakan penyebaran ejen hari ini bergantung kepada:

Tiada satu pun yang boleh menjawab soalan juruaudit tanpa memerlukan juruaudit mempercayai seseorang (anda, penyedia awan anda, vendor pangkalan data anda). Untuk penggunaan dalaman, kepercayaan tersebut biasanya boleh diterima. Untuk beban kerja terkawal (kewangan, penjagaan kesihatan, apa sahaja tertakluk kepada Akta AI EU), ia tidak boleh.

Resit kriptografi menyelesaikan ini dengan menjadikan setiap tindakan ejen boleh disahkan secara bebas. Juruaudit tidak perlu mempercayai anda. Mereka hanya perlu kunci awam anda dan resit itu sendiri.

Apa Itu Resit Kriptografi?

Resit adalah objek JSON yang merekodkan apa yang ejen lakukan, ditandatangani dengan tandatangan digital.

flowchart LR
    A[Ejen memanggil alat] --> B[Bina muatan resit]
    B --> C[Kanunkan JSON RFC 8785]
    C --> D[Hash SHA-256]
    D --> E[Tandatangan Ed25519]
    E --> F[Resit dengan tandatangan]
    F --> G[Auditor mengesah tanpa talian]
    G --> H{Tandatangan sah?}
    H -- ya --> I[Bukti tahan gangguan]
    H -- tidak --> J[Resit ditolak]

Resit minimum kelihatan seperti ini:

{
  "type": "agent.tool_call.v1",
  "agent_id": "contoso-travel-bot",
  "tool_name": "lookup_flights",
  "tool_args_hash": "sha256:a3f9c1...",
  "result_hash": "sha256:7b2e1d...",
  "policy_id": "contoso-travel-policy-v3",
  "timestamp": "2026-04-25T14:30:00Z",
  "sequence": 47,
  "previous_receipt_hash": "sha256:9d4e6a...",
  "signature": {
    "alg": "EdDSA",
    "sig": "c5af83...",
    "public_key": "8f3b2c..."
  }
}

Tiga sifat yang menjalankan kerja:

  1. Tandatangan. Resit ditandatangani oleh pintu masuk ejen menggunakan kunci peribadi Ed25519. Sesiapa yang mempunyai kunci awam sepadan boleh mengesahkan tandatangan itu secara luar talian. Penyuntingan mana-mana medan akan membatalkan tandatangan.

  2. Pengekodan kanonik. Sebelum menandatangani, resit diseriaknakan menggunakan Skema Kanonifikasi JSON (JCS, RFC 8785). Ini memastikan dua pelaksanaan yang menghasilkan resit logik yang sama menghasilkan output yang sama tepat. Tanpa kanonikifikasi, serializer JSON berbeza akan menghasilkan tandatangan berbeza untuk kandungan sama.

  3. Rantai hash. Medan previous_receipt_hash menghubungkan setiap resit kepada resit sebelumnya. Mengeluarkan atau menyusun semula satu resit akan merosakkan setiap resit selepasnya. Penyuntingan menjadi jelas pada tahap rantai walaupun tandatangan individu dimintas.

Ketiga-tiga sifat ini memberikan tiga jaminan:

Menghasilkan Resit dalam Python

Anda tidak memerlukan perpustakaan khas untuk menghasilkan resit. Primitif kriptografi tersedia meluas dan logiknya hanya beberapa baris Python.

Latihan secara langsung dalam code_samples/18-signed-receipts.ipynb menerangkan alur penuh. Versi ringkasnya:

import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize  # JSON kanonik RFC 8785

def b64url_nopad(data: bytes) -> str:
    return base64.urlsafe_b64encode(data).decode("ascii").rstrip("=")

def sha256_canonical(obj) -> str:
    """SHA-256 of a Python object's JCS-canonical JSON form."""
    return f"sha256:{hashlib.sha256(canonicalize(obj)).hexdigest()}"

# Jana atau muatkan kunci tandatangan (dalam pengeluaran, simpan dalam peti kunci)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key

# Bina muatan resit (belum ada tandatangan)
tool_args = {"origin": "SYD", "destination": "LAX"}
tool_result = [{"flight": "QF11", "price": 1850, "stops": 0}]

payload = {
    "type": "agent.tool_call.v1",
    "agent_id": "contoso-travel-bot",
    "tool_name": "lookup_flights",
    "tool_args_hash": sha256_canonical(tool_args),
    "result_hash": sha256_canonical(tool_result),
    "policy_id": "contoso-travel-policy-v3",
    "timestamp": "2026-04-25T14:30:00Z",
    "sequence": 0,
    "previous_receipt_hash": None,
}

# Kanonikan, hash, tandatangan.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature

# Lampirkan objek tandatangan berstruktur.
receipt = {
    **payload,
    "signature": {
        "alg": "EdDSA",
        "sig": b64url_nopad(signature_bytes),
        "public_key": b64url_nopad(bytes(verify_key)),
    },
}

Itu keseluruhan laluan penandatanganan. Latihan dalam notebook menerangkan setiap langkah.

Mengesahkan Resit dan Mengesan Penyuntingan

Pengesahan adalah operasi songsang:

import base64
import hashlib
from nacl import signing
from nacl.exceptions import BadSignatureError
from jcs import canonicalize

def b64url_decode(s: str) -> bytes:
    padding = "=" * ((4 - len(s) % 4) % 4)
    return base64.urlsafe_b64decode(s + padding)

def verify_receipt(receipt: dict) -> bool:
    # Tandatangan adalah objek berstruktur: {"alg", "sig", "public_key"}.
    sig_obj = receipt.get("signature")
    if not sig_obj or sig_obj.get("alg") != "EdDSA":
        return False

    # Bangunkan semula muatan yang sebenarnya ditandatangani (semua kecuali tandatangan).
    payload = {k: v for k, v in receipt.items() if k != "signature"}

    canonical_bytes = canonicalize(payload)
    message_hash = hashlib.sha256(canonical_bytes).digest()

    try:
        verify_key = signing.VerifyKey(b64url_decode(sig_obj["public_key"]))
        verify_key.verify(message_hash, b64url_decode(sig_obj["sig"]))
        return True
    except BadSignatureError:
        return False

Fungsi ini mengambil resit dan mengembalikan True jika tandatangan sah, False jika tidak. Tiada panggilan rangkaian, tiada kebergantungan perkhidmatan, tiada kepercayaan diperlukan kepada mana-mana pihak ketiga.

Untuk melihat pengesanan penyuntingan berfungsi, notebook terangkan:

  1. Menghasilkan resit sah dan mengesahkan ia sah.
  2. Mengubah satu bait medan tool_args_hash.
  3. Menjalankan semula pengesahan dan melihat ia gagal.

Ini adalah demonstrasi praktikal bahawa resit boleh dikesan penyuntingannya: sebarang pengubahsuaian, walaupun kecil, merosakkan tandatangan.

Mengikat Rantai Resit untuk Ejen Multi-Langkah

Satu resit bertandatangan melindungi satu tindakan. Rantai resit melindungi satu urutan.

flowchart LR
    R0[Resit 0<br/>asal] --> R1[Resit 1]
    R1 --> R2[Resit 2]
    R2 --> R3[Resit 3]
    R1 -. previous_receipt_hash .-> R0
    R2 -. previous_receipt_hash .-> R1
    R3 -. previous_receipt_hash .-> R2

Setiap resit merekod hash resit sebelumnya. Untuk mengeluarkan resit 2 tanpa dikesan, penyerang perlu sama ada:

Jika kunci peribadi disimpan dalam peti kunci perkakasan dan anda menerbitkan kunci awam bersama setiap resit, kedua-dua serangan tersebut tidak mungkin berlaku tanpa dikesan.

Notebook menerangkan:

  1. Membina rantai tiga resit.
  2. Mengesahkan bahawa medan previous_receipt_hash setiap resit sepadan dengan hash sebenar resit sebelumnya.
  3. Menyunting satu resit di tengah dan melihat rantai terputus tepat pada titik itu.

Inilah cara anda menghasilkan jejak audit yang boleh disahkan juruaudit luar tanpa perlu mempercayai anda.

Apa yang Resit Buktikan (dan Apa yang Tidak)

Ini adalah bahagian paling penting pelajaran ini. Resit sangat kuat tapi kuasanya terhad.

Resit membuktikan tiga perkara:

  1. Atribusi: kunci tertentu menandatangani muatan tertentu.
  2. Integriti: muatan tidak berubah sejak ditandatangani.
  3. Susunan: resit ini datang selepas resit yang lain dalam rantai hash.

Resit TIDAK membuktikan:

  1. Ketepatan: tindakan ejen adalah tindakan yang betul. Resit boleh ditandatangani untuk jawapan salah sama bersihnya seperti untuk jawapan betul.
  2. Pematuhan polisi: polisi yang dirujuk dalam policy_id benar-benar dinilai, atau bahawa ia akan membenarkan tindakan ini jika diperiksa. Resit merekod apa yang dituntut, bukan apa yang dikuatkuasakan.
  3. Identiti selain kunci: resit berkata “kunci ini menandatangani kandungan ini.” Ia tidak berkata “manusia ini membenarkan ini.” Menghubungkan kunci kepada orang atau organisasi memerlukan infrastruktur identiti berasingan (direktori, daftar kunci awam, dsb.).
  4. Kebenaran input: jika ejen menerima arahan yang dimanipulasi dan bertindak ke atasnya, resit merekod tindakan dengan setia. Resit adalah selepas pengesahan input, bukan pengganti padanya.

Sempadan ini penting untuk dua sebab:

Kesilapan biasa ialah menganggap “kami ada resit” bermaksud “kami diperintah.” Tidak begitu. Resit adalah asas. Tadbir urus adalah sistem yang anda bina di atasnya.

Rujukan Pengeluaran

Kod Python dalam pelajaran ini sengaja minimum supaya anda boleh baca setiap baris dan faham apa yang berlaku. Dalam pengeluaran, anda ada dua pilihan:

  1. Terus bina atas primitif kriptografi. 50 baris yang anda lihat di atas sudah cukup untuk banyak kes penggunaan. PyNaCl (Ed25519) dan pakej jcs (JSON kanonik) adalah perpustakaan yang diselenggara dan diaudit dengan baik.

  2. Gunakan perpustakaan resit pengeluaran. Beberapa projek sumber terbuka melaksanakan corak sama dengan ciri tambahan (rotasi kunci, pengesahan berkelompok, pengedaran JWK Set, integrasi dengan enjin polisi):

    • Format resit yang digunakan dalam pelajaran ini mengikuti Draf Internet IETF (draft-farley-acta-signed-receipts) yang kini dalam proses piawaian.
    • Microsoft Agent Governance Toolkit menggabungkan resit dengan keputusan polisi berdasar Cedar; lihat Tutorial 33 dalam repositori itu untuk contoh menyeluruh.
    • Pakej protect-mcp (npm) dan @veritasacta/verify (npm) menyediakan pelaksanaan Node bagi penandatanganan resit dan pengesahan luar talian, bertujuan untuk membalut mana-mana pelayan MCP dengan jejak audit yang mudah dikesan penyuntingannya.

Keputusan antara membina sendiri dan guna perpustakaan serupa dengan keputusan menulis perpustakaan JWT sendiri versus guna perpustakaan yang telah diuji: kedua-duanya munasabah; perpustakaan menjimatkan masa dan mengurangkan kawasan audit; cara-bina-sendiri memaksa anda faham setiap primitif. Pelajaran ini mengajar jalan cara-bina-sendiri supaya anda ada asas untuk mana-mana pilihan.

Semak Pengetahuan

Uji kefahaman anda sebelum beralih ke latihan praktikal.

1. Resit ditandatangani menggunakan kunci peribadi Ed25519 ejen. Juruaudit hanya ada kunci awam. Boleh juruaudit mengesahkan resit secara luar talian?

Jawapan Boleh. Pengesahan Ed25519 hanya memerlukan kunci awam dan bait bertandatangan. Tiada panggilan rangkaian, tiada kebergantungan perkhidmatan. Ini sifat yang menjadikan resit berguna dalam keadaan audit berpisah udara, pelbagai organisasi, atau kepercayaan rendah.

2. Penyerang mengubah medan policy_id dalam resit untuk mendakwa ia dikawal oleh polisi lebih permisif. Tandatangan itu dibuat ke atas muatan asal. Apa berlaku semasa pengesahan?

Jawapan Pengesahan gagal. Tandatangan dikira ke atas bait kanonik muatan asal; mengubah mana-mana medan mengubah bait kanonik, yang mengubah hash SHA-256, menyebabkan tandatangan tidak sah. Penyerang perlu kunci peribadi untuk menghasilkan tandatangan sah baru, yang mereka tidak ada.

3. Kenapa resit memasukkan tool_args_hash dan result_hash dan bukan hujah dan keputusan mentah?

Jawapan Dua sebab. Pertama, resit mungkin perlu diarkib atau dihantar dalam persekitaran di mana mendedahkan kandungan mentah (PII, data perniagaan) adalah masalah. Hash menjaga resit kecil dan kandungan peribadi; juruaudit mengesahkan hash sepadan dengan salinan kandungan sebenar yang disimpan berasingan. Kedua, hash berukuran tetap; resit dengan hash terhad saiznya tanpa mengira besar input dan output.

4. Medan previous_receipt_hash menghubungkan setiap resit kepada pendahulunya. Jika penyerang memadam satu resit secara senyap dari tengah rantai, apa yang menjadi tidak sah?

Jawapan Setiap resit selepas yang dipadam. Medan `previous_receipt_hash` mereka tidak sepadan dengan rantai sebenar (kerana resit dirujuk tidak wujud lagi, atau rantai kini tunjuk ke pendahulu berbeza). Untuk menyembunyikan pemadaman, penyerang perlu menandatangani semula setiap resit kemudian, yang memerlukan kunci peribadi.

5. Resit mengesahkan dengan bersih. Adakah itu membuktikan tindakan ejen betul, sah, atau patuh polisi?

Jawapan Tidak. Resit sah membuktikan tiga perkara: atribusi (kunci ini menandatangani ini), integriti (kandungan tidak berubah), dan susunan (resit ini datang selepas yang lain). Ia TIDAK membuktikan tindakan betul, bahawa polisi `policy_id` benar menilai, atau ejen ikut setiap peraturan. Resit menjadikan tingkah laku ejen audit-able, tidak semestinya betul. Ini sempadan paling penting dalam pelajaran.

Latihan Praktikal

Buka code_samples/18-signed-receipts.ipynb dan lengkapkan keempat-empat bahagian:

  1. Bahagian 1: Tandatangani resit pertama anda dan sahkan ia.
  2. Bahagian 2: Ubah suai resit dan perhatikan pengesahan gagal.
  3. Bahagian 3: Bina rantai tiga resit dan sahkan integriti rantai.
  4. Bahagian 4: Gunakan corak ini pada ejen yang dibina dengan Microsoft Agent Framework: bungkus panggilan alat dalam penandatanganan resit, kemudian sahkan resit secara bebas.

Cabaran lanjutan 1: lanjutkan skema resit dengan medan tambahan pilihan anda (contohnya, ID permintaan untuk penjejakan), kemas kini logik penandatanganan kanonik untuk memasukkannya, dan sahkan resit masih melalui pengesahan. Kemudian ubah medan selepas tandatangan dan sahkan pengesahan gagal. Ini memaksa anda faham bagaimana setiap bait pengekodan kanonik menyumbang kepada tandatangan. Cabaran regangan 2: SHA-256-hash dua resit anda bersama-sama (gabungkan bait kanonik mereka dalam susunan deterministik) dan tanamkan digest yang terhasil sebagai medan baharu pada resit ketiga sebelum menandatanganinya. Sahkan bahawa ketiga-tiga resit masih boleh diproses dua hala. Anda baru sahaja membina bukti kemasukan satu langkah: sesiapa yang memegang resit ketiga boleh membuktikan dua resit pertama wujud pada masa ia ditandatangani, tanpa perlu mendedahkan kandungannya. Ini adalah corak yang digunakan oleh resit pendedahan selektif pada skala besar (komitmen Merkle, RFC 6962).

Kesimpulan

Resit kriptografi memberikan ejen AI jejak audit yang:

Ia bukan pengganti untuk pengesahan input, penguatkuasaan dasar, atau infrastruktur identiti. Ia adalah asas bagi lapisan-lapisan tersebut. Apabila anda melancarkan ejen ke dalam beban kerja terkawal, aliran kerja pelbagai organisasi, atau mana-mana tetapan di mana juruaudit masa depan tidak boleh dianggap mempercayai anda, resit adalah cara untuk memastikan jejak audit jujur.

Pengajaran yang paling penting: resit membuktikan siapa yang berkata apa, bila. Ia tidak membuktikan bahawa apa yang dikatakan adalah benar atau tepat. Pegang perbezaan itu dengan erat. Ia adalah perbezaan antara sistem asal-usul yang jujur dan yang mengelirukan.

Senarai Semak Pengeluaran

Apabila anda bersedia untuk melangkah dari pelajaran ini kepada pelancaran ejen yang ditandatangani resit dalam persekitaran sebenar:

Ada Soalan Lebih Lanjut tentang Menyediakan Ejen AI?

Sertai Microsoft Foundry Discord untuk bertemu dengan pelajar lain, menghadiri waktu pejabat, dan mendapatkan jawapan kepada soalan Ejen AI anda.

Di Luar Pelajaran Ini

Pelajaran ini merangkumi penandatanganan resit tunggal dan urutan rantaian hash. Primitif yang sama membentuk beberapa corak lanjutan yang mungkin anda temui apabila kedudukan tadbir urus anda matang:

Sumber Tambahan

Pelajaran Sebelumnya

Menjadi Ejen Penggunaan Komputer (CUA)

Pelajaran Seterusnya

(Akan ditentukan oleh penyelenggara kurikulum)


Penafian: Dokumen ini telah diterjemahkan menggunakan perkhidmatan terjemahan AI Co-op Translator. Walaupun kami berusaha untuk ketepatan, sila ambil maklum bahawa terjemahan automatik mungkin mengandungi kesilapan atau ketidaktepatan. Dokumen asal dalam bahasa asalnya harus dianggap sebagai sumber yang sahih. Untuk maklumat penting, terjemahan oleh manusia profesional adalah disyorkan. Kami tidak bertanggungjawab terhadap sebarang salah faham atau salah tafsir yang timbul daripada penggunaan terjemahan ini.