การกำกับดูแลแบบรวมศูนย์ของ Agent Gateway ด้วย Agent Registry แบบข้ามโปรเจ็กต์สำหรับ Agent Runtime

1. บทนำ

เมื่อองค์กรระดับองค์กรนำ Generative AI มาใช้ สถาปัตยกรรมก็พัฒนาอย่างรวดเร็วจากแชทบอทแบบสแตนด์อโลนและแบบโมโนลิธไปเป็นระบบแบบหลายเอเจนต์แบบกระจาย (Agent-to-Agent / A2A) ในโทโพโลยีที่ทันสมัยเหล่านี้ เอเจนต์ Orchestrator ระดับสูงจะประสานงานเวิร์กโฟลว์ทางธุรกิจที่ซับซ้อนโดยมอบหมายงานให้กับเอเจนต์ Worker เฉพาะโดเมน เซิร์ฟเวอร์เครื่องมือ Model Context Protocol (MCP) และฐานข้อมูลระดับองค์กรแบ็กเอนด์ในโปรเจ็กต์ Google Cloud ที่เป็นอิสระ

อย่างไรก็ตาม การใช้งานระบบแบบหลายเอเจนต์ในวงกว้างทำให้เกิดความท้าทายด้านความปลอดภัย การกำกับดูแล และการปฏิบัติงานที่สำคัญ ดังนี้

  • Shadow Agent และการขยายเครื่องมือ: เมื่อทีมพัฒนาติดตั้งใช้งานเอเจนต์ในโปรเจ็กต์ที่แยกจากกันโดยไม่มีแคตตาล็อกส่วนกลาง องค์กรจะมองไม่เห็นว่ามีเครื่องมือและเอเจนต์ย่อยใดอยู่บ้าง
  • การส่งข้อมูลขาออกจากโปรเจ็กต์โดยไม่มีการตรวจสอบ: การอนุญาตให้ตัวแทนใช้เส้นทางเครือข่ายโดยตรงที่ไม่มีการตรวจสอบจะทำให้เกิดความเสี่ยงในการนำข้อมูลออกไปและข้ามขอบเขตด้านความปลอดภัย
  • การผสานรวมที่เขียนโค้ดแบบตายตัวซึ่งไม่ยืดหยุ่น: การเขียนโค้ดแบบตายตัวสำหรับ URL ของเอเจนต์ปลายทางและรหัสของ Reasoning Engine จะสร้างการอ้างอิงที่เปราะบางซึ่งจะหยุดทำงานระหว่างการอัปเกรดหรือการติดตั้งใช้งานใหม่
  • ไม่มีการระบุตัวตนที่มีสิทธิ์น้อยที่สุด: บัญชีบริการที่ใช้ร่วมกันไม่สามารถให้การปฏิเสธความรับผิดทางคริปโตกราฟีที่ระดับอินสแตนซ์ของตัวแทนแต่ละราย

แพลตฟอร์มเอเจนต์ Gemini Enterprise มีระนาบการควบคุมการกำกับดูแลและการเชื่อมต่อแบบรวมที่ประกอบด้วยเสาหลัก 4 ประการเพื่อแก้ปัญหาความท้าทายเหล่านี้

  1. เกตเวย์ของเอเจนต์ (networkservices.googleapis.com): พร็อกซีการบังคับใช้นโยบายและเครือข่ายระดับภูมิภาคที่มีการจัดการ เมื่อทำงานในAGENT_TO_ANYWHEREโหมดขาออก ระบบจะสกัดกั้นการรับส่งข้อมูลของเอเจนต์ขาออก มอบหมายการประเมินการให้สิทธิ์ให้กับส่วนขยายความปลอดภัย และกำหนดเส้นทางคำขอทั่วทั้งขอบเขตของโปรเจ็กต์
  2. Agent Registry (agentregistry.googleapis.com): แคตตาล็อกบริการขององค์กรเดียว ซึ่งมีไดเรกทอรีแบบรวมที่ผ่านการตรวจสอบของเครื่องมือ เซิร์ฟเวอร์ MCP และเอเจนต์เพียร์ทั้งหมดที่พร้อมใช้งานทั่วทั้งองค์กร ทำให้สามารถค้นหาอัตโนมัติแบบไดนามิกในรันไทม์โดยไม่มีฮาร์ดโค้ดของปลายทาง
  3. การกำกับดูแลข้อมูลประจำตัวของตัวแทนและ IAP เวอร์ชัน 2 (iap.googleapis.com และ iam.googleapis.com): กรอบการจัดการข้อมูลประจำตัวและการเข้าถึงแบบเข้ารหัส เอเจนต์ที่ดำเนินการจะได้รับ URN ของเครื่อง SPIFFE ที่รับรองและไม่ซ้ำกัน (principal://...) ระบบจะประเมินการออกขาออกเทียบกับนโยบายการเข้าถึงแบบรวม (UAP / IAP v2) ของ IAM ที่มีศูนย์กลางเพื่อยืนยันสิทธิ์สากล iap.googleapis.com/resources.egressViaIAP โดยใช้เงื่อนไขแคตตาล็อก Common Expression Language (CEL) ที่สมบูรณ์ (destination.agent_registry.*)
  4. Agent Runtime (เครื่องมือให้เหตุผล): แพลตฟอร์มการดำเนินการแบบ Serverless ที่มีการจัดการครบวงจรสำหรับแอปพลิเคชันแบบ Agent ที่ใช้ Python ซึ่งมีการเชื่อมโยงการกำหนดค่าดั้งเดิม (agent_gateway_config) กับเกตเวย์ส่วนกลาง

สถานการณ์ทางธุรกิจของ Codelab: การจัดซื้ออาหารและเครื่องดื่มหลายโปรเจ็กต์

ใน Codelab นี้ คุณจะได้สร้างและควบคุมระบบนิเวศการซื้อแบบหลายโปรเจ็กต์ในโลกแห่งความเป็นจริงซึ่งครอบคลุมโปรเจ็กต์ Google Cloud ที่แตกต่างกัน 3 โปรเจ็กต์ ดังนี้

  • โปรเจ็กต์การกำกับดูแลส่วนกลาง (PROJECT_GOVERNANCE): เป็นของทีมไอทีส่วนกลางและ SecOps ซึ่งโฮสต์เกตเวย์ของเอเจนต์ส่วนกลาง, รีจิสทรีของเอเจนต์ส่วนกลาง และนโยบายการเข้าถึงแบบรวมของ IAM
  • โปรเจ็กต์ Consumer Orchestrator (PROJECT_CONCIERGE): เป็นของทีมจัดซื้อ ซึ่งโฮสต์ตัวแทนบริการด้านการซื้อที่ค้นหาผู้ให้บริการและกำหนดเส้นทางคำสั่งซื้อของลูกค้าแบบไดนามิก
  • โปรเจ็กต์ของผู้ให้บริการโดเมน (PROJECT_SELLERS): เป็นของผู้ให้บริการภายนอกหรือผู้ให้บริการระดับแผนก ซึ่งโฮสต์ตัวแทนผู้ขายเบอร์เกอร์และตัวแทนผู้ขายพิซซ่า

figure1

รูปที่ 1 สถาปัตยกรรมการกำกับดูแลแบบรวมศูนย์หลายโปรเจ็กต์

เหตุใดจึงต้องมีการกํากับดูแลแบบรวมศูนย์ข้ามโปรเจ็กต์

ในองค์กรขนาดใหญ่ ทีมผลิตภัณฑ์และกลุ่มวิทยาศาสตร์ข้อมูลจะสร้างเอเจนต์ AI ในโปรเจ็กต์ Google Cloud ที่เป็นอิสระหลายสิบโปรเจ็กต์ การให้แต่ละทีมควบคุมการลงทะเบียนเครื่องมือ เส้นทางเครือข่ายขาออก และแนวทางการรักษาความปลอดภัยโดยตรงจะทำให้เกิดการขยายเครื่องมือที่ไม่ผ่านการตรวจสอบ นโยบาย DLP ที่ไม่สอดคล้องกัน ขาออกของ VPC ที่ไม่มีการตรวจสอบ และบันทึกการตรวจสอบที่กระจัดกระจาย

การกํากับดูแลแบบรวมศูนย์ข้ามโปรเจ็กต์จะแยกการเขียนนโยบายจากการดำเนินการของเอเจนต์

  • ไอทีส่วนกลางและ SecOps จะสร้างนโยบายความปลอดภัย ตรวจสอบเครื่องมือ และตรวจสอบการรับส่งข้อมูลขาออกภายในโปรเจ็กต์การกำกับดูแลแบบรวมศูนย์เดียว
  • ทีมผลิตภัณฑ์และแอปพลิเคชันมุ่งเน้นเฉพาะตรรกะทางธุรกิจในโปรเจ็กต์รันไทม์ของเอเจนต์ที่เป็นอิสระ โดยเชื่อมโยงกับเกตเวย์ส่วนกลางโดยตรงโดยไม่ต้องมีค่าใช้จ่ายในการดำเนินงานในการจัดการ VPC ในพื้นที่ การเชื่อมต่อ หรือเครื่องมือนโยบายที่กระจัดกระจาย

figure2

รูปที่ 2 สถาปัตยกรรมและการแบ่งขอบเขตการกำกับดูแลแบบ 3 ระดับข้ามโปรเจ็กต์

รูปแบบการกำหนดขอบเขตตัวตนแบบ 2 ระดับในนโยบายการเข้าถึงแบบรวม

เมื่อตัวแทนสื่อสารผ่าน Central Agent Gateway, Identity-Aware Proxy (IAP v2) จะประเมินการเข้าถึงตามข้อมูลประจำตัวของตัวแทนของผู้โทร ซึ่งเป็นข้อมูลประจำตัวที่อิงตาม SPIFFE ที่ได้รับการรับรองด้วยการเข้ารหัสซึ่งออกให้กับคอนเทนเนอร์รันไทม์โดยอัตโนมัติ โดยเทียบกับนโยบายการเข้าถึง IAM ทั่วโลก ดังนี้

  • ระดับที่ 1: Google Cloud API พื้นฐาน (แบบหยาบผ่าน principalSet:// ในกฎข้อที่ 1): การให้สิทธิ์ขาออกระดับโปรเจ็กต์ที่อนุญาตให้รันไทม์ของเอเจนต์ทั้งหมดในโปรเจ็กต์ Spoke เข้าถึง Google API มาตรฐาน (aiplatform, iamcredentials, telemetry, agentregistry) เพื่อการค้นหา การสร้างโทเค็น และการอนุมาน
  • ระดับที่ 2: เครื่องมือทางธุรกิจและบริการ A2A (ละเอียดผ่าน principal:// ในกฎข้อ 2 และ 3): การเข้าถึงที่มีสิทธิ์น้อยที่สุดอย่างเข้มงวดซึ่งเชื่อมโยงกับอินสแตนซ์ Reasoning Engine แต่ละรายการ บังคับใช้ด้วยเงื่อนไข Common Expression Language (CEL) ที่กำหนดเป้าหมายไปยังบริการ Agent Registry ที่ลงทะเบียนไว้โดยเฉพาะ (destination.agent_registry.agent.name)

สิ่งที่คุณสร้าง

  • Centralized Agent Gateway (centralized-agw) ใน PROJECT_GOVERNANCE
  • ส่วนขยายบริการให้สิทธิ์ IAP v2 และนโยบาย Authz ในโหมดบังคับใช้แบบเข้มงวด (failOpen: false)
  • นโยบายการเข้าถึงแบบรวมของ IAM พื้นฐาน (uap-rules.json) และการเชื่อมโยงนโยบายของโปรเจ็กต์
  • สิทธิ์ IAM ของตัวแทนบริการข้ามโปรเจ็กต์ (ar_agw_cross_project_sa)
  • Bucket พื้นที่งานส่วนกลางของ Google Cloud Storage (GCS) ที่ใช้ร่วมกัน
  • ตัวแทนผู้ขายเบอร์เกอร์และพิซซ่าที่แยกกันใน PROJECT_SELLERS
  • ตัวแทนบริการด้านการซื้อที่มีการค้นหาอัตโนมัติแบบไดนามิกของ REST ใน PROJECT_CONCIERGE
  • การลงทะเบียนบริการใน Central Agent Registry ด้วย URL ของ mTLS ข้ามโปรเจ็กต์
  • การอัปเดตนโยบายขาออกของ IAP v2 แบบไดนามิกพร้อมการยืนยันแบบเรียลไทม์และการตรวจสอบ Cloud Logging

figure3

รูปที่ 3 ลำดับการติดตั้งใช้งานแบบทีละขั้นตอน

สิ่งที่คุณจะได้เรียนรู้

  • วิธีกำหนดค่าสิทธิ์ IAM ของตัวแทนบริการข้ามโปรเจ็กต์สำหรับเกตเวย์แบบรวมศูนย์
  • วิธีกำหนดเส้นทางการออกของ Agent Runtime ผ่าน Agent Gateway ส่วนกลางในสภาพแวดล้อมแบบหลายโปรเจ็กต์
  • วิธีมอบสิทธิ์การให้สิทธิ์ Agent Gateway ให้กับ Identity-Aware Proxy (IAP v2) โดยใช้ส่วนขยายบริการ (iapPolicyVersion: "V2")
  • วิธีเขียนและเชื่อมโยงนโยบายการเข้าถึงแบบรวม (UAP) ของ IAM กับกฎ Common Expression Language (CEL) ที่ควบคุมปลายทางรีจิสทรีของตัวแทนที่ลงทะเบียน (destination.agent_registry.*)
  • วิธีกำจัดรหัสเอเจนต์และ URL แบบฮาร์ดโค้ดโดยใช้การค้นหาอัตโนมัติรันไทม์กับรีจิสทรีของเอเจนต์
  • วิธีทดสอบการบล็อกแบบ Zero Trust ที่ขอบเขตจริง (HTTP 403 Forbidden) และยืนยันการอัปเดตนโยบายแบบเรียลไทม์ใน Cloud Logging

สิ่งที่ต้องมี

  • โปรเจ็กต์ Google Cloud 3 รายการที่เปิดใช้การเรียกเก็บเงิน:
    • PROJECT_GOVERNANCE: นโยบายการกำกับดูแลส่วนกลาง เกตเวย์ รีจิสทรี และการเข้าถึง IAM
    • PROJECT_CONCIERGE: ตัวแทนผู้ประสานงานการซื้อ
    • PROJECT_SELLERS: ตัวแทนผู้ขายที่เชี่ยวชาญด้านเบอร์เกอร์และพิซซ่า
  • ผู้ใช้ IAM หรือบัญชีบริการที่มีสิทธิ์roles/ownerหรือสิทธิ์ระดับผู้ดูแลระบบในทั้ง 3 โปรเจ็กต์
  • องค์กร Google Cloud (สำหรับการแมปโดเมนที่เชื่อถือได้ของ SPIFFE)
  • Google Cloud Shell หรือเครื่องภายในที่มีการติดตั้ง gcloud CLI, python (3.11+) และ uv

เรามาถึงส่วนท้ายของส่วนแนะนำแล้ว... ต่อไปจะเป็นส่วนการตั้งค่าและสภาพแวดล้อม

2. ตั้งค่า

แม้ว่าสถาปัตยกรรมนี้จะครอบคลุมโปรเจ็กต์ Google Cloud ที่แตกต่างกัน 3 โปรเจ็กต์ แต่คุณก็สามารถเรียกใช้คำสั่งการติดตั้งใช้งานเทอร์มินัล การดาวน์โหลดที่เก็บ และการดำเนินการ Staging ได้ 100% จากเทอร์มินัล Cloud Shell เดียวที่ตั้งค่าเป็น PROJECT_GOVERNANCE สคริปต์การติดตั้งใช้งานและgcloudคำสั่งทุกรายการจะกำหนดเป้าหมายไปยังโปรเจ็กต์ปลายทางที่เหมาะสมอย่างชัดเจนผ่านแฟล็ก CLI (--project)

เริ่มต้นด้วยการเข้าถึงบรรทัดคำสั่งของโปรเจ็กต์ที่อยู่ในระบบคลาวด์ของ Google โดยทำดังนี้

กำหนดบริบทของโปรเจ็กต์

# set terminal project context to Central Governance Project
gcloud config set project SET_YOUR_GOVERNANCE_PROJECT_ID_HERE
# login to gcloud cli
gcloud auth login
# login for application default credentials
gcloud auth application-default login
# update gcloud components
gcloud components update --quiet

ตั้งค่าตัวแปรสภาพแวดล้อมของ Shell

ป้อนตัวระบุเฉพาะของโปรเจ็กต์

# 1. Project Identifiers
export PROJECT_GOVERNANCE="SET_YOUR_GOVERNANCE_PROJECT_ID_HERE"
export PROJECT_CONCIERGE="SET_YOUR_CONCIERGE_PROJECT_ID_HERE"
export PROJECT_SELLERS="SET_YOUR_SELLERS_PROJECT_ID_HERE"

ระบบจะดึงตัวแปรเชลล์เหล่านี้โดยอัตโนมัติ

# 2. Regional & Gateway Settings
export REGION="us-central1"
export AGW_NAME="centralized-agw"
export UAP_POLICY_NAME="uap-policy-${AGW_NAME}"
export UAP_BINDING_NAME="uap-binding-${AGW_NAME}"

# 3. Retrieve Project Numbers
export PROJECT_NUMBER_GOVERNANCE=$(gcloud projects describe ${PROJECT_GOVERNANCE} --format="value(projectNumber)")
export PROJECT_NUMBER_CONCIERGE=$(gcloud projects describe ${PROJECT_CONCIERGE} --format="value(projectNumber)")
export PROJECT_NUMBER_SELLERS=$(gcloud projects describe ${PROJECT_SELLERS} --format="value(projectNumber)")

# 4. Obtain Organization ID
export ORG_ID=$(gcloud projects get-ancestors ${PROJECT_GOVERNANCE} --format="value(id, type)" | grep organization | awk '{print $1}')

# 5. Set Application Default Credentials (ADC) Quota Project
gcloud auth application-default set-quota-project ${PROJECT_GOVERNANCE}

echo "Governance Project: ${PROJECT_GOVERNANCE} (${PROJECT_NUMBER_GOVERNANCE})"
echo "Concierge Project:  ${PROJECT_CONCIERGE} (${PROJECT_NUMBER_CONCIERGE})"
echo "Sellers Project:    ${PROJECT_SELLERS} (${PROJECT_NUMBER_SELLERS})"
echo "Organization ID:    ${ORG_ID}"
echo "UAP Policy Name:    ${UAP_POLICY_NAME}"
echo "UAP Binding Name:   ${UAP_BINDING_NAME}"

สร้างไดเรกทอรีในเครื่องสำหรับไฟล์การกำหนดค่า

# create config folder
mkdir -p cfg

กำหนดบทบาทผู้ดูแลระบบนโยบายการเข้าถึงสำหรับนโยบายการเข้าถึงแบบรวม

# grant Access Policy Admin and Project IAM Admin to current user in Governance Project
for ROLE in "roles/iam.accessPolicyAdmin" "roles/resourcemanager.projectIamAdmin"; do
  gcloud projects add-iam-policy-binding ${PROJECT_GOVERNANCE} \
    --member="user:$(gcloud config get-value account)" \
    --role="${ROLE}" \
    --condition=None
done

เปิดใช้บันทึกการเข้าถึงข้อมูลการตรวจสอบของ Cloud สำหรับ IAP v2

โดยค่าเริ่มต้น Google Cloud จะปิดใช้บันทึกการตรวจสอบการเข้าถึงข้อมูลเพื่อป้องกันค่าใช้จ่ายในการจัดเก็บที่ไม่ต้องการ เนื่องจาก IAP v2 จะส่งการตัดสินการให้สิทธิ์ (granted=true และ granted=false) เป็นบันทึกการตรวจสอบการเข้าถึงข้อมูล ให้เปิดใช้การบันทึก ADMIN_READ, DATA_READ และ DATA_WRITE สำหรับ iap.googleapis.com ใน PROJECT_GOVERNANCE ดังนี้

# 1. export current IAM policy for PROJECT_GOVERNANCE
gcloud projects get-iam-policy ${PROJECT_GOVERNANCE} \
  --format=json > cfg/gov_iam_policy.json
# 2. append auditConfigs for iap.googleapis.com
python3 -c "
import json
with open('cfg/gov_iam_policy.json') as f:
    policy = json.load(f)
audit_configs = [c for c in policy.get('auditConfigs', []) if c.get('service') != 'iap.googleapis.com']
audit_configs.append({
    'service': 'iap.googleapis.com',
    'auditLogConfigs': [
        {'logType': 'ADMIN_READ'},
        {'logType': 'DATA_READ'},
        {'logType': 'DATA_WRITE'}
    ]
})
policy['auditConfigs'] = audit_configs
with open('cfg/gov_iam_policy.json', 'w') as f:
    json.dump(policy, f, indent=2)
"
# 3. apply updated policy
gcloud projects set-iam-policy ${PROJECT_GOVERNANCE} cfg/gov_iam_policy.json
# 4. verify auditConfigs applied
gcloud projects get-iam-policy ${PROJECT_GOVERNANCE} --format="yaml(auditConfigs)"

เปิดใช้ Google Cloud APIs ที่จำเป็น

# enable google apis (agent platform & security bundle, part 1)
for PROJ in ${PROJECT_GOVERNANCE} ${PROJECT_CONCIERGE} ${PROJECT_SELLERS}; do
  gcloud services enable \
    agentregistry.googleapis.com \
    aiplatform.googleapis.com \
    apphub.googleapis.com \
    apptopology.googleapis.com \
    cloudapiregistry.googleapis.com \
    cloudtrace.googleapis.com \
    compute.googleapis.com \
    dataform.googleapis.com \
    iam.googleapis.com \
    agentidentity.googleapis.com \
    iap.googleapis.com \
    logging.googleapis.com \
    modelarmor.googleapis.com \
    monitoring.googleapis.com \
    networksecurity.googleapis.com \
    networkservices.googleapis.com \
    notebooks.googleapis.com \
    observability.googleapis.com \
    --project=${PROJ}
done
# enable google apis (agent platform bundle, part 2)
for PROJ in ${PROJECT_GOVERNANCE} ${PROJECT_CONCIERGE} ${PROJECT_SELLERS}; do
  gcloud services enable \
    securitycenter.googleapis.com \
    saasservicemgmt.googleapis.com \
    storage.googleapis.com \
    telemetry.googleapis.com \
    texttospeech.googleapis.com \
    --project=${PROJ}
done
# enable google apis (foundational & agent runtime build bundle, part 3)
for PROJ in ${PROJECT_GOVERNANCE} ${PROJECT_CONCIERGE} ${PROJECT_SELLERS}; do
  gcloud services enable \
    artifactregistry.googleapis.com \
    cloudbuild.googleapis.com \
    cloudresourcemanager.googleapis.com \
    iamcredentials.googleapis.com \
    serviceusage.googleapis.com \
    run.googleapis.com \
    orgpolicy.googleapis.com \
    --project=${PROJ}
done

ตรวจสอบการเปิดใช้ API ในทุกโปรเจ็กต์

การตรวจสอบว่าทั้ง 3 โปรเจ็กต์ (PROJECT_GOVERNANCE, PROJECT_CONCIERGE และ PROJECT_SELLERS) มีการเปิดใช้ API เดียวกันทุกประการจะช่วยสร้างความสอดคล้องในการดำเนินงานและป้องกันไม่ให้เกิดความล้มเหลวในการสร้างโทเค็นรันไทม์ ข้อผิดพลาดในการจัดแคตตาล็อกสคีมา หรือการขาดหายไปของข้อมูลการวัดและส่งข้อมูล

เรียกใช้สคริปต์การตรวจสอบต่อไปนี้ใน Cloud Shell เพื่อยืนยันความเท่าเทียมของ API ในทั้ง 3 โปรเจ็กต์

# validate that all required APIs are enabled across all 3 projects
python3 - << 'EOF'
import subprocess
import os
import sys

REQUIRED_APIS = [
    "agentregistry.googleapis.com",
    "aiplatform.googleapis.com",
    "apphub.googleapis.com",
    "apptopology.googleapis.com",
    "cloudapiregistry.googleapis.com",
    "cloudtrace.googleapis.com",
    "compute.googleapis.com",
    "dataform.googleapis.com",
    "iam.googleapis.com",
    "agentidentity.googleapis.com",
    "iap.googleapis.com",
    "logging.googleapis.com",
    "modelarmor.googleapis.com",
    "monitoring.googleapis.com",
    "networksecurity.googleapis.com",
    "networkservices.googleapis.com",
    "notebooks.googleapis.com",
    "observability.googleapis.com",
    "securitycenter.googleapis.com",
    "saasservicemgmt.googleapis.com",
    "storage.googleapis.com",
    "telemetry.googleapis.com",
    "texttospeech.googleapis.com",
    "artifactregistry.googleapis.com",
    "cloudbuild.googleapis.com",
    "cloudresourcemanager.googleapis.com",
    "iamcredentials.googleapis.com",
    "serviceusage.googleapis.com",
    "run.googleapis.com",
    "orgpolicy.googleapis.com"
]

projects = {
    "GOVERNANCE": os.environ.get("PROJECT_GOVERNANCE", ""),
    "CONCIERGE": os.environ.get("PROJECT_CONCIERGE", ""),
    "SELLERS": os.environ.get("PROJECT_SELLERS", "")
}

enabled = {}
for role, proj in projects.items():
    if not proj:
        print(f"Error: Environment variable for {role} is not set.")
        sys.exit(1)
    res = subprocess.run(
        ["gcloud", "services", "list", "--enabled", f"--project={proj}", "--format=value(config.name)"],
        capture_output=True, text=True, check=True
    )
    enabled[role] = set(res.stdout.strip().splitlines())

print(f"\n{'API Name':<36} | {'GOVERNANCE':<12} | {'CONCIERGE':<12} | {'SELLERS':<12}")
print("-" * 78)

all_synced = True
for api in REQUIRED_APIS:
    g_status = "ENABLED" if api in enabled["GOVERNANCE"] else "MISSING"
    c_status = "ENABLED" if api in enabled["CONCIERGE"] else "MISSING"
    s_status = "ENABLED" if api in enabled["SELLERS"] else "MISSING"
    if "MISSING" in (g_status, c_status, s_status):
        all_synced = False
    print(f"{api:<36} | {g_status:<12} | {c_status:<12} | {s_status:<12}")

print("-" * 78)
if all_synced:
    print("✅ All 29 required APIs are ENABLED and synchronized across all three projects.\n")
else:
    print("❌ Discrepancies detected. Please re-run the enablement commands for missing services.\n")
    sys.exit(1)
EOF

ตัวอย่างเอาต์พุตการตรวจสอบความถูกต้อง

คุณควรเห็นว่า API ทั้งหมดเปิดใช้อยู่

✅ All 30 required APIs are ENABLED and synchronized across all three projects.

กำหนดค่านโยบายองค์กร

นโยบายองค์กร Google Cloud เริ่มต้นจะบังคับใช้ข้อจํากัดที่จํากัดการเชื่อมโยงนโยบายการเข้าถึง IAM v3 กับทรัพยากร (constraints/iam.managed.disableAccessPolicyBinding)

ลบล้างข้อจำกัดของนโยบายองค์กรที่รับค่ามาในระดับโปรเจ็กต์โดยตั้งค่า enforce: false เป็นอนุญาตอย่างชัดเจน

# disable iam v3 constraint (allow v3 access policies)
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJECT_NUMBER_GOVERNANCE}/policies/iam.managed.disableAccessPolicyBinding
spec:
  rules:
  - enforce: false
EOF
# verify org policy constraints on project
gcloud org-policies describe iam.managed.disableAccessPolicyBinding \
  --project=${PROJECT_GOVERNANCE} --effective

ส่วนการตั้งค่าสิ้นสุดลงแล้ว... ไปที่ส่วนลงทะเบียน Core Google APIs กันต่อ

3. Agent Registry

ลงทะเบียนบริการปลายทางของ Core Google APIs

Agent Gateway กำหนดให้ต้องลงทะเบียน URL ของ Google API ในรีจิสทรีของ Central Agent เพื่อให้ Agent ที่กำหนดค่าด้วย agent_gateway_config สามารถกำหนดเส้นทางการรับส่งข้อมูลขาออกไปยังบริการแบ็กเอนด์หลักของ Google Cloud (เช่น aiplatform, ข้อมูลเข้าสู่ระบบ IAM และการวัดและส่งข้อมูล) ได้อย่างปลอดภัย

สร้าง core-gapi-services ในรีจิสทรีของ Agent

# register core google api endpoints in agent registry with standard and :443 port variants
gcloud agent-registry services create core-gapi-services \
  --project=${PROJECT_GOVERNANCE} \
  --location=${REGION} \
  --display-name="gapi.core.services" \
  --description="Core Google Cloud APIs and Service Endpoints" \
  --endpoint-spec-type=no-spec \
  --interfaces=protocolBinding=JSONRPC,url=https://telemetry.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://telemetry.mtls.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com:443 \
  --interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com:443 \
  --interfaces=protocolBinding=JSONRPC,url=https://aiplatform.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://aiplatform.googleapis.com:443 \
  --interfaces=protocolBinding=JSONRPC,url=https://aiplatform.mtls.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://aiplatform.mtls.googleapis.com:443 \
  --interfaces=protocolBinding=JSONRPC,url=https://cloudresourcemanager.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://iamcredentials.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://iamcredentials.mtls.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://agentregistry.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://agentregistry.mtls.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://agentregistry.googleapis.com:443 \
  --interfaces=protocolBinding=JSONRPC,url=https://agentregistry.mtls.googleapis.com:443

บันทึกรหัสทรัพยากรของปลายทาง Capture Core APIs

# capture the underlying Agent Registry endpoint ID
export ENDPOINT_ID=$(gcloud agent-registry services describe core-gapi-services \
  --project=${PROJECT_GOVERNANCE} \
  --location=${REGION} \
  --format="value(registryResource)" | awk -F'/' '{print $NF}')
echo "Core APIs Endpoint ID: ${ENDPOINT_ID}"

ทำความเข้าใจ principalSet กับ principal ในข้อมูลระบุตัวตนของ Agent

ใน Google Cloud IAM และ Gemini Enterprise Agent Platform ข้อมูลประจำตัวของเครื่องที่ออกให้กับคอนเทนเนอร์ของเอเจนต์ที่ดำเนินการจะใช้ URN ของ SPIFFE ที่ได้รับการรับรองด้วยการเข้ารหัสซึ่งประเมินโดย Identity-Aware Proxy (IAP v2) เมื่อกำหนดค่านโยบายการเข้าถึงแบบรวม IAM คุณสามารถกำหนดเป้าหมายเป็น principal เดียวที่เฉพาะเจาะจง หรือ principalSet ตามแอตทริบิวต์ได้

มิติข้อมูล

principal:// (ข้อมูลระบุตัวตนของเครื่องเดียว)

principalSet:// (กลุ่มตามแอตทริบิวต์)

ไวยากรณ์ IAM

principal://...

principalSet://...

ระดับรายละเอียด

แบบละเอียด (ระดับอินสแตนซ์): ระบุอินสแตนซ์คอนเทนเนอร์ Reasoning Engine ที่เฉพาะเจาะจงรายการเดียว

แบบหยาบ (ระดับโปรเจ็กต์): ระบุเครื่องมือการให้เหตุผลทั้งหมดที่แชร์แอตทริบิวต์โปรเจ็กต์ร่วมกัน

รูปแบบ URN

principal://agents.global.org-${ORG_ID}.system.id.goog/resources/aiplatform/projects/${PROJECT_NUMBER}/locations/${REGION}/reasoningEngines/${ENGINE_ID}

principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER}

กรณีการใช้งานในแพลตฟอร์มเอเจนต์

ระดับ 2 (เครื่องมือทางธุรกิจและ A2A): การให้สิทธิ์ตัวแทนผู้ประสานงานที่เฉพาะเจาะจงเพื่อเรียกใช้เครื่องมือโดเมนเป้าหมาย (เช่น เจ้าหน้าที่บริการด้านการซื้อ $\rightarrow$ ผู้ขายเบอร์เกอร์)

ระดับที่ 1 (โครงสร้างพื้นฐาน): การให้สิทธิ์เข้าถึงขาออกแก่ตัวแทนทั้งหมดในโปรเจ็กต์ไปยัง Google Cloud API (core-gapi-services)

ผลกระทบต่อวงจรผลิตภัณฑ์

หากมีการลบและสร้างเอเจนต์ขึ้นมาใหม่ รหัสเครื่องยนต์ใหม่ของเอเจนต์จะต้องมีการอัปเดตการเชื่อมโยงนโยบาย IAM

ใช้กับเอเจนต์ที่เพิ่งติดตั้งใช้งานในโปรเจ็กต์นั้นโดยอัตโนมัติโดยไม่ต้องอัปเดต IAM เพิ่มเติม

การกำกับดูแลแบบประกาศด้วยนโยบายการเข้าถึงแบบรวม (UAP / IAP v2)

ใน IAP v1 แบบเดิม ระบบจะแนบนโยบายขาออกกับทรัพยากร Agent Registry แต่ละรายการโดยตรงโดยใช้ gcloud beta iap web add-iam-policy-binding ในส่วนนโยบายการเข้าถึงแบบรวมและ IAP v2 ระบบจะยกเลิกการเชื่อมโยงต่อทรัพยากรเพื่อใช้นโยบายการเข้าถึง IAM แบบรวมศูนย์เดียว (cfg/uap-rules.json) แทน

การให้สิทธิ์ขาออกพื้นฐานสำหรับ core-gapi-services จะได้รับการกำหนดค่าเป็นกฎ 1 ในนโยบายการเข้าถึงแบบรวมในส่วนที่ 5 เพื่อให้มั่นใจว่าคอนเทนเนอร์ของตัวแทนทั้งหมดมีเส้นทางการส่งออกพื้นฐานก่อนการติดตั้งใช้งาน

ดูรายละเอียดทางเทคนิคเพิ่มเติมเกี่ยวกับตัวระบุหลักและกลไกการทำงานของ Workload Identity ได้ที่

การลงทะเบียนปลายทาง API หลักเสร็จสมบูรณ์แล้ว... ไปที่ส่วนติดตั้งใช้งานเกตเวย์ตัวแทนแบบรวมศูนย์กันต่อ

4. Agent Gateway

ติดตั้งใช้งาน Centralized Agent Gateway

ติดตั้งใช้งาน Agent Gateway (centralized-agw) ที่มีศูนย์กลางในโหมดขาออกของ AGENT_TO_ANYWHERE ภายในโปรเจ็กต์ $PROJECT_GOVERNANCE

กำหนดไฟล์ Manifest การกำหนดค่าเกตเวย์

สร้าง cfg/${AGW_NAME}.yaml สำหรับการกำกับดูแลการรับส่งข้อมูลขาออก

# generate agent gateway config yaml
cat > cfg/${AGW_NAME}.yaml << EOF
name: ${AGW_NAME}
protocols:
  - MCP
googleManaged:
  governedAccessPath: AGENT_TO_ANYWHERE
registries:
  - "//agentregistry.googleapis.com/projects/${PROJECT_GOVERNANCE}/locations/${REGION}"
EOF

การกำหนดค่าเกตเวย์ของ Agent การนำเข้า

# import and create agent gateway
gcloud network-services agent-gateways import ${AGW_NAME} \
  --source="cfg/${AGW_NAME}.yaml" \
  --location=${REGION} \
  --project=${PROJECT_GOVERNANCE}

ยืนยันรายละเอียดเกตเวย์ของตัวแทน

# show agent gateway status
gcloud network-services agent-gateways describe ${AGW_NAME} \
  --location=${REGION} \
  --project=${PROJECT_GOVERNANCE}

เอาต์พุตตัวอย่าง

agentGatewayCard:
  mtlsEndpoint: projects/${AGW_TP_ID}/regions/us-central1/serviceAttachments/unitkind1-swp-mtls-psc-sa
  rootCertificates:
  - |
    -----BEGIN CERTIFICATE-----
    MIIDwzCCAqugAwIBAgITNQuWGopdOZaHdcK7r7AYFhonqDANBgkqhkiG9w0BAQsF
    ...
    -----END CERTIFICATE-----
  serviceExtensionsServiceAccount: service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com
createTime: 'YYYY-MM-DDT12:34:56.789098765Z'
googleManaged:
  governedAccessPath: AGENT_TO_ANYWHERE
name: projects/${PROJECT_GOVERNANCE}/locations/us-central1/agentGateways/centralized-agw
protocols:
- MCP
registries:
- //agentregistry.googleapis.com/projects/${PROJECT_GOVERNANCE}/locations/us-central1
updateTime: 'YYYY-MM-DDT12:34:56.789098765Z'

การติดตั้งใช้งานเกตเวย์เสร็จสิ้นแล้ว... ไปที่ส่วนกำหนดค่าการให้สิทธิ์กันต่อ

5. การให้สิทธิ์

กำหนดค่าการให้สิทธิ์เกตเวย์ของ Agent และ UAP พื้นฐาน

Agent Gateway จะรักษาความปลอดภัยและควบคุมการเข้าชมเครื่องมือและ Agent ขาออกโดยใช้นโยบายการให้สิทธิ์ (networksecurity.authzPolicies) ที่ผสานรวมกับนโยบายการเข้าถึงแบบรวม (UAP) ของ Identity-Aware Proxy (IAP v2)

ภาพรวมสถาปัตยกรรมการให้สิทธิ์

figure4

รูปที่ 4 ภาพรวมสถาปัตยกรรมการให้สิทธิ์

สถาปัตยกรรมการให้สิทธิ์ประกอบด้วย 3 เลเยอร์ที่เชื่อมต่อกัน ดังนี้

  1. ส่วนขยายบริการ IAP (authzExtension): ทรัพยากรระดับภูมิภาคที่กำหนดค่าด้วย service: iap.googleapis.com, metadata: iapPolicyVersion: "V2" และ failOpen: false เพื่อบังคับใช้ Zero Trust ที่เข้มงวด
  2. นโยบายการให้สิทธิ์ของเกตเวย์ (authzPolicy): ทรัพยากรที่เข้าถึงได้ในภูมิภาคที่กำหนดเป้าหมายไปยัง Agent Gateway ด้วย policyProfile: REQUEST_AUTHZ และ action: CUSTOM ซึ่งจะกำหนดเส้นทางการตรวจสอบการให้สิทธิ์ไปยังส่วนขยาย Authz ของ IAP
  3. นโยบายการเข้าถึงและการเชื่อมโยงแบบรวมของ IAM (accessPolicy และ policyBinding): ทรัพยากร IAM v3 ทั่วโลกที่ IAP ประเมิน โดยจะยืนยันสิทธิ์สากล iap.googleapis.com/resources.egressViaIAP กับข้อมูลประจำตัว SPIFFE ของผู้โทรและเงื่อนไขแคตตาล็อก CEL

ขั้นตอนที่ 1: สร้างและนำเข้าส่วนขยายการให้สิทธิ์ IAP v2

สร้างไฟล์ Manifest ของส่วนขยายบริการด้วย iapPolicyVersion: "V2" และ failOpen: false ในโหมด ENFORCE ที่เข้มงวด

# create authz extension config file in ENFORCE mode
cat > cfg/${AGW_NAME}-svc-ext-authz-iap.yaml << EOF
name: ${AGW_NAME}-svc-ext-authz-iap
service: iap.googleapis.com
failOpen: false
timeout: 1s
metadata:
  iapPolicyVersion: "V2"
EOF

นำเข้าส่วนขยาย Authz

# import IAP v2 authz extension
gcloud service-extensions authz-extensions import ${AGW_NAME}-svc-ext-authz-iap \
  --source=cfg/${AGW_NAME}-svc-ext-authz-iap.yaml \
  --location=${REGION} \
  --project=${PROJECT_GOVERNANCE}

ตรวจสอบว่าส่วนขยาย Authz ทำงานอยู่

# describe authz extension
gcloud service-extensions authz-extensions describe ${AGW_NAME}-svc-ext-authz-iap \
  --location=${REGION} \
  --project=${PROJECT_GOVERNANCE}

เอาต์พุตตัวอย่าง

createTime: 'YYYY-MM-DDT12:34:56.789098765Z'
failOpen: false
metadata:
  iapPolicyVersion: V2
name: projects/${PROJECT_GOVERNANCE}/locations/us-central1/authzExtensions/centralized-agw-svc-ext-authz-iap
service: iap.googleapis.com
timeout: 1s

ขั้นตอนที่ 2: สร้างและนำเข้านโยบายการให้สิทธิ์เกตเวย์

สร้างการกำหนดค่านโยบายการให้สิทธิ์ที่แนบกับ Agent Gateway และมอบสิทธิ์การยืนยันคำขอให้กับส่วนขยาย Authz ของ IAP โดยทำดังนี้

# create authz policy manifest
cat > cfg/${AGW_NAME}-authz-policy-profile-iap.yaml << EOF
name: ${AGW_NAME}-authz-policy-profile-iap
target:
  resources:
    - "projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agentGateways/${AGW_NAME}"
policyProfile: REQUEST_AUTHZ
action: CUSTOM
customProvider:
  authzExtension:
    resources:
      - "projects/${PROJECT_GOVERNANCE}/locations/${REGION}/authzExtensions/${AGW_NAME}-svc-ext-authz-iap"
EOF

นำเข้านโยบายการให้สิทธิ์

# import authz policy
gcloud beta network-security authz-policies import ${AGW_NAME}-authz-policy-profile-iap \
  --source=cfg/${AGW_NAME}-authz-policy-profile-iap.yaml \
  --location=${REGION} \
  --project=${PROJECT_GOVERNANCE}

ตรวจสอบนโยบายการให้สิทธิ์ที่ใช้งานอยู่

# describe authz policy
gcloud beta network-security authz-policies describe ${AGW_NAME}-authz-policy-profile-iap \
  --location=${REGION} \
  --project=${PROJECT_GOVERNANCE}

ขั้นตอนที่ 3: สร้างนโยบายการเข้าถึงแบบรวมเริ่มต้น (กฎที่ 1: Google API หลัก)

สร้าง cfg/uap-rules.json โดยมีกฎ 1 ที่ให้สิทธิ์โปรเจ็กต์ 3 รายการ principalSet ในการเข้าถึง core-gapi-services ดังนี้

# create initial unified access policy rules manifest
cat > cfg/uap-rules.json << EOF
[
  {
    "description": "Rule 1: Allow agent runtimes across all 3 projects to reach Core Google APIs",
    "effect": "ALLOW",
    "principals": [
      "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_GOVERNANCE}",
      "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}",
      "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_SELLERS}"
    ],
    "operation": {
      "permissions": [
        "iap.googleapis.com/resources.egressViaIAP"
      ]
    },
    "conditions": {
      "iap.googleapis.com": {
        "expression": \
        "destination.is_registered == true && \
         destination.agent_registry.resource_type == 'ENDPOINT' && ( \
         destination.agent_registry.endpoint.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/endpoints/core-gapi-services' || \
         destination.agent_registry.endpoint.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/endpoints/${ENDPOINT_ID}' || \
         destination.agent_registry.endpoint.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/${REGION}/endpoints/${ENDPOINT_ID}')"
      }
    }
  }
]
EOF

ขั้นตอนที่ 4: สร้างและเชื่อมโยงนโยบายการเข้าถึง IAM

สร้างนโยบายการเข้าถึง IAM ทั่วโลก

# create global IAM access policy
gcloud iam access-policies create ${UAP_POLICY_NAME} \
  --details-rules=cfg/uap-rules.json \
  --project=${PROJECT_GOVERNANCE} \
  --location=global

เชื่อมโยงนโยบายการเข้าถึงกับ PROJECT_GOVERNANCE โดยทำดังนี้

# bind access policy to governance project
gcloud iam policy-bindings create ${UAP_BINDING_NAME} \
  --policy="projects/${PROJECT_GOVERNANCE}/locations/global/accessPolicies/${UAP_POLICY_NAME}" \
  --target-resource="//cloudresourcemanager.googleapis.com/projects/${PROJECT_GOVERNANCE}" \
  --project=${PROJECT_GOVERNANCE} \
  --location=global

ตรวจสอบว่าการเชื่อมโยงนโยบายใช้งานอยู่โดยทำดังนี้

# verify policy binding
gcloud iam policy-bindings describe ${UAP_BINDING_NAME} \
  --project=${PROJECT_GOVERNANCE} \
  --location=global

เอาต์พุตตัวอย่าง

name: projects/${PROJECT_GOVERNANCE}/locations/global/policyBindings/uap-binding-centralized-agw
policy: projects/${PROJECT_GOVERNANCE}/locations/global/accessPolicies/uap-policy-centralized-agw
policyKind: ACCESS_POLICY
target:
  resource: //cloudresourcemanager.googleapis.com/projects/${PROJECT_GOVERNANCE}

ตอนนี้การออกของ Google Cloud API พื้นฐานได้รับอนุญาตอย่างปลอดภัยในทั้ง 3 โปรเจ็กต์ในโหมด ENFORCE ที่เข้มงวด

การตั้งค่าการให้สิทธิ์เกตเวย์เสร็จสมบูรณ์แล้ว... ไปที่ส่วนกำหนดค่าสิทธิ์ IAM ข้ามโปรเจ็กต์กันต่อ

6. IAM ข้ามโปรเจ็กต์

กำหนดค่าสิทธิ์ IAM ข้ามโปรเจ็กต์

ในโทโพโลยีแบบหลายโปรเจ็กต์นี้ Agent Runtime จะอยู่ในโปรเจ็กต์ Spoke (PROJECT_CONCIERGE และ PROJECT_SELLERS) ส่วน Central Agent Gateway และ Agent Registry จะอยู่ใน PROJECT_GOVERNANCE

เนื่องจากโปรเจ็กต์ Google Cloud เป็นขอบเขตการรักษาความปลอดภัยที่แยกกัน การเข้าถึงข้ามโปรเจ็กต์จึงต้องได้รับอนุญาตอย่างชัดเจนใน 2 ชั้นการทำงาน ดังนี้

  1. Control Plane (เวลาในการติดตั้งใช้งาน): เมื่อติดตั้งใช้งานคอนเทนเนอร์ของเอเจนต์ที่กำหนดค่าด้วย --agent-gateway-config Agent Runtime Service Agent (service-@gcp-sa-aiplatform.iam.gserviceaccount.com) ของโปรเจ็กต์ Spoke ต้องแนบคอนเทนเนอร์กับเกตเวย์ส่วนกลาง เราสร้างบทบาทที่กำหนดเองขั้นต่ำ (ar_agw_cross_project_sa) ที่ให้สิทธิ์ networkservices.agentGateways.use, get และ operations.get ใน PROJECT_GOVERNANCE
  2. Data Plane (การดำเนินการรันไทม์):
    • การค้นพบแคตตาล็อก: ข้อมูลประจำตัวของ Spoke ต้องมี roles/agentregistry.viewer ใน PROJECT_GOVERNANCE เพื่อแก้ไขปลายทางของเอเจนต์เป้าหมายแบบไดนามิก
    • การเรียกใช้เป้าหมาย: เอเจนต์ Concierge ต้องมี roles/aiplatform.user ใน PROJECT_SELLERS เพื่อเรียกใช้การค้นหาเทียบกับเครื่องมือให้เหตุผลของผู้ขาย

สร้างบทบาท IAM ที่กำหนดเองใน PROJECT_GOVERNANCE

# create custom role in central governance project
gcloud iam roles create ar_agw_cross_project_sa \
  --project=${PROJECT_GOVERNANCE} \
  --title="Runtime Agent Gateway Cross-Project SA" \
  --description="Custom role for cross-project service agents to access Central Agent Gateway" \
  --permissions="networkservices.agentGateways.get,networkservices.agentGateways.use,networkservices.operations.get" \
  --stage="GA"

มอบหมายบทบาทที่กำหนดเองให้กับตัวแทนบริการ Agent Runtime

# 1. ensure aiplatform service identities are provisioned across all projects
for PROJ in ${PROJECT_GOVERNANCE} ${PROJECT_CONCIERGE} ${PROJECT_SELLERS}; do
  gcloud beta services identity create --service=aiplatform.googleapis.com --project=${PROJ}
done
# 2. derive aiplatform service agent emails
export CONCIERGE_AI_SA="service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform.iam.gserviceaccount.com"
export CONCIERGE_RE_SA="service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
export CONCIERGE_COMPUTE_SA="${PROJECT_NUMBER_CONCIERGE}-compute@developer.gserviceaccount.com"

export SELLERS_AI_SA="service-${PROJECT_NUMBER_SELLERS}@gcp-sa-aiplatform.iam.gserviceaccount.com"
export SELLERS_RE_SA="service-${PROJECT_NUMBER_SELLERS}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
export SELLERS_COMPUTE_SA="${PROJECT_NUMBER_SELLERS}-compute@developer.gserviceaccount.com"
# 3. grant custom role & network viewer to Concierge and Sellers Service Agents
for SA in ${CONCIERGE_AI_SA} ${SELLERS_AI_SA}; do
  gcloud projects add-iam-policy-binding ${PROJECT_GOVERNANCE} \
    --member="serviceAccount:${SA}" \
    --role="projects/${PROJECT_GOVERNANCE}/roles/ar_agw_cross_project_sa" \
    --condition=None

  gcloud projects add-iam-policy-binding ${PROJECT_GOVERNANCE} \
    --member="serviceAccount:${SA}" \
    --role="roles/networkservices.viewer" \
    --condition=None
done
# 4. grant agent registry viewer on Governance Project for dynamic autodiscovery
for MEMBER in "serviceAccount:${CONCIERGE_AI_SA}" "serviceAccount:${CONCIERGE_RE_SA}" "serviceAccount:${CONCIERGE_COMPUTE_SA}" "serviceAccount:${SELLERS_AI_SA}" "serviceAccount:${SELLERS_RE_SA}" "serviceAccount:${SELLERS_COMPUTE_SA}" "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}" "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_SELLERS}"; do
  gcloud projects add-iam-policy-binding ${PROJECT_GOVERNANCE} \
    --member="${MEMBER}" \
    --role="roles/agentregistry.viewer" \
    --condition=None
done
# 5. grant agent project viewer on Governance Project for dynamic autodiscovery
for SA in ${CONCIERGE_COMPUTE_SA} ${CONCIERGE_AI_SA}; do
  gcloud projects add-iam-policy-binding ${PROJECT_GOVERNANCE} \
    --member="serviceAccount:${SA}" \
    --role="roles/viewer" \
    --condition=None
done
# 6. grant aitplatform user on Sellers project to Concierge for cross-project A2A invocation
for MEMBER in "serviceAccount:${CONCIERGE_AI_SA}" "serviceAccount:${CONCIERGE_RE_SA}" "serviceAccount:${CONCIERGE_COMPUTE_SA}" "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}"; do
  gcloud projects add-iam-policy-binding ${PROJECT_SELLERS} \
    --member="${MEMBER}" \
    --role="roles/aiplatform.user" \
    --condition=None
done

การตั้งค่า IAM ข้ามโปรเจ็กต์ก็มีเพียงเท่านี้... ต่อไปคือส่วนการติดตั้งใช้งานเอเจนต์ผู้ขายและเอเจนต์อำนวยความสะดวก

7. รันไทม์ของ Agent

ติดตั้งใช้งาน Seller Agent และ Concierge Agent

เราดูแลรักษาฐานของโค้ดของแอปพลิเคชันแบบหลาย Agent และสคริปต์การทำให้ใช้งานได้ที่ใช้สำหรับ Codelab นี้ไว้ในที่เก็บ Google Cloud GitHub ระยะไกล ขั้นตอนต่อไปนี้จะโคลนที่เก็บในเครื่อง คัดลอกไฟล์ที่จำเป็นไปยังโครงสร้างไดเรกทอรีการทำงานปัจจุบัน ล้างไฟล์ชั่วคราว และติดตั้งทรัพยากร Dependency ด้วย uv

ดึงข้อมูลอาร์ติแฟกต์ระยะไกล

# clone remote repository to temp local dir
git clone https://github.com/GoogleCloudPlatform/cloud-networking-solutions.git ./temp_agw_cuj_arun_multiproject
# copy multi-agent application files to current working directory
cp -r temp_agw_cuj_arun_multiproject/codelabs/agw-cuj-arun-multiproject ./cross-project-multiagent
# remove temporary directory
rm -rf temp_agw_cuj_arun_multiproject
# install dependencies
uv sync --directory ./cross-project-multiagent

สร้างที่เก็บข้อมูลกลางที่ใช้ร่วมกัน

# create shared central staging bucket
gcloud storage buckets create gs://${PROJECT_GOVERNANCE}-shared-staging \
  --project=${PROJECT_GOVERNANCE} \
  --location=${REGION}
# grant cross-project read/write access to runtime service agents
gcloud storage buckets add-iam-policy-binding gs://${PROJECT_GOVERNANCE}-shared-staging \
  --member="serviceAccount:service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform.iam.gserviceaccount.com" \
  --role="roles/storage.objectAdmin"

gcloud storage buckets add-iam-policy-binding gs://${PROJECT_GOVERNANCE}-shared-staging \
  --member="serviceAccount:service-${PROJECT_NUMBER_SELLERS}@gcp-sa-aiplatform.iam.gserviceaccount.com" \
  --role="roles/storage.objectAdmin"

วิธีการทำงานของการเชื่อมโยงเกตเวย์ของเอเจนต์ข้ามโปรเจ็กต์

ในขั้นตอนนี้ คุณจะติดตั้งใช้งาน Seller Agent ในโปรเจ็กต์ Spoke (PROJECT_SELLERS) ขณะกำหนดค่าให้กำหนดเส้นทางการออกผ่าน Central Agent Gateway ใน PROJECT_GOVERNANCE ดังนี้

# !-- for example purposes -- NOT a command to execute --!
# snippet from deploy_burger.py
burger_config = {
    "staging_bucket": staging_bucket_uri,
    "gcs_dir_name": "burger_agent",
    "display_name": "burger-seller-agent-adk",
    "identity_type": "AGENT_IDENTITY",
    "agent_gateway_config": {
        "agent_to_anywhere_config": {
            "agent_gateway": f"projects/{args.governance_project}/locations/{args.region}/agentGateways/{args.gateway}"
        }
    },
}
deployed_burger = client.agent_engines.create(agent=burger_playground, config=burger_config)

เนื่องจากกฎข้อที่ 1 ได้รับการกำหนดไว้ก่อนหน้านี้ในนโยบายการเข้าถึงแบบรวมของเรา คำขอการเริ่มต้นคอนเทนเนอร์ไปยัง Google Cloud API จึงได้รับอนุญาตผ่านเกตเวย์โดยไม่มีการหยุดชะงัก

ติดตั้งใช้งานเอเจนต์ผู้ขายเบอร์เกอร์และพิซซ่าใน PROJECT_SELLERS

# 1. deploy Burger Seller Agent to PROJECT_SELLERS
uv run --directory ./cross-project-multiagent python deploy_burger.py \
  --project=${PROJECT_SELLERS} \
  --region=${REGION} \
  --governance-project=${PROJECT_GOVERNANCE} \
  --gateway=projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agentGateways/${AGW_NAME}
# 2. deploy Pizza Seller Agent to PROJECT_SELLERS
uv run --directory ./cross-project-multiagent python deploy_pizza.py \
  --project=${PROJECT_SELLERS} \
  --region=${REGION} \
  --governance-project=${PROJECT_GOVERNANCE} \
  --gateway=projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agentGateways/${AGW_NAME}

ตรวจสอบการกำหนดเส้นทางเกตเวย์ของผู้ขาย

# retrieve deployed seller reasoning engine IDs
export BURGER_ENGINE_ID=$(grep BURGER_SELLER_AGENT_ID cross-project-multiagent/burger_agent.env | awk -F'/' '{print $NF}')
export PIZZA_ENGINE_ID=$(grep PIZZA_SELLER_AGENT_ID cross-project-multiagent/pizza_agent.env | awk -F'/' '{print $NF}')

echo "Burger Engine ID: ${BURGER_ENGINE_ID}"
echo "Pizza Engine ID:  ${PIZZA_ENGINE_ID}"
# inspect runtime configuration for both Seller Agents
for ENGINE_ID in ${BURGER_ENGINE_ID} ${PIZZA_ENGINE_ID}; do
  curl -s -X GET "https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_SELLERS}/locations/${REGION}/reasoningEngines/${ENGINE_ID}" \
    -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type: application/json" \
    | jq '{displayName: .displayName, identityType: .spec.identityType, effectiveIdentity: .spec.effectiveIdentity, agentGatewayConfig: .spec.deploymentSpec.agentGatewayConfig}'
done

ติดตั้งใช้งาน Agent ของเจ้าหน้าที่บริการด้านการซื้อใน PROJECT_CONCIERGE

# deploy Purchasing Concierge to PROJECT_CONCIERGE
uv run --directory ./cross-project-multiagent python deploy_concierge_adk.py \
  --project=${PROJECT_CONCIERGE} \
  --region=${REGION} \
  --staging-bucket=gs://${PROJECT_GOVERNANCE}-shared-staging \
  --gateway-name=${AGW_NAME} \
  --gateway-project=${PROJECT_GOVERNANCE}

ตรวจสอบการกำหนดเส้นทางการชำระเงิน

# retrieve Concierge engine ID
export CONCIERGE_ENGINE_ID=$(grep CONCIERGE_AGENT_ID cross-project-multiagent/concierge_agent.env | awk -F'/' '{print $NF}')
echo "Concierge Engine ID: ${CONCIERGE_ENGINE_ID}"
# inspect runtime configuration for Purchasing Concierge
curl -s -X GET "https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  | jq '{displayName: .displayName, identityType: .spec.identityType, effectiveIdentity: .spec.effectiveIdentity, agentGatewayConfig: .spec.deploymentSpec.agentGatewayConfig}'

เอาต์พุตควรแสดงข้อมูลประจำตัวของรันไทม์ของตัวแทน Concierge และโปรเจ็กต์ รวมถึงการเชื่อมโยงกับ Agent Gateway ของโปรเจ็กต์การกำกับดูแล

{
  "displayName": "purchasing-concierge-adk",
  "identityType": "AGENT_IDENTITY",
  "effectiveIdentity": "agents.global.org-${ORG_ID}.system.id.goog/resources/aiplatform/projects/${PROJECT_CONCIERGE}/locations/us-central1/reasoningEngines/${CONCIERGE_ENGINE_ID}",
  "agentGatewayConfig": {
    "agentToAnywhereConfig": {
      "agentGateway": "projects/${PROJECT_GOVERNANCE}/locations/us-central1/agentGateways/centralized-agw"
    }
  }
}

การติดตั้งใช้งาน Agent ก็มีเพียงเท่านี้... ต่อไปเราจะไปที่ส่วนลงทะเบียน Agent ใน Central Agent Registry

8. รีจิสทรีข้ามโปรเจ็กต์

ลงทะเบียน Agent ใน Central Agent Registry

ลงทะเบียน Agent ทั้ง 3 รายใน Central Agent Registry ใน PROJECT_GOVERNANCE โดยใช้ปลายทาง mTLS ระดับภูมิภาคแบบข้ามโปรเจ็กต์และหมายเลขโปรเจ็กต์ที่เป็นตัวเลข

ลงทะเบียนบริการเป็นเอเจนต์ที่ไม่ใช่ A2A ใน Agent Registry

# 1. register Burger Seller Agent
gcloud agent-registry services create burger-seller-agent \
  --project=${PROJECT_GOVERNANCE} \
  --location=${REGION} \
  --display-name="Burger Seller Agent" \
  --description="Specialist agent that sells burgers and fries" \
  --agent-spec-type=no-spec \
  --interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${BURGER_ENGINE_ID}:query \
  --interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${BURGER_ENGINE_ID}:query
# 2. register Pizza Seller Agent
gcloud agent-registry services create pizza-seller-agent \
  --project=${PROJECT_GOVERNANCE} \
  --location=${REGION} \
  --display-name="Pizza Seller Agent" \
  --description="Specialist agent that sells pizzas and pasta" \
  --agent-spec-type=no-spec \
  --interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${PIZZA_ENGINE_ID}:query \
  --interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${PIZZA_ENGINE_ID}:query
# 3. register Purchasing Concierge Agent
gcloud agent-registry services create purchasing-concierge-adk \
  --project=${PROJECT_GOVERNANCE} \
  --location=${REGION} \
  --display-name="Purchasing Concierge Agent" \
  --description="Orchestrator concierge agent that routes purchasing requests" \
  --agent-spec-type=no-spec \
  --interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}:query \
  --interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}:query

บันทึกรหัสรีจิสทรีของตัวแทนพื้นฐาน

# capture underlying Agent Registry Agent UUIDs
export BURGER_AGENT_ID=$(gcloud agent-registry services describe burger-seller-agent --project=${PROJECT_GOVERNANCE} --location=${REGION} --format="value(registryResource)" | awk -F'/' '{print $NF}')
export PIZZA_AGENT_ID=$(gcloud agent-registry services describe pizza-seller-agent --project=${PROJECT_GOVERNANCE} --location=${REGION} --format="value(registryResource)" | awk -F'/' '{print $NF}')
export CONCIERGE_AGENT_ID=$(gcloud agent-registry services describe purchasing-concierge-adk --project=${PROJECT_GOVERNANCE} --location=${REGION} --format="value(registryResource)" | awk -F'/' '{print $NF}')

echo "Burger Agent ID:    ${BURGER_AGENT_ID}"
echo "Pizza Agent ID:     ${PIZZA_AGENT_ID}"
echo "Concierge Agent ID: ${CONCIERGE_AGENT_ID}"

การกำหนดค่ารีจิสทรีเสร็จสมบูรณ์แล้ว... ไปที่ส่วนกำหนดค่านโยบายขาออก A2A กันต่อ

9. นโยบาย UAP

กำหนดค่านโยบายขาออก A2A ในนโยบายการเข้าถึงแบบรวม

ภายใต้สถาปัตยกรรม Default Deny ของ Agent Gateway ในโหมด ENFORCE ที่เข้มงวด

  1. กฎ 1 (Google Cloud APIs พื้นฐาน): อนุญาตให้คอนเทนเนอร์ของเอเจนต์ในทั้ง 3 โปรเจ็กต์เข้าถึง core-gapi-services
  2. กฎ 2 (เอเจนต์ผู้ขายเบอร์เกอร์: อนุญาต): อนุญาตให้อินสแตนซ์เอเจนต์บริการด้านการซื้อเรียกใช้เอเจนต์ผู้ขายเบอร์เกอร์โดยเฉพาะ
  3. Pizza Seller Agent (ปฏิเสธโดยค่าเริ่มต้น): ไม่ได้รวมไว้ในกฎนโยบายโดยเจตนา ในENFORCEโหมด (failOpen: false) ความพยายามใดๆ ของ Concierge ในการเรียกใช้ผู้ขายพิซซ่าจะสิ้นสุดลงทันทีที่ขอบเขตเกตเวย์ด้วย HTTP 403 Forbidden

กำหนดตัวตนของตัวแทน Concierge

# formulate the exact SPIFFE machine identity for the Concierge Agent
export CONCIERGE_SPIFFE_PRINCIPAL="principal://agents.global.org-${ORG_ID}.system.id.goog/resources/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}"
echo "Concierge SPIFFE Principal: ${CONCIERGE_SPIFFE_PRINCIPAL}"

อัปเดตไฟล์ Manifest ด้วยกฎ 1 และ 2

สร้าง cfg/uap-rules-update-2.json ใหม่เพื่อรวม กฎ 1 (Core API) และตอนนี้ กฎ 2 (ตัวแทนผู้ขายเบอร์เกอร์)

# create addendum to update policy manifest with Rule 2 for Burger Agent
cat > cfg/uap-rules-update-2.json << EOF
[
  {
    "description": "Rule 2: Allow Purchasing Concierge to invoke Burger Seller Agent via Central Gateway",
    "effect": "ALLOW",
    "principals": [
      "${CONCIERGE_SPIFFE_PRINCIPAL}"
    ],
    "operation": {
      "permissions": [
        "iap.googleapis.com/resources.egressViaIAP"
      ]
    },
    "conditions": {
      "iap.googleapis.com": {
        "expression": \
        "destination.is_registered == true && \
         destination.agent_registry.resource_type == 'AGENT' && ( \
         destination.agent_registry.agent.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agents/burger-seller-agent' || \
         destination.agent_registry.agent.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agents/${BURGER_AGENT_ID}' || \
         destination.agent_registry.agent.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/${REGION}/agents/${BURGER_AGENT_ID}')"
      }
    }
  }
]
EOF

ใช้นโยบายการเข้าถึงที่ปรับปรุงแล้ว

# update IAM access policy with Burger rule
gcloud iam access-policies update ${UAP_POLICY_NAME} \
  --add-details-rules=cfg/uap-rules-update-2.json \
  --project=${PROJECT_GOVERNANCE} \
  --location=global

ยืนยันรายละเอียดนโยบายการเข้าถึง IAM

# inspect updated access policy
gcloud iam access-policies describe ${UAP_POLICY_NAME} \
  --project=${PROJECT_GOVERNANCE} \
  --location=global

เอาต์พุตตัวอย่าง

details:
  rules:
  - conditions:
      iap.googleapis.com:
        expression: destination.is_registered == true && destination.agent_registry.resource_type
          == 'ENDPOINT' && (destination.agent_registry.endpoint.name == 'projects/${PROJECT_GOVERNANCE}/locations/us-central1/endpoints/core-gapi-services'
          || destination.agent_registry.endpoint.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/us-central1/endpoints/${ENDPOINT_ID}')
    description: 'Rule 1: Allow agent runtimes across all 3 projects to reach Core
      Google APIs'
    effect: ALLOW
    operation:
      permissions:
      - iap.googleapis.com/resources.egressViaIAP
    principals:
    - principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_GOVERNANCE}
    - principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}
    - principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_SELLERS}
  - conditions:
      iap.googleapis.com:
        expression: (destination.is_registered == true) && (destination.agent_registry.resource_type
          == 'AGENT') && (destination.agent_registry.agent.name == 'projects/${PROJECT_GOVERNANCE}/locations/us-central1/agents/burger-seller-agent'
          || destination.agent_registry.agent.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/us-central1/agents/${BURGER_AGENT_ID}')
    description: 'Rule 2: Allow Purchasing Concierge to invoke Burger Seller Agent
      via Central Gateway'
    effect: ALLOW
    operation:
      permissions:
      - iap.googleapis.com/resources.egressViaIAP
    principals:
    - principal://agents.global.org-${ORG_ID}.system.id.goog/resources/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}/locations/us-central1/reasoningEngines/${CONCIERGE_ENGINE_ID}
name: projects/${PROJECT_GOVERNANCE}/locations/global/accessPolicies/uap-policy-centralized-agw

การตั้งค่านโยบายเสร็จสิ้นแล้ว... ไปที่ส่วนทดสอบและยืนยันนโยบายการกำกับดูแลกันต่อ

10. ยืนยันนโยบาย

ทดสอบและยืนยันนโยบายการกำกับดูแลผ่าน Cloud Logging

ในส่วนนี้ คุณจะได้ทดสอบการโต้ตอบแบบเอเจนต์ต่อเอเจนต์ (A2A) ข้ามโปรเจ็กต์ใน AI Playground ของ Agent Runtime สังเกตการHTTP 403 Forbiddenบล็อกขอบเขตจริงในโหมดENFORCEเข้มงวด แก้ไขนโยบายการเข้าถึงแบบรวมแบบเรียลไทม์ และตรวจสอบการอนุมัติคำสั่งซื้อทันที

ขั้นตอนที่ 1: เปิด Agent Runtime AI Playground ใน PROJECT_CONCIERGE

  1. เปิด คอนโซล Google Cloud
  2. ในแถบตัวเลือกโปรเจ็กต์ด้านบน ให้เปลี่ยนไปใช้ PROJECT_CONCIERGE
  3. ในเมนูการนำทาง ให้ไปที่แพลตฟอร์มเอเจนต์ > เอเจนต์ > การติดตั้งใช้งาน
  4. คลิก purchasing-concierge-adk
  5. เลือก Playground เพื่อเปิดอินเทอร์เฟซแชทแบบอินเทอร์แอกทีฟทางด้านขวาของหน้าจอ

ขั้นตอนที่ 2: ทดสอบคำสั่งซื้อเบอร์เกอร์ (กฎ 2 ตรงกัน -> 200 OK)

ในหน้าต่างแชทของ Playground ให้ส่งพรอมต์คำสั่งต่อไปนี้

I would like 10 Classic Cheeseburgers. Place this order now.

และหากจำเป็นต้องมีการตอบกลับเพื่อยืนยัน ให้ส่งการตอบกลับต่อไปนี้

Confirmed, please place the order.

หรือจะทดสอบแบบเป็นโปรแกรมจาก Cloud Shell / เทอร์มินัลก็ได้ โดยทำดังนี้

uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input={'message': 'I would like 22 Spicy Cajun Burgers please. Place this order now.'})
print(response)
"

และหากต้องการการตอบกลับเพื่อยืนยัน ให้ใช้คำสั่งนี้

uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input='Yes please place the order now.')
print(response['text'])
"

สิ่งที่เกิดขึ้นเบื้องหลัง

  1. การค้นพบแบบไดนามิก: ในระหว่างการเริ่มต้นเซสชัน ผู้ช่วยการซื้อจะค้นหา Central Agent Registry ใน PROJECT_GOVERNANCE (ผ่าน core-gapi-services ผ่าน Agent Gateway ที่ได้รับอนุญาตตามกฎข้อ 1) เพื่อค้นหาปลายทาง mTLS ระดับภูมิภาคสำหรับ burger-seller-agent
  2. การแก้ปัญหาความตั้งใจและการเรียกใช้ A2A: Gemini ในเจ้าหน้าที่บริการด้านการซื้อจะแยกวิเคราะห์ความตั้งใจในการสั่งอาหารและเรียกใช้ตัวแทนผู้ขายเบอร์เกอร์ผ่าน RPC ขาออกไปยัง https://${REGION}-aiplatform.mtls.googleapis.com/.../reasoningEngines/${BURGER_ENGINE_ID}
  3. การสกัดกั้นเกตเวย์และการเผยแพร่ SPIFFE: agent_gateway_config จะจับการรับส่งข้อมูลขาออกและนำไปยัง Central Agent Gateway ใน PROJECT_GOVERNANCE โดยมีข้อมูลประจำตัว SPIFFE ที่เข้ารหัสของ Concierge (principal://...)
  4. การประเมินนโยบาย IAP v2: Central Agent Gateway เรียกใช้ส่วนขยายการให้สิทธิ์ IAP (authzExtension) IAP v2 ประเมินกฎ 2 ในนโยบายการเข้าถึงแบบรวมของ IAM เนื่องจากผู้โทรตรงกับ ${CONCIERGE_SPIFFE_PRINCIPAL} และเป้าหมายตรงกับ burger-seller-agent IAP จึงแสดงผล ALLOW (granted: true)
  5. การดำเนินการข้ามโปรเจ็กต์: Agent Gateway จะพร็อกซีคำขอที่ได้รับอนุญาตข้ามโปรเจ็กต์ไปยัง PROJECT_SELLERS ซึ่งเป็นที่ที่เครื่องมือให้เหตุผลของผู้ขายเบอร์เกอร์จะประมวลผลคำสั่งซื้อและส่งการยืนยันกลับ

การตอบกลับที่คาดหวัง

Your order for 10 Classic Cheeseburger(s) has been placed!
Here is a summary of your order:
- 10x Classic Cheeseburger @ IDR 85,000/each = IDR 850,000

Total: IDR 850,000
Your Order ID is: e8f9c732-f347-4cc4-acff-cfe09ccbeddd

ขั้นตอนที่ 3: ตรวจสอบบันทึกการตรวจสอบของ Agent Gateway และ IAP v2 (HTTP 200 / อนุญาต)

บันทึกคำขอของ Agent Gateway ใน PROJECT_GOVERNANCE

# query Agent Gateway logs for successful 200 OK requests
gcloud logging read "
  logName=\"projects/${PROJECT_GOVERNANCE}/logs/networkservices.googleapis.com%2Fgateway_requests\"
  AND jsonPayload.authzPolicyInfo.result=\"ALLOWED\"
" \
  --project="${PROJECT_GOVERNANCE}" \
  --limit=10 \
  --format="table(
    timestamp.date('%H:%M:%S'):label=TIME,
    httpRequest.requestMethod:label=METHOD,
    httpRequest.status:label=STATUS,
    jsonPayload.authzPolicyInfo.result:label=AUTHZ,
    httpRequest.requestUrl:label=URL
  )"

บันทึกควรบันทึกการรับส่งขาออกที่มาจากทั้งโปรเจ็กต์ Spoke (PROJECT_CONCIERGE และ PROJECT_SELLERS) โดยมีฟิลด์ขาออกสำหรับการเรียกใช้การให้เหตุผลของ Gemini (generateContent), การวัดและส่งข้อมูลทางไกลของ Cloud Trace (/v1/traces) และการค้นหาข้อมูลเข้าสู่ระบบ IAM ซึ่งจะได้รับการสกัดกั้นและให้สิทธิ์อย่างโปร่งใสโดยกฎข้อที่ 1 (core-gapi-services)

เรียกใช้การค้นหาบันทึกการเข้าถึงข้อมูล Cloud Audit ของ IAP v2 เพื่อยืนยันเวอร์ชันนโยบาย POLICY_VERSION_V2

# query IAP v2 audit logs with shortened principal and resource fields
gcloud logging read "
  logName=\"projects/${PROJECT_GOVERNANCE}/logs/cloudaudit.googleapis.com%2Fdata_access\"
  AND protoPayload.serviceName=\"iap.googleapis.com\"
" \
  --project="${PROJECT_GOVERNANCE}" \
  --limit=5 \
  --format="table(
    timestamp.date('%H:%M:%S'):label=TIME,
    protoPayload.authenticationInfo.principalSubject.sub('\.global\..*\/reasoningEngines\/', '.[...]/reasoningEngines/'):label=CALLER,
    protoPayload.authorizationInfo[0].granted:label=GRANTED,
    protoPayload.metadata.destination.agent_registry.resource_type.basename():label=TYPE,
    protoPayload.metadata.destination.agent_registry.resource_id.basename():label=RESOURCE_ID,
    protoPayload.authorizationInfo[0].permission.basename():label=PERMISSION
  )"

ตัวอย่างเอาต์พุต

TIME      CALLER                                                            GRANTED  TYPE      RESOURCE_ID     PERMISSION
HH:MM:SS  principal://agents.[...]/reasoningEngines/${CONCIERGE_ENGINE_ID}  True     Endpoint  ${ENDPOINT_ID}  resources.egressViaIAP
HH:MM:SS  principal://agents.[...]/reasoningEngines/${BURGER_ENGINE_ID}     True     Endpoint  ${ENDPOINT_ID}  resources.egressViaIAP
HH:MM:SS  principal://agents.[...]/reasoningEngines/${CONCIERGE_ENGINE_ID}  True     Endpoint  ${ENDPOINT_ID}  resources.egressViaIAP
HH:MM:SS  principal://agents.[...]/reasoningEngines/${BURGER_ENGINE_ID}     True     Endpoint  ${ENDPOINT_ID}  resources.egressViaIAP

ขั้นตอนที่ 4: ทดสอบการสั่งพิซซ่า (ปฏิเสธโดยค่าเริ่มต้น -> บังคับใช้ HTTP 403 Forbidden)

ในหน้าต่างแชท Playground เดียวกัน ให้ส่งพรอมต์คำสั่งพิซซ่าต่อไปนี้

I would like 10 BBQ Chicken Pizzas. Place this order now.

และหากจำเป็นต้องมีการตอบกลับเพื่อยืนยัน ให้ส่งการตอบกลับต่อไปนี้

Confirmed, please place the order.

หรือจะทดสอบแบบเป็นโปรแกรมจาก Cloud Shell / เทอร์มินัลก็ได้ โดยทำดังนี้

uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input='I would like 8 Hawaiian pizzas, please. Place this order now.')
print(response)
"

และหากต้องการการตอบกลับเพื่อยืนยัน ให้ใช้คำสั่งนี้

uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input='Yes please place the order now.')
print(response['text'])
"

การตอบกลับที่คาดหวัง

I apologize, but I am unable to process that request at the moment. It seems
there was an issue connecting to the pizza seller agent. Please try again later.

สิ่งที่เกิดขึ้นเบื้องหลัง

  1. การค้นพบแบบไดนามิก: เจ้าหน้าที่บริการด้านการซื้อแก้ไขปลายทาง pizza-seller-agent จากรีจิสทรีเอเจนต์ส่วนกลางในระหว่างการเริ่มต้น
  2. การแก้ปัญหาความตั้งใจและการเรียกใช้ A2A: Gemini ในเจ้าหน้าที่บริการด้านการซื้อพยายามส่งคำขอสั่งพิซซ่าไปยังปลายทางผู้ขายพิซซ่าใน PROJECT_SELLERS
  3. การสกัดกั้นเกตเวย์: agent_gateway_config จะจับ RPC ขาออกและนำไปยังเกตเวย์ของ Central Agent
  4. การประเมินนโยบาย IAP v2 (ปฏิเสธโดยค่าเริ่มต้น): เกตเวย์ของ Central Agent จะเรียกใช้ IAP v2 เนื่องจากไม่มีกฎในนโยบายการเข้าถึงแบบรวมที่ตรงกับ pizza-seller-agent IAP จึงแสดงผล DENY (granted: false)
  5. การบล็อกขอบเขตที่เข้มงวด: เนื่องจากส่วนขยาย Authz อยู่ในโหมด ENFORCE (failOpen: false) เกตเวย์ของ Central Agent จึงสิ้นสุดการเชื่อมต่อขาออกทันทีและแสดง HTTP 403 Forbidden การเข้าชมจะไม่ผ่านเกตเวย์และไม่ถึงPROJECT_SELLERS

ขั้นตอนที่ 5: ตรวจสอบบันทึกเกตเวย์ของตัวแทนสำหรับคำขอที่ถูกบล็อก (HTTP 403 / DENIED)

# query Agent Gateway logs for blocked 403 requests
gcloud logging read "
  logName=\"projects/${PROJECT_GOVERNANCE}/logs/networkservices.googleapis.com%2Fgateway_requests\"
  AND httpRequest.status=403
" \
  --project="${PROJECT_GOVERNANCE}" \
  --limit=5 \
  --format="table(
    timestamp.date('%H:%M:%S'):label=TIME,
    httpRequest.requestMethod:label=METHOD,
    httpRequest.status:label=STATUS,
    jsonPayload.authzPolicyInfo.result:label=AUTHZ,
    httpRequest.requestUrl:label=URL
  )"

ตัวอย่างเอาต์พุตของบันทึกที่ถูกปฏิเสธ

TIME      METHOD  STATUS  AUTHZ   URL
HH:MM:SS  POST    403     DENIED  https://us-central1-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_SELLERS}/locations/us-central1/reasoningEngines/${PIZZA_ENGINE_ID}:query

ค้นหาบันทึกการตรวจสอบการเข้าถึงข้อมูล IAP v2 สำหรับการตัดสินใจที่ถูกปฏิเสธ

# query IAP v2 audit logs with shortened principal and resource fields
gcloud logging read "
  logName=\"projects/${PROJECT_GOVERNANCE}/logs/cloudaudit.googleapis.com%2Fdata_access\"
  AND protoPayload.serviceName=\"iap.googleapis.com\"
" \
  --project="${PROJECT_GOVERNANCE}" \
  --limit=5 \
  --format="table(
    timestamp.date('%H:%M:%S'):label=TIME,
    protoPayload.authenticationInfo.principalSubject.sub('\.global\..*\/reasoningEngines\/', '.[...]/reasoningEngines/'):label=CALLER,
    protoPayload.authorizationInfo[0].granted:label=GRANTED,
    protoPayload.metadata.destination.agent_registry.resource_type.basename():label=TYPE,
    protoPayload.metadata.destination.agent_registry.resource_id.basename():label=RESOURCE_ID,
    protoPayload.authorizationInfo[0].permission.basename():label=PERMISSION
  )"

ตัวอย่างเอาต์พุตบันทึกการตรวจสอบที่ถูกปฏิเสธ

TIME      CALLER                                                            GRANTED  TYPE      RESOURCE_ID     PERMISSION
HH:MM:SS  principal://agents.[...]/reasoningEngines/${PIZZA_ENGINE_ID}      True     Endpoint  ${REGISTRY_ID}  resources.egressViaIAP
HH:MM:SS  principal://agents.[...]/reasoningEngines/${PIZZA_ENGINE_ID}      True     Endpoint  ${REGISTRY_ID}  resources.egressViaIAP
HH:MM:SS  principal://agents.[...]/reasoningEngines/${CONCIERGE_ENGINE_ID}  False    Agent     ${REGISTRY_ID}  resources.egressViaIAP
HH:MM:SS  principal://agents.[...]/reasoningEngines/${PIZZA_ENGINE_ID}      True     Endpoint  ${REGISTRY_ID}  resources.egressViaIAP

ขั้นตอนที่ 6: ให้สิทธิ์การเข้าถึงขาออกแบบไดนามิกแก่ Pizza Agent

สร้าง cfg/uap-rules-update-3.json ใหม่เพื่อรวมกฎข้อที่ 1 (Core API), กฎข้อที่ 2 (ตัวแทนผู้ขายเบอร์เกอร์) และตอนนี้คือกฎข้อที่ 3 (ตัวแทนผู้ขายพิซซ่า)

# create addendum to update policy manifest with Rule 3 for Pizza Agent
cat > cfg/uap-rules-update-3.json << EOF
[
  {
    "description": "Rule 3: Allow Purchasing Concierge to invoke Pizza Seller Agent via Central Gateway",
    "effect": "ALLOW",
    "principals": [
      "${CONCIERGE_SPIFFE_PRINCIPAL}"
    ],
    "operation": {
      "permissions": [
        "iap.googleapis.com/resources.egressViaIAP"
      ]
    },
    "conditions": {
      "iap.googleapis.com": {
        "expression": \
        "destination.is_registered == true && \
         destination.agent_registry.resource_type == 'AGENT' && ( \
         destination.agent_registry.agent.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agents/pizza-seller-agent' || \
         destination.agent_registry.agent.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agents/${PIZZA_AGENT_ID}' || \
         destination.agent_registry.agent.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/${REGION}/agents/${PIZZA_AGENT_ID}')"
      }
    }
  }
]
EOF

ใช้การปรับปรุงนโยบายแบบเรียลไทม์

# update IAM access policy with Pizza rule
gcloud iam access-policies update ${UAP_POLICY_NAME} \
  --add-details-rules=cfg/uap-rules-update-3.json \
  --project=${PROJECT_GOVERNANCE} \
  --location=global

ขั้นตอนที่ 7: ถามตัวแทนพิซซ่าอีกครั้ง (สำเร็จทันทีด้วยรหัส 200 OK)

ในหน้าต่างแชทของ Playground ให้ส่งพรอมต์คำสั่งพิซซ่าอีกครั้งโดยทำดังนี้

I would like 10 BBQ Chicken Pizzas. Place this order now.

และหากจำเป็นต้องมีการตอบกลับเพื่อยืนยัน ให้ส่งการตอบกลับต่อไปนี้

Confirmed, please place the order.

หรือจะทดสอบแบบเป็นโปรแกรมจาก Cloud Shell / เทอร์มินัลก็ได้ โดยทำดังนี้

uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input='I would like 11 Veggie pizzas, please. Place this order now.')
print(response)
"

และหากต้องการการตอบกลับเพื่อยืนยัน ให้ใช้คำสั่งนี้

uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input='Yes please place the order now.')
print(response['text'])
"

การตอบกลับที่คาดหวัง

Your order has been placed!

**Order ID:** 8d6c13d7-31dc-4d80-b6a7-80d1e50b6411

**Order Details:**
*   10 x BBQ Chicken Pizza @ IDR 130,000 each = IDR 1,300,000

**Total: IDR 1,300,000**

สิ่งที่เกิดขึ้นเบื้องหลัง

  1. การรีเฟรชนโยบายแบบไดนามิก: การอัปเดตนโยบายการเข้าถึงแบบรวมของ IAM จะมีผลทันทีในเครื่องมือประเมิน IAP โดยไม่ต้องหยุดทำงานและไม่ต้องติดตั้งใช้งานคอนเทนเนอร์ใหม่
  2. การเรียกใช้ A2A: เจ้าหน้าที่บริการส่งคำขอผ่านเกตเวย์เอเจนต์กลาง
  3. การประเมินนโยบาย IAP เวอร์ชัน 2 (การอนุมัติ): IAP เวอร์ชัน 2 ตรงกับกฎข้อที่ 3, ยืนยันตัวตนผู้โทรและนิพจน์ CEL เป้าหมาย และแสดงผล ALLOW (granted: true)
  4. การดำเนินการข้ามโปรเจ็กต์: Central Agent Gateway จะพร็อกซีการเข้าชมที่ได้รับอนุญาตไปยัง PROJECT_SELLERS ซึ่งผู้ขายพิซซ่าจะประมวลผลคำสั่งซื้อ

ขั้นตอนที่ 8: ตรวจสอบบันทึกเกตเวย์ของตัวแทนสำหรับคำขอพิซซ่าที่ได้รับ

# query Agent Gateway logs for successful 200 OK requests
gcloud logging read "
  logName=\"projects/${PROJECT_GOVERNANCE}/logs/networkservices.googleapis.com%2Fgateway_requests\"
  AND jsonPayload.authzPolicyInfo.result=\"ALLOWED\"
" \
  --project="${PROJECT_GOVERNANCE}" \
  --limit=10 \
  --format="table(
    timestamp.date('%H:%M:%S'):label=TIME,
    httpRequest.requestMethod:label=METHOD,
    httpRequest.status:label=STATUS,
    jsonPayload.authzPolicyInfo.result:label=AUTHZ,
    httpRequest.requestUrl:label=URL
  )"

ตัวอย่างเอาต์พุตของบันทึกที่ได้รับสิทธิ์

TIME      METHOD  STATUS  AUTHZ    URL
HH:MM:SS  POST    200     ALLOWED  https://us-central1-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_SELLERS}/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent
HH:MM:SS  POST    200     ALLOWED  https://us-central1-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_SELLERS}/locations/us-central1/reasoningEngines/${PIZZA_ENGINE_ID}:query

การทดสอบและการยืนยันเสร็จสิ้นแล้ว... ไปที่ส่วนล้างข้อมูลกันต่อ

11. ล้างข้อมูล

โปรดทำตามขั้นตอนการลบออกตามลำดับการอ้างอิงย้อนกลับอย่างเคร่งครัดเพื่อเลี่ยงไม่ให้เกิดการเรียกเก็บเงินกับบัญชี Google Cloud สำหรับทรัพยากรที่ใช้ใน Codelab นี้

1. ล้างข้อมูลการติดตั้งใช้งาน Reasoning Engine

เรียกใช้สคริปต์ cleanup_old_deployments.py ที่รวมไว้ในโปรเจ็กต์รันไทม์ทั้ง 2 รายการเพื่อลบเครื่องมือให้เหตุผลและรอการดำเนินการที่ใช้เวลานาน

# delete all Reasoning Engines deployed in Concierge and Sellers projects
uv run --directory ./cross-project-multiagent python cleanup_old_deployments.py --project=${PROJECT_CONCIERGE} --region=${REGION}
uv run --directory ./cross-project-multiagent python cleanup_old_deployments.py --project=${PROJECT_SELLERS} --region=${REGION}

หรือจะแสดงและลบเครื่องมือให้เหตุผลในบรรทัดก็ได้ โดยทำดังนี้

uv run --directory ./cross-project-multiagent python -c '
import vertexai
import os
from vertexai.preview import reasoning_engines

region = os.environ.get("REGION", "us-central1")
for proj in [os.environ.get("PROJECT_CONCIERGE"), os.environ.get("PROJECT_SELLERS")]:
    if not proj:
        continue
    print(f"Cleaning reasoning engines in {proj}...")
    vertexai.init(project=proj, location=region)
    for eng in reasoning_engines.ReasoningEngine.list():
        print(f"  Deleting {eng.resource_name} ({eng.display_name})...")
        eng.delete()
'

2. ลบบริการรีจิสทรีของ Agent

# delete agent registry services in Central Governance Project
for SERVICE in burger-seller-agent pizza-seller-agent purchasing-concierge-adk core-gapi-services; do
  gcloud agent-registry services delete ${SERVICE} \
    --project=${PROJECT_GOVERNANCE} \
    --location=${REGION} \
    --quiet || true
done

3. ลบการเชื่อมโยงนโยบายการเข้าถึงแบบรวมและนโยบายการเข้าถึงของ IAM

# 1. delete IAM policy binding
gcloud -q iam policy-bindings delete ${UAP_BINDING_NAME} \
  --project=${PROJECT_GOVERNANCE} \
  --location=global || true

# 2. delete IAM access policy
gcloud -q iam access-policies delete ${UAP_POLICY_NAME} \
  --project=${PROJECT_GOVERNANCE} \
  --location=global || true

4. ลบเกตเวย์ของตัวแทนและนโยบายความปลอดภัย

# 1. delete authorization policy
gcloud beta network-security authz-policies delete ${AGW_NAME}-authz-policy-profile-iap \
  --location=${REGION} \
  --project=${PROJECT_GOVERNANCE} --quiet || true

# 2. delete authorization extension
gcloud service-extensions authz-extensions delete ${AGW_NAME}-svc-ext-authz-iap \
  --location=${REGION} \
  --project=${PROJECT_GOVERNANCE} --quiet || true
# 3. delete agent gateway
gcloud network-services agent-gateways delete ${AGW_NAME} \
  --project=${PROJECT_GOVERNANCE} \
  --location=${REGION} --quiet || true

5. นำการเชื่อมโยง IAM ข้ามโปรเจ็กต์และบทบาทที่กำหนดเองออก

# 1. remove custom role and network viewer bindings for spoke service agents
for NUM in "${PROJECT_NUMBER_CONCIERGE}" "${PROJECT_NUMBER_SELLERS}"; do
  SA="service-${NUM}@gcp-sa-aiplatform.iam.gserviceaccount.com"
  
  gcloud projects remove-iam-policy-binding ${PROJECT_GOVERNANCE} \
    --member="serviceAccount:${SA}" \
    --role="projects/${PROJECT_GOVERNANCE}/roles/ar_agw_cross_project_sa" --quiet || true

  gcloud projects remove-iam-policy-binding ${PROJECT_GOVERNANCE} \
    --member="serviceAccount:${SA}" \
    --role="roles/networkservices.viewer" --quiet || true
done
# 2. remove registry viewer permissions across both spoke projects
for NUM in "${PROJECT_NUMBER_CONCIERGE}" "${PROJECT_NUMBER_SELLERS}"; do
  for MEMBER in \
    "serviceAccount:service-${NUM}@gcp-sa-aiplatform.iam.gserviceaccount.com" \
    "serviceAccount:service-${NUM}@gcp-sa-aiplatform-re.iam.gserviceaccount.com" \
    "serviceAccount:${NUM}-compute@developer.gserviceaccount.com" \
    "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${NUM}"; do
      gcloud projects remove-iam-policy-binding ${PROJECT_GOVERNANCE} \
        --member="${MEMBER}" \
        --role="roles/agentregistry.viewer" --quiet || true
  done
done
# 3. remove project viewer permissions
for MEMBER in \
  "serviceAccount:${PROJECT_NUMBER_CONCIERGE}-compute@developer.gserviceaccount.com" \
  "serviceAccount:service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform.iam.gserviceaccount.com"; do
    gcloud projects remove-iam-policy-binding ${PROJECT_GOVERNANCE} \
      --member="${MEMBER}" \
      --role="roles/viewer" --quiet || true
done
# 4. remove spoke-to-spoke delegation in Sellers project
for MEMBER in \
  "serviceAccount:service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform.iam.gserviceaccount.com" \
  "serviceAccount:service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform-re.iam.gserviceaccount.com" \
  "serviceAccount:${PROJECT_NUMBER_CONCIERGE}-compute@developer.gserviceaccount.com" \
  "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}"; do
    gcloud projects remove-iam-policy-binding ${PROJECT_SELLERS} \
      --member="${MEMBER}" \
      --role="roles/aiplatform.user" --quiet || true
done
# 5. delete custom IAM role after all bindings have been unlinked
gcloud iam roles delete ar_agw_cross_project_sa \
  --project=${PROJECT_GOVERNANCE} --quiet || true

หากคุณมอบหมาย roles/iam.accessPolicyAdmin และ roles/resourcemanager.projectIamAdmin ในระหว่างขั้นตอนการตั้งค่า ให้นำออกจากบัญชีผู้ใช้ที่ใช้งานอยู่เพื่อคืนค่าสิทธิ์ขั้นต่ำ

# 6. remove Access Policy Admin and Project IAM Admin roles from user
for ROLE in "roles/iam.accessPolicyAdmin" "roles/resourcemanager.projectIamAdmin"; do
  gcloud projects remove-iam-policy-binding ${PROJECT_GOVERNANCE} \
    --member="user:$(gcloud config get-value account)" \
    --role="${ROLE}" \
    --condition=None --quiet || true
done

6. เปลี่ยนกลับการบันทึกข้อมูลการตรวจสอบและข้อจำกัดของนโยบายขององค์กร

# 1. Export current Central Governance IAM policy
gcloud projects get-iam-policy ${PROJECT_GOVERNANCE} --format=json > cfg/gov_iam_policy.json
# 2. Filter out iap.googleapis.com from auditConfigs
python3 -c "
import json
with open('cfg/gov_iam_policy.json') as f:
    policy = json.load(f)

if 'auditConfigs' in policy:
    # Remove iap.googleapis.com; if nothing else remains, clear the list
    policy['auditConfigs'] = [
        ac for ac in policy['auditConfigs'] if ac.get('service') != 'iap.googleapis.com'
    ]

with open('cfg/gov_iam_policy.json', 'w') as f:
    json.dump(policy, f, indent=2)
"
# 3. Apply the updated policy to revert audit logging to default
gcloud projects set-iam-policy ${PROJECT_GOVERNANCE} cfg/gov_iam_policy.json

7. เปลี่ยนกลับข้อจำกัดของนโยบายองค์กร

# revert iam v3 access policy binding org policy on project to org level setting
gcloud org-policies delete iam.managed.disableAccessPolicyBinding --project=${PROJECT_GOVERNANCE}

8. ลบที่เก็บข้อมูลชั่วคราวของ GCS ที่แชร์และอาร์ติแฟกต์ในเครื่อง

# delete central staging bucket
gcloud storage rm -r gs://${PROJECT_GOVERNANCE}-shared-staging
# remove local configuration manifests, environment files, and application
rm -rf cfg/ cross-project-multiagent/ *.env

ส่วนการทำความสะอาดข้อมูลก็มีเพียงเท่านี้... ต่อไปเราจะไปที่บทสรุปกัน

12. บทสรุป

ยินดีด้วย คุณได้ติดตั้งใช้งานและควบคุมสถาปัตยกรรม Agent-to-Agent (A2A) แบบหลายโปรเจ็กต์ใน Google Cloud โดยใช้ Vertex AI Agent Runtime, Central Agent Gateway, Agent Registry และนโยบายการเข้าถึงแบบรวม (UAP) ของ IAM

สรุปแนวคิดหลัก

  • ขอบเขตขาออกส่วนกลาง: คอนเทนเนอร์รันไทม์ของ Spoke ที่กำหนดเส้นทาง (PROJECT_CONCIERGE, PROJECT_SELLERS) ผ่านเกตเวย์ตัวแทนส่วนกลางใน PROJECT_GOVERNANCE โดยใช้ agentGatewayConfig
  • การกำกับดูแลแบบประกาศ (UAP): แทนที่การเชื่อมโยงต่อทรัพยากรที่กระจัดกระจายด้วยนโยบายการเข้าถึง IAM แบบเดียวที่ตรวจสอบได้ ซึ่ง IAP v2 จะประเมินที่เกตเวย์
  • ข้อมูลประจำตัวแบบเข้ารหัส: บังคับใช้สิทธิ์ขั้นต่ำที่สุดสำหรับขาออกโดยใช้ข้อมูลประจำตัว SPIFFE ของคอนเทนเนอร์ (principal://...) แทนคีย์ที่มีอายุการใช้งานยาวนาน
  • การค้นหาบริการแบบไดนามิก: แก้ไขปลายทางของเอเจนต์เพียร์ไทม์รันผ่านรีจิสทรีเอเจนต์กลาง ซึ่งจะช่วยขจัด URL และรหัสโปรเจ็กต์แบบฮาร์ดโค้ด
  • ความคล่องตัวของนโยบายรันไทม์: เปลี่ยนจากpizza-seller-agentปฏิเสธโดยค่าเริ่มต้น (403 Forbidden) เป็นอนุญาต (200 OK) แบบเรียลไทม์ผ่านการอัปเดตนโยบาย โดยไม่ต้องรีสตาร์ทคอนเทนเนอร์

cosmopup

Cosmopup กล่าวว่า "เอเจนต์ยอดเยี่ยมมาก พวกเขาทำงานข้ามโปรเจ็กต์ทั้งหมดในขณะที่ฉันมุ่งเน้นไปที่เป้าหมายหลักของฉัน นั่นคือการงีบหลับ!"

ขั้นตอนถัดไปและเอกสาร