שימוש בתצוגות עם פרמטרים באפליקציות מבוססות-סוכנים

כדי להריץ בצורה מאובטחת תצוגות עם פרמטרים באפליקציות Bigtable שמשתמשות בסוכני AI או במודלים גדולים של שפה (LLM), צריך להגדיר בקרת גישה מחמירה ולהעביר פרמטרים מחוץ לפס.

הגדרת בקרת גישה

תצוגות לוגיות של Bigtable פועלות במודל אבטחה של זכויות המגדיר. כלומר, כשמריצים שאילתה על תצוגה, השאילתה מופעלת עם ההרשאות של המשתמש שהגדיר את התצוגה, ולא של המשתמש שמריץ את השאילתה. כדי לאכוף את העיקרון של הרשאות מינימליות, צריך להעניק לחשבון השירות של האפליקציה הרשאות גישה רק לתצוגה, ולמנוע הרשאות גישה לטבלת המקור הבסיסית.

כדי להגדיר בקרת גישה:

  1. יוצרים תפקיד ייעודי ב-IAM לאפליקציה עם הרשאות מינימליות, כמו התפקיד bigtable.reader.
  2. נותנים לתפקיד הזה הרשאות לצפייה בלבד. אפשר להשתמש בתנאי IAM כדי להגביל את ההרשאה bigtable.logicalViews.readRows לתצוגה הספציפית שלכם.
  3. כדי להגביל את בקרת הגישה, צריך לדחות באופן מפורש את ההרשאות של תפקיד האפליקציה במסד הנתונים הטבלאי הבסיסי באמצעות מדיניות דחייה ב-IAM.

מידע נוסף זמין במאמר בנושא בקרת גישה ל-Bigtable באמצעות IAM.

הוספת פרמטר של תצוגה מפורטת

באפליקציות מבוססות-סוכן, ערכי הפרמטרים של התצוגה הלוגית עם הפרמטרים, כמו פרטי כניסה של משתמשים או גבולות של דיירים, צריכים להיות מסופקים על ידי קוד האפליקציה המהימן, ולא על ידי ה-LLM או משתמש הקצה. כך מבודדים את קלט המשתמשים הלא מהימן ואת מחרוזות השאילתות שנוצרו על ידי המודל מהקלט של מסד הנתונים.

כדי ליצור סוכן AI, אפשר להשתמש במסגרת Agent Development Kit (ADK). ערכת ה-ADK מספקת את הרכיבים הבאים שעוזרים לכם לשלב תצוגות עם פרמטרים:

  • BigtableToolset: ערכת הכלים של ADK להגדרת מסד נתונים ולמתן כלים שפונים למסד הנתונים (במיוחד execute_sql_parameterized) שמתקשרים עם Bigtable. ערכת הכלים הזו מחלצת באופן אוטומטי פרמטרים של תצוגה מחוץ לפס ומריצה את שאילתת ה-SQL על הנתונים שלכם.
  • ToolContext: מנגנון זמן הריצה שמבודד את המצב הספציפי של הסשן ואת מאפייני התשתית, ומאפשר לכלי לפתור פרמטרים רגישים של סינון בלי לחשוף אותם ל-LLM.

בתמונה הבאה אפשר לראות איך הרכיבים פועלים יחד כדי להוסיף פרמטר ל-Bigtable:

התהליך של הוספת פרמטר תצוגה ל-Bigtable.
איור 1. תהליך השילוב של תצוגות עם פרמטרים באפליקציה מבוססת-סוכן (אפשר ללחוץ כדי להגדיל).

השלבים הבאים מסבירים את תהליך הוספת הפרמטרים:

  1. האפליקציה מאמתת את משתמש הקצה ומקבלת את פרטי הכניסה המאומתים של המשתמש ואת הארגון של הדייר.
  2. האפליקציה מקבלת שאילתה בשפה טבעית מהמשתמש.
  3. האפליקציה מפעילה את סוכן ה-ADK, ומעבירה את מזהי המשתמש והדייר המאומתים במצב הסשן המאובטח.
  4. כשהסוכן מחליט לשלוח שאילתה למסד הנתונים, הוא קובע רק את ארגומנטי הסינון בשפה טבעית, כמו עיר, ומפעיל את הכלי execute_sql_parameterized.
  5. כלי מסד הנתונים הבסיסי מאחזר בצורה מאובטחת את פרטי הכניסה הרגישים של המשתמש ואת גבולות הדייר מ-ToolContext ומריץ את השאילתה מול Bigtable.

בדוגמה הבאה מוצג איך להגדיר אפליקציה מבוססת-סוכן באמצעות ADK כדי לשלוח שאילתה לגבי היסטוריית הרכישות של משתמש.

הגדרת ערכת הכלים של Bigtable

באפליקציית Python, מגדירים את ה-ADK‏ BigtableToolset עם שמות הפרמטרים שרוצים לפתור מחוץ לפס (view_parameter_names). כך ממפים ישירות את מאפייני התשתית של המסגרת, כמו user_id, ואת משתני הסשן של האפליקציה, כמו tenant_id, לשאילתת מסד הנתונים.

import google.auth
from google.adk.agents.llm_agent import LlmAgent
from google.adk.tools.bigtable.bigtable_credentials import BigtableCredentialsConfig
from google.adk.tools.bigtable.bigtable_toolset import BigtableToolset

# 1. Initialize credentials (using Application Default Credentials here)
credentials, _ = google.auth.default()
credentials_config = BigtableCredentialsConfig(credentials=credentials)

# 2. Configure the BigtableToolset
# Passing view_parameter_names=["user_id", "tenant_id"] instructs the toolset
# to automatically extract both parameters from the ToolContext at runtime
# and inject them into the query's view_parameters.
bigtable_toolset = BigtableToolset(
    credentials_config=credentials_config,
    view_parameter_names=["user_id", "tenant_id"],
)

הפעלת הסוכן עם ערכת הכלים

העברת ערכת הכלים ישירות לרשימה של הסוכן tools. הסוכן יזהה באופן אוטומטי את הכלי execute_sql_parameterized ויציג אותו.

# 3. Create the agent and expose the toolset
agent = LlmAgent(
    model="MODEL_NAME",
    name="purchase_history_agent",
    description="An agent that retrieves multi-tenant purchase history.",
    instruction="You are an assistant that helps users find their purchase history within their tenant.",
    tools=[bigtable_toolset],
)

מחליפים את MODEL_NAME בשם המודל שרוצים להשתמש בו – לדוגמה, gemini-2.5-flash.

הרצת האפליקציה שמבוססת על סוכן

כשמריצים את הסוכן, צריך לאתחל את הסשן הפעיל עם זהות המשתמש בתשתית ועם מצב הארגון באפליקציה.

import asyncio
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types

async def main():
    # 4. Initialize session service
    session_service = InMemorySessionService()

    # 5. Create a session for the authenticated user and store their specific
    # organization tenant in the state.
    authenticated_user_id = "user-anwesha-123"
    organization_tenant_id = "tenant-corp-alpha"

    session = await session_service.create_session(
        user_id=authenticated_user_id, # Resolved from tool_context.user_id
        # Resolved from tool_context.state["tenant_id"]
        state={"tenant_id": organization_tenant_id},
        app_name="purchase_history_app",
    )

    runner = Runner(
        app_name="purchase_history_app",
        agent=agent,
        session_service=session_service,
    )

    # 6. Simulate a user query
    user_query = "What did I buy in New York?"
    content = types.Content(role="user", parts=[types.Part(text=user_query)])

    # The runner runs the agent.
    # When the agent calls execute_sql_parameterized, the ADK framework resolves
    # both "user_id" and "tenant_id" out-of-band and passes them to Bigtable
    # as view parameters, completely hidden from the LLM.
    events = runner.run(
        session_id=session.id,
        user_id=session.user_id,
        new_message=content,
    )

    for event in events:
        if event.content and event.content.parts:
            print(f"Agent: {event.content.parts[0].text}")

if __name__ == "__main__":
    asyncio.run(main())

התוצאה היא רשימה של רשומות היסטוריית רכישות של המשתמש המאומת, מסוננות לפי העיר שהמשתמש ציין בשאילתה ומוגבלות לגבולות הדייר שלו.

התהליך הזה מבטיח שהפרמטרים של האבטחה מוזרקים מחוץ לפס, ונשארים מוסתרים לחלוטין מפני מניפולציה של מודל השפה.