<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Pier Paolo Ippolito</title>
		<description>
			Welcome to my website! Here you can find some of my published works and blogs (1.5M+ views). If you have any questions, feel free to get in touch.

			
		</description>
		<link>https://ppiconsulting.dev/</link>
		<atom:link href="https://ppiconsulting.dev/blog/feed.xml" rel="self" type="application/rss+xml"/>
		
			<item>
				<title>Building AI Agents in 30 Minutes from Prototype to Production</title>
				<description>&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:4800/format:webp/1*_fXKb5a6w-1Kl3yK5-egFg.png&quot; alt=&quot;Agents CLI in Agent Platform (Image by Author).&quot; /&gt;&lt;br /&gt;Agents CLI in Agent Platform (Image by Author).&lt;/p&gt;

&lt;!--end_excerpt--&gt;

&lt;table&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;td align=&quot;left&quot;&gt;
        :memo:   Please Note
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;

    &lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;
        &lt;ul&gt;
            This is a guest post originally published on &lt;a href=&quot;https://medium.com/google-cloud/building-ai-agents-in-30-minutes-from-prototype-to-production-3d1eb54263a7&quot; target=&quot;_blank&quot;&gt;Google Cloud - Community&lt;/a&gt;.
        &lt;/ul&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;building-ai-agents-in-30-minutes-from-prototype-to-production&quot;&gt;Building AI Agents in 30 Minutes from Prototype to Production&lt;/h1&gt;

&lt;h2 id=&quot;building-evaluating-and-deploying-production-ready-ai-agents-using-agents-cli-in-agent-platform&quot;&gt;Building, evaluating and deploying production-ready AI agents using Agents CLI in Agent Platform&lt;/h2&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;If you’ve tried deploying an AI agent recently, you’ve probably run into the same problem. Your agent works perfectly in development: it answers questions, calls the right tools, makes sensible decisions. Then someone asks “when can we deploy this?” and suddenly you’re spending days configuring Docker, setting up authentication, implementing observability, and writing deployment pipelines.&lt;/p&gt;

&lt;p&gt;The agent code itself? That took a few hours. The infrastructure around it? That’s taking weeks.&lt;/p&gt;

&lt;p&gt;In this article, we are going to explore how to build and deploy a production-ready AI agent from scratch using Agents CLI: an open-source toolkit that handles all the deployment complexity. We’ll build a complete expense approval agent with business logic, evaluations, and cloud deployment in approximately 30 minutes.&lt;/p&gt;

&lt;p&gt;More on my &lt;a href=&quot;https://github.com/pierpaolo28&quot;&gt;GitHub account&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-agent-deployment-problem&quot;&gt;The Agent Deployment Problem&lt;/h2&gt;

&lt;p&gt;Building an AI agent with the Agent Development Kit (ADK), LangChain, or LlamaIndex is straightforward. Getting that agent into production? That’s where the complexity lives.&lt;/p&gt;

&lt;p&gt;Here’s what you typically need for a production agent:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local Development:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Agent code (the interesting part)&lt;/li&gt;
  &lt;li&gt;Local testing environment&lt;/li&gt;
  &lt;li&gt;Mock data or API stubs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Testing &amp;amp; Evaluation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Test case definitions&lt;/li&gt;
  &lt;li&gt;Evaluation metrics and rubrics&lt;/li&gt;
  &lt;li&gt;LLM-as-judge configuration&lt;/li&gt;
  &lt;li&gt;Regression test suite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Production Infrastructure:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Container image (Docker)&lt;/li&gt;
  &lt;li&gt;Cloud deployment config (Cloud Run/Kubernetes)&lt;/li&gt;
  &lt;li&gt;Authentication and authorization&lt;/li&gt;
  &lt;li&gt;Secret management&lt;/li&gt;
  &lt;li&gt;CI/CD pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Observability:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Request tracing&lt;/li&gt;
  &lt;li&gt;Prompt/response logging&lt;/li&gt;
  &lt;li&gt;Cost tracking and analytics&lt;/li&gt;
  &lt;li&gt;Performance monitoring&lt;/li&gt;
  &lt;li&gt;Error alerting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each piece requires learning new tools, reading documentation, and connecting disparate systems. Your coding assistant can help with agent logic, but struggles with deployment context: it doesn’t know your infrastructure patterns, leading to multiple debugging iterations.&lt;/p&gt;

&lt;h2 id=&quot;what-is-agents-cli&quot;&gt;What is Agents CLI?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/google/agents-cli&quot;&gt;Agents CLI in Agent Platform&lt;/a&gt; is a toolkit providing a unified interface to the full agent development lifecycle on Google Cloud.&lt;/p&gt;

&lt;p&gt;It operates in two modes:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Agent Mode:&lt;/strong&gt; Install “skills” into your coding assistant (Gemini CLI, Claude Code, Cursor). These skills teach your assistant the deployment patterns so it makes correct decisions.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Manual Mode:&lt;/strong&gt; Run CLI commands directly. Every command works standalone: no AI assistant required.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The core innovation: instead of your AI assistant guessing at deployment patterns, it has direct access to machine-readable context about when to use different deployment targets, how to structure evaluations, and which observability patterns work best.&lt;/p&gt;

&lt;h2 id=&quot;building-an-expense-approval-agent&quot;&gt;Building an Expense Approval Agent&lt;/h2&gt;

&lt;p&gt;We’ll build an agent that reviews employee expense reports and makes approval decisions based on company policy. The agent will use Gemini models through Vertex AI for its reasoning capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Auto-approve routine expenses under $50&lt;/li&gt;
  &lt;li&gt;Detect duplicate submissions&lt;/li&gt;
  &lt;li&gt;Flag suspicious patterns (weekend charges, unusual vendors)&lt;/li&gt;
  &lt;li&gt;Escalate uncertain cases to human reviewers&lt;/li&gt;
  &lt;li&gt;Hard safety constraint: never auto-approve anything over $50&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;p&gt;Before we start, make sure you have:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Required tools
Python 3.11+
uv package manager
Node.js (for skills installation)
Google Cloud SDK (gcloud)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’ll also need a Google Cloud project with billing enabled. If you don’t have one yet, you can create it at &lt;a href=&quot;https://console.cloud.google.com/&quot;&gt;https://console.cloud.google.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;uvx google-agents-cli setup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Authentication:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Authenticate with Google Cloud and set your project:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Authenticate with Google Cloud&lt;/span&gt;
gcloud auth application-default login
&lt;span class=&quot;c&quot;&gt;# Set your project ID&lt;/span&gt;
gcloud config &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;project YOUR_PROJECT_ID
&lt;span class=&quot;c&quot;&gt;# Enable required APIs&lt;/span&gt;
gcloud services &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;aiplatform.googleapis.com
gcloud services &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;run.googleapis.com
gcloud services &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;artifactregistry.googleapis.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This configures Vertex AI access for your agent, which will use Gemini models through the Vertex AI API.&lt;/p&gt;

&lt;h2 id=&quot;step-1-project-scaffolding&quot;&gt;Step 1: Project Scaffolding&lt;/h2&gt;

&lt;p&gt;Instead of manually creating directories and configuration files, we’ll use Agents CLI to scaffold the complete project structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With a coding assistant (Gemini CLI, Claude, Cursor):&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Build an expense approval agent using agents-cli. 
Auto-approve under $50, flag duplicates, escalate suspicious cases. 
Start with a prototype.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Your assistant reads the installed skills and generates the project with the correct structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual approach:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;agents-cli create expense-agent &lt;span class=&quot;nt&quot;&gt;--prototype&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--yes&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;expense-agent
agents-cli &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--prototype&lt;/code&gt; flag is important: it generates just the agent code and test structure, skipping deployment infrastructure (Docker, Terraform, CI/CD). We’ll add that later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generated structure:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;expense-agent/
├── app/
│   ├── agent.py          # Agent definition
│   └── app_utils/        # Telemetry helpers
├── tests/
│   ├── eval/
│   │   ├── evalsets/     # Test cases for LLM-as-judge
│   │   └── eval_config.json
│   ├── integration/
│   └── unit/
├── pyproject.toml        # Dependencies managed by uv
└── GEMINI.md             # Guidance for coding agents
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-2-implementing-business-logic&quot;&gt;Step 2: Implementing Business Logic&lt;/h2&gt;

&lt;p&gt;Now we’ll implement the actual expense approval logic. Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/agent.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In ADK (and most agent frameworks), tools are plain Python functions. The docstring is critical, the LLM reads it to determine when and how to call each tool.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool 1: Check Expense History&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;adk.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gemini&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;adk.agents&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;check_expense_history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;employee_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vendor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Check if this expense was already submitted.
    Args:
        employee_id: Employee identifier
        vendor: Vendor name
        date: Expense date (YYYY-MM-DD)
        amount: Expense amount in USD
    Returns:
        JSON string with duplicate check results
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# In production, this would query your expense database
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Using mock data for demonstration
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;mock_history&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;date&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2026-04-15&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vendor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Coffee Shop&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;amount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;8.50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;date&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2026-04-15&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;vendor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Uber&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;amount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;24.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;past&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mock_history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;past&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vendor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vendor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; 
            &lt;span class=&quot;n&quot;&gt;past&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;date&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; 
            &lt;span class=&quot;nb&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;past&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;amount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.01&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;is_duplicate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Duplicate found: $&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; at &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vendor&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; on &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;is_duplicate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;No duplicate found&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Tool 2: Get Company Policy&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_company_policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Retrieve expense policy for a given category.Args:
        category: Expense category (meals, transport, lodging, etc.)
    Returns:
        JSON string with policy rules
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;policies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;meals&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;auto_approve_threshold&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;50.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;transport&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;auto_approve_threshold&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;50.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;lodging&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;auto_approve_threshold&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Always escalate
&lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;auto_approve_threshold&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;25.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;policies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;policies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;default&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Tool 3: Escalate to Human&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;escalate_to_human&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;expense_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;reason&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Route expense to human approval queue.Args:
        expense_id: Unique expense identifier
        reason: Why this needs human review
        context: Additional context for reviewer
    Returns:
        Confirmation message
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# In production, this creates a ticket or notification
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;🚨 ESCALATED: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expense_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Reason: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reason&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;escalated&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;ticket_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;REVIEW-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expense_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Agent Definition:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we wire these tools together into an agent with clear instructions and safety constraints:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;expense_approval_agent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Gemini&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gemini-3.1-pro-preview&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Using Vertex AI
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;You are an expense approval agent. Review expenses and make 
    approval decisions based on company policy.
    Process for every expense:
    1. Call get_company_policy() to check the category threshold
    2. Call check_expense_history() to verify no duplicate exists
    3. Make a decision: AUTO_APPROVE, ESCALATE, or REJECT
    Auto-approve only if ALL of these conditions are true:
    - Amount is under the threshold for that category
    - No duplicate found in expense history
    - Expense is from a business day (Monday-Friday)
    - Vendor appears legitimate
    Escalate to human if ANY of these conditions are true:
    - Amount is over the category threshold
    - Duplicate submission detected
    - Weekend expense without clear business justification
    - Uncertain about vendor legitimacy
    - Category is &quot;lodging&quot; (always requires human review)
    Safety rules (NEVER violate these):
    - NEVER auto-approve any expense over $50
    - NEVER approve without checking for duplicates first
    - ALWAYS provide clear reasoning for your decision
    - When in doubt, ESCALATE (false escalation is better than false approval)
    Response format:
    Decision: [AUTO_APPROVE | ESCALATE | REJECT]
    Reasoning: [Clear explanation of why you made this decision]
    Tools called: [Which tools you used]
    &quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check_expense_history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_company_policy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;escalate_to_human&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice the safety constraints in the instruction. Even if the policy permits approving up to $50 for meals, we enforce a hard limit, the agent will never auto-approve over $50 without human review. This prevents expensive mistakes.&lt;/p&gt;

&lt;h2 id=&quot;step-3-local-testing&quot;&gt;Step 3: Local Testing&lt;/h2&gt;

&lt;p&gt;Start the ADK playground:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;agents-cli playground
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This launches the web interface at &lt;a href=&quot;http://localhost:8080/&quot;&gt;http://localhost:8080&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Case 1: Routine approval&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Review this expense:
Employee: emp-123
Category: meals
Vendor: Coffee Shop
Date: 2026-04-18
Amount: $12.50
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Expected behavior: Agent calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_company_policy()&lt;/code&gt; (threshold is $50), calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check_expense_history()&lt;/code&gt; (no duplicate), and auto-approves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Case 2: Over threshold&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Review this expense:
Employee: emp-456
Category: meals  
Vendor: Restaurant
Date: 2026-04-18
Amount: $85.00
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Expected behavior: Agent escalates because amount exceeds $50.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Case 3: Duplicate detection&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Review this expense:
Employee: emp-789
Category: transport
Vendor: Uber
Date: 2026-04-15
Amount: $24.00
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Expected behavior: Agent finds duplicate in mock history and escalates.&lt;/p&gt;

&lt;p&gt;Manual testing covers the happy path, but we need systematic validation for production readiness.&lt;/p&gt;

&lt;h2 id=&quot;step-4-writing-structured-evaluations&quot;&gt;Step 4: Writing Structured Evaluations&lt;/h2&gt;

&lt;p&gt;This is the part most developers skip, and it’s why agents break in production.&lt;/p&gt;

&lt;p&gt;You need structured test cases with clear pass/fail criteria. Not “does this feel right?” but “does this meet policy requirements?”&lt;/p&gt;

&lt;p&gt;Edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tests/eval/evalsets/basic.evalset.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;eval_set_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;expense_approval_eval&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Expense Policy Validation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;eval_cases&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;eval_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;routine_approval&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;conversation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;user_content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;parts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Review: emp-101, meals, Coffee Shop, 2026-04-18, $15.00&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;session_input&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;app_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;user_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;eval_user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;expected_tool_calls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;get_company_policy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;check_expense_history&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;expected_output_keywords&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;approve&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;approved&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;eval_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;escalate_over_threshold&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;conversation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;user_content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;parts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Review: emp-102, meals, Restaurant, 2026-04-18, $85.00&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;session_input&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;app_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;user_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;eval_user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;expected_tool_calls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;get_company_policy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;escalate_to_human&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;expected_output_keywords&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;escalate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;human review&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;eval_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;reject_duplicate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;conversation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;user_content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;parts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
              &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Review: emp-103, transport, Uber, 2026-04-15, $24.00&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
          &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;session_input&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;app_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;user_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;eval_user&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;expected_tool_calls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;check_expense_history&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;expected_output_keywords&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;duplicate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;escalate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Run the evaluation:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;agents-cli &lt;span class=&quot;nb&quot;&gt;eval &lt;/span&gt;run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Running expense_approval_eval...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ routine_approval       policy_compliance: 1.0  safety: 1.0  tool_usage: 1.0
✓ escalate_over_threshold   policy_compliance: 1.0  safety: 1.0  tool_usage: 1.0
✓ reject_duplicate       policy_compliance: 0.9  safety: 1.0  tool_usage: 0.9
Overall Pass Rate: 100% (3/3 cases)
Average Scores: policy_compliance=0.97, safety=1.0, tool_usage=0.97
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The eval system uses LLM-as-judge to score responses against rubrics defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval_config.json&lt;/code&gt;. If any case fails, you iterate on the agent instruction or tool logic until all cases pass.&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;eval-fix loop,&lt;/strong&gt; the key to building reliable production agents. Without evals, you’re hoping your agent works. With evals, you know it works.&lt;/p&gt;

&lt;h2 id=&quot;step-5-deploying-to-production&quot;&gt;Step 5: Deploying to Production&lt;/h2&gt;

&lt;p&gt;Our agent works and passes all evaluations. Time to deploy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add deployment infrastructure:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;agents-cli scaffold enhance &lt;span class=&quot;nt&quot;&gt;--deployment-target&lt;/span&gt; cloud_run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This generates:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Dockerfile&lt;/li&gt;
  &lt;li&gt;Cloud Run deployment configuration&lt;/li&gt;
  &lt;li&gt;Terraform infrastructure files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Configure your project and deploy:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcloud config &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;project YOUR_PROJECT_ID
agents-cli deploy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Deployment output:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Building container image...
Pushing to us-central1-docker.pkg.dev/your-project/agents/expense-agent...
Deploying to Cloud Run...
✓ Deployment successful!
Service URL: https://expense-agent-xyz123-uc.a.run.app
Logs: https://console.cloud.google.com/run/detail/.../logs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Total time from&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**agents-cli create**&lt;/code&gt; &lt;strong&gt;to deployed service: approximately 30 minutes.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;step-6-observability&quot;&gt;Step 6: Observability&lt;/h2&gt;

&lt;p&gt;Cloud Trace is automatically enabled, no configuration required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test the deployed agent:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;agents-cli run &lt;span class=&quot;s2&quot;&gt;&quot;Review expense: emp-501, transport, Uber, 2026-04-18, &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$15&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.00&quot;&lt;/span&gt;
agents-cli run &lt;span class=&quot;s2&quot;&gt;&quot;Review expense: emp-502, meals, Restaurant, 2026-04-18, &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$95&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.00&quot;&lt;/span&gt;
agents-cli run &lt;span class=&quot;s2&quot;&gt;&quot;Review expense: emp-503, lodging, Hilton, 2026-04-18, &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$200&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.00&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Open &lt;a href=&quot;https://console.cloud.google.com/traces&quot;&gt;Cloud Trace&lt;/a&gt; to see:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Full request traces with latency breakdown&lt;/li&gt;
  &lt;li&gt;Individual LLM call durations&lt;/li&gt;
  &lt;li&gt;Tool execution times&lt;/li&gt;
  &lt;li&gt;End-to-end request timeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Set up content logging&lt;/strong&gt; for debugging and analysis:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;agents-cli infra single-project &lt;span class=&quot;nt&quot;&gt;--project&lt;/span&gt; YOUR_PROJECT_ID
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This provisions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Service account for logging&lt;/li&gt;
  &lt;li&gt;GCS bucket for prompt-response storage&lt;/li&gt;
  &lt;li&gt;BigQuery dataset for analytics&lt;/li&gt;
  &lt;li&gt;Updates your agent to log all conversations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Query production behavior in BigQuery:&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;JSON_EXTRACT_SCALAR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;$.user_content.parts[0].text&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;JSON_EXTRACT_SCALAR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;$.decision&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;latency_ms&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;`your-project.agent_analytics.conversations`&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;expense-agent&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;timestamp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DESC&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;LIMIT&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is critical for debugging production issues. “Why did it escalate that $30 meal?” Just query BigQuery and see exactly what the agent was thinking.&lt;/p&gt;

&lt;h2 id=&quot;what-makes-agents-cli-different&quot;&gt;What Makes Agents CLI Different&lt;/h2&gt;

&lt;p&gt;I’ve used various agent deployment tools over the past few years. Here’s what stands out about Agents CLI:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Skills as Machine-Readable Context&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agents CLI doesn’t just provide commands: it provides “skills” that teach your coding assistant how to use them correctly.&lt;/p&gt;

&lt;p&gt;When you run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;agents-cli setup&lt;/code&gt;, it installs 7 skills:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;google-agents-cli-workflow&lt;/code&gt;: Development lifecycle&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;google-agents-cli-adk-code&lt;/code&gt;: ADK Python API patterns&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;google-agents-cli-scaffold&lt;/code&gt;: Project scaffolding&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;google-agents-cli-eval&lt;/code&gt;: Evaluation methodology&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;google-agents-cli-deploy&lt;/code&gt;: Deployment targets&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;google-agents-cli-publish&lt;/code&gt;: Gemini Enterprise registration&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;google-agents-cli-observability&lt;/code&gt;: Tracing and logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your coding assistant reads these when relevant. Instead of guessing deployment options, it knows when to use Agent Runtime vs Cloud Run vs GKE. Instead of trial-and-error with eval metrics, it knows the LLM-as-judge patterns that work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Evaluation as Default, Not Optional&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every scaffolded project includes evaluation infrastructure from the start:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tests/eval/evalsets/&lt;/code&gt; for test cases&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval_config.json&lt;/code&gt; for scoring rubrics&lt;/li&gt;
  &lt;li&gt;LLM-as-judge setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design choice reflects reality, agents without evals don’t make it to production. Making evaluation the default path ensures agents are tested before deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Observability by Default&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cloud Trace is enabled automatically in every deployed agent. No configuration, no opt-in, it just works.&lt;/p&gt;

&lt;p&gt;Why? Because debugging production agents without traces is nearly impossible. The content logging and BigQuery analytics are opt-in (via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;agents-cli infra single-project&lt;/code&gt;), but basic tracing is mandatory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Handles Infrastructure Complexity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agent logic is interesting. Docker configurations, authentication middleware, and Terraform files are not. Agents CLI handles the infrastructure so you can focus on making your agent smart.&lt;/p&gt;

&lt;h2 id=&quot;beyond-the-basics&quot;&gt;Beyond the Basics&lt;/h2&gt;

&lt;p&gt;Our expense agent handles the core requirements, but production systems need more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real Data Connections&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Replace the mock expense history with actual database queries:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;psycopg2&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;check_expense_history&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;employee_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vendor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;psycopg2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DATABASE_URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cursor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
        SELECT * FROM expenses 
        WHERE employee_id = %s 
        AND vendor = %s 
        AND date = %s 
        AND amount = %s
    &quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;employee_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vendor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Process results...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;CI/CD Pipeline&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Generate GitHub Actions workflow for staging and production:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;agents-cli infra cicd &lt;span class=&quot;nt&quot;&gt;--runner&lt;/span&gt; github-actions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This creates a multi-environment pipeline:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Commits to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; → deploy to staging&lt;/li&gt;
  &lt;li&gt;Tagged releases → deploy to production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Session Management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add Cloud SQL for persistent session storage:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;agents-cli scaffold enhance &lt;span class=&quot;nt&quot;&gt;--session-type&lt;/span&gt; cloud_sql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Multi-Agent Systems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;adk_a2a&lt;/code&gt; template enables specialist agents to coordinate:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;agents-cli create coordinator-agent &lt;span class=&quot;nt&quot;&gt;--agent-type&lt;/span&gt; adk_a2a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Useful for complex workflows like incident response or code migrations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RAG (Retrieval-Augmented Generation)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Scaffold an agent with vector search:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;agents-cli create docs-agent &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--agent-type&lt;/span&gt; agentic_rag &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--datastore&lt;/span&gt; agent_platform_vector_search
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This generates data ingestion code, vector search integration, and retrieval logic.&lt;/p&gt;

&lt;h2 id=&quot;techniques-summary&quot;&gt;Techniques Summary&lt;/h2&gt;

&lt;p&gt;Throughout this article, we explored several key techniques for building production agents:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1376/format:webp/1*PSNsb3FRGl89yvl7WBcLkA.png&quot; alt=&quot;Figure 1: Techniques Summary Table (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 1: Techniques Summary Table (Image by Author).&lt;/p&gt;

&lt;p&gt;Each technique solves a specific problem in the agent development lifecycle. Combined, they create a complete path from prototype to production.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The deployment gap is real. Most AI agent projects fail not because the agent isn’t good enough, but because shipping it requires too much infrastructure work.&lt;/p&gt;

&lt;p&gt;Agents CLI doesn’t solve every problem. You still need well-designed prompts, appropriate tools, and thorough testing. But it eliminates the infrastructure busywork that keeps agents stuck in development environments.&lt;/p&gt;

&lt;p&gt;Your agent development workflow should feel like running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create-react-app&lt;/code&gt;, not like manually assembling infrastructure. That’s what we built.&lt;/p&gt;
</description>
				<pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate>
				<link>https://ppiconsulting.dev//blog/blog99/</link>
				<guid isPermaLink="true">https://ppiconsulting.dev//blog/blog99/</guid>
			</item>
		
			<item>
				<title>Building End to End AI Agents with ADK Dev Skills</title>
				<description>&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2000/format:webp/1*kzcIyquyBiN1w5b1pytvaQ.png&quot; alt=&quot;Building End to End AI Agents with ADK Dev Skills (Image by Author).&quot; /&gt;&lt;br /&gt;Building End to End AI Agents with ADK Dev Skills (Image by Author).&lt;/p&gt;

&lt;!--end_excerpt--&gt;

&lt;table&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;td align=&quot;left&quot;&gt;
        :memo:   Please Note
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;

    &lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;
        &lt;ul&gt;
            This is a guest post originally published on &lt;a href=&quot;https://medium.com/google-cloud/building-end-to-end-ai-agents-with-adk-dev-skills-26e1176ba661&quot; target=&quot;_blank&quot;&gt;Google Cloud - Community&lt;/a&gt;.
        &lt;/ul&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;putting-a-principal-adk-engineer-in-every-developers-laptop&quot;&gt;Putting a “Principal ADK Engineer” in every developer’s laptop&lt;/h2&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;In this tutorial, we’ll build a complete multi-agent customer support system in about an hour. Not a prototype or a demo: a production-ready system with CI/CD, comprehensive testing, and cloud deployment. The kind of project that would normally take a few weeks to scaffold properly.&lt;/p&gt;

&lt;p&gt;Here’s what we’ll end up with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Multi-agent orchestration with intelligent routing&lt;/li&gt;
  &lt;li&gt;Production deployment to Vertex AI Agent Engine&lt;/li&gt;
  &lt;li&gt;Unit tests, integration tests, and evaluation datasets&lt;/li&gt;
  &lt;li&gt;Full CI/CD pipeline with staging and production environments&lt;/li&gt;
  &lt;li&gt;Cloud observability with tracing and logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The approach? We’ll barely write any code ourselves. Instead, we’ll use &lt;a href=&quot;https://adk.dev/tutorials/coding-with-ai/#adk-dev-skills&quot;&gt;ADK Dev Skills&lt;/a&gt; to turn our AI coding assistant into an expert ADK (&lt;a href=&quot;https://adk.dev/&quot;&gt;Google Agent Development Kit&lt;/a&gt;) developer who knows exactly what to build and how to build it right.&lt;/p&gt;

&lt;p&gt;Let’s see how this works! (Video tutorial below for anyone interested)&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt;
  &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/7PNOkMLAk4c&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2 id=&quot;what-are-adk-dev-skills&quot;&gt;What Are ADK Dev Skills?&lt;/h2&gt;

&lt;p&gt;ADK Dev Skills are pre-built knowledge modules that give AI coding assistants deep expertise in specific domains. When we install them, our AI assistant stops guessing about ADK APIs and starts giving us correct, production-ready code.&lt;/p&gt;

&lt;p&gt;Think of it this way: instead of our AI assistant reading generic documentation and trying to piece together how ADK works, it has direct access to the actual patterns, APIs, and best practices that the ADK team recommends.&lt;/p&gt;

&lt;p&gt;This solves some real problems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The AI stops hallucinating non-existent ADK APIs&lt;/li&gt;
  &lt;li&gt;We don’t need to constantly look up documentation&lt;/li&gt;
  &lt;li&gt;We get consistent patterns across our codebase&lt;/li&gt;
  &lt;li&gt;Evaluation and deployment configs just work&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;available-skills&quot;&gt;Available Skills&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2000/format:webp/1*LHkVuJOSdwYptLbJKl3Tsg.png&quot; alt=&quot;Figure 1: Available ADK Dev Skills (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 1: Available ADK Dev Skills (Image by Author).&lt;/p&gt;

&lt;h2 id=&quot;compatibility&quot;&gt;Compatibility&lt;/h2&gt;

&lt;p&gt;These skills work with any AI coding tool that supports the Skills Protocol. They work with Gemini CLI, Claude Code, Cursor, Antigravity, and other compatible tools.&lt;/p&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;p&gt;Before we start, we’ll need:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Required tools
- Node.js (for npx)
- Python 3.10+ 
- uv package manager (pip install uv)
- Google Cloud SDK (gcloud)
- An active GCP project with billing enabled
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s set up our GCP project:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcloud config &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;project YOUR_PROJECT_ID
gcloud auth application-default login
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-1-install-adk-dev-skills&quot;&gt;Step 1: Install ADK Dev Skills&lt;/h2&gt;

&lt;p&gt;First, install the skills globally so they’re available in all your projects:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npx skills add google/adk-docs/skills &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This downloads the 6 ADK skills from Google’s repository and makes them available to our AI assistant. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g&lt;/code&gt; flag means global installation, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-y&lt;/code&gt; just auto-confirms the prompt.&lt;/p&gt;

&lt;p&gt;Let’s verify it worked:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npx skills list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We should see all 6 ADK skills listed. Once they’re installed, any compatible AI assistant can use them.&lt;/p&gt;

&lt;h2 id=&quot;step-2-define-your-requirements&quot;&gt;Step 2: Define Your Requirements&lt;/h2&gt;

&lt;p&gt;Let’s start by telling our AI assistant what we’re trying to build. Be specific about the features we need.&lt;/p&gt;

&lt;p&gt;Here’s what we’ll ask for:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I need to build a Retail Returns multiagent system using ADK.
Requirements:
- Check order status by order ID
- Process refunds for delivered orders
- Multi-agent architecture with routing
- Production deployment to Agent Engine
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The AI will use the &lt;strong&gt;&lt;em&gt;adk-scaffold&lt;/em&gt;&lt;/strong&gt; skill to figure out the right project structure and create a design spec.&lt;/p&gt;

&lt;h2 id=&quot;step-3-generate-project-scaffolding&quot;&gt;Step 3: Generate Project Scaffolding&lt;/h2&gt;

&lt;p&gt;Next, ask the AI to create the project structure:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Use adk-scaffold to create this project with:
- Agent Engine deployment target
- GitHub Actions CI/CD
- No datastore needed (we&apos;ll use mock data)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The AI runs the &lt;strong&gt;&lt;em&gt;agent-starter-pack&lt;/em&gt;&lt;/strong&gt; (&lt;a href=&quot;https://github.com/GoogleCloudPlatform/agent-starter-pack&quot;&gt;repo here&lt;/a&gt;) scaffolding command with the right parameters and generates everything:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;retail-returns/
├── app/                    # Our agent code
├── tests/                  # Unit, integration, eval tests
├── .github/workflows/      # CI/CD pipelines
├── deployment/terraform/   # Infrastructure as code
├── notebooks/              # Jupyter notebooks
└── Makefile               # Common development commands
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It also sets up &lt;strong&gt;&lt;em&gt;pyproject.toml&lt;/em&gt;&lt;/strong&gt; with the right dependencies and configures deployment metadata.&lt;/p&gt;

&lt;p&gt;The nice thing here is we don’t need to remember the &lt;strong&gt;&lt;em&gt;agent-starter-pack&lt;/em&gt;&lt;/strong&gt; command syntax or know which deployment target to pick. The skill has that knowledge built in.&lt;/p&gt;

&lt;h2 id=&quot;step-4-implement-business-logic&quot;&gt;Step 4: Implement Business Logic&lt;/h2&gt;

&lt;p&gt;Now for the actual agent code. Let’s tell the AI what tools we need:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Add tools for:
1. check_order_status(order_id: str) -&amp;gt; dict
2. process_refund(order_id: str) -&amp;gt; dict
Use mock data with 3 sample orders. Refunds only work for delivered orders.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The AI uses &lt;strong&gt;&lt;em&gt;adk-cheatsheet&lt;/em&gt;&lt;/strong&gt; to write proper ADK code. Here’s what we get:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**app/tools.py**&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Mock database
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ORDERS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;12345&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shipped&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;total&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;45.99&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;T-shirt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;refunded&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;67890&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;delivered&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;total&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;120.50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;items&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Shoes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Socks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;refunded&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;check_order_status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;order_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Checks order status and details.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order_id&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ORDERS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;order&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ORDERS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;order_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Order &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;order_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; not found.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process_refund&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;order_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Processes refund with validation.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order_id&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ORDERS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Order &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;order_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; not found.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ORDERS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;order_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;delivered&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Order must be delivered&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;refunded&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Already refunded&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;refunded&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;transaction_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;REF-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;order_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;-123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**app/agent.py**&lt;/code&gt; with multi-agent architecture:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.agents&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.apps&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.models&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Gemini&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_status_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status_agent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Gemini&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gemini-3-flash-preview&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Look up orders using check_order_status tool.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check_order_status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_refund_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;refund_agent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Gemini&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gemini-3-flash-preview&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Verify order is delivered before processing refund.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check_order_status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;process_refund&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;triage_agent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Gemini&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gemini-3-flash-preview&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Route requests to status_agent or refund_agent.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sub_agents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_status_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_refund_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;retail_returns_app&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice a few things here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It used factory functions for sub-agents, which is the recommended pattern&lt;/li&gt;
  &lt;li&gt;The imports are correct (&lt;strong&gt;&lt;em&gt;google.adk.agents&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;google.adk.models&lt;/em&gt;&lt;/strong&gt;)&lt;/li&gt;
  &lt;li&gt;It set up the orchestration properly with a parent agent and sub_agents&lt;/li&gt;
  &lt;li&gt;Validation logic is both in the instructions and the tool code itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without &lt;strong&gt;&lt;em&gt;adk-cheatsheet&lt;/em&gt;&lt;/strong&gt;, we’d probably spend time figuring out the right way to structure this. The skill just knows.&lt;/p&gt;

&lt;h2 id=&quot;step-5-test-locally&quot;&gt;Step 5: Test Locally&lt;/h2&gt;

&lt;p&gt;Before deploying anything, test it locally:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Let&apos;s test this locally
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This runs the install and playground commands:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;retail-returns
make &lt;span class=&quot;nb&quot;&gt;install
&lt;/span&gt;make playground
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The ADK web interface starts on localhost:8501. We can chat with our agent and try different scenarios:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“Where is my order #12345?”&lt;/li&gt;
  &lt;li&gt;“Can I get a refund for order #67890?”&lt;/li&gt;
  &lt;li&gt;“Refund order #99999” (this one should fail gracefully)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;step-6-create-evaluations&quot;&gt;Step 6: Create Evaluations&lt;/h2&gt;

&lt;p&gt;Manual testing is fine for development, but you need automated evaluations for production. Ask the AI to create them:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Create an evaluation to test invalid order handling
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using &lt;strong&gt;&lt;em&gt;adk-eval-guide&lt;/em&gt;&lt;/strong&gt;, it generates proper evaluation datasets:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**tests/eval/evalsets/invalid_orders.evalset.json**&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;eval_set_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;invalid_orders&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;eval_cases&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;eval_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;invalid_status_check&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;conversation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;user_content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;parts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;What&apos;s the status of order #99999?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]}}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;expected_tool_calls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;tool_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;check_order_status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;order_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;99999&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;eval_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;invalid_refund&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;conversation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;user_content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;parts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;I want a refund for order #88888&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]}}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**tests/eval/eval_config.json**&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;criteria&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;tool_trajectory_avg_score&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;threshold&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;match_type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;IN_ORDER&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;final_response_match_v2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;threshold&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;judgeModelOptions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;judgeModel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;gemini-3-flash-preview&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Run the evaluations:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;make &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Tests passed: 2
Tests failed: 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The skill knows the right evalset schema, applies the appropriate metrics (tool trajectory scoring for tool calls, LLM-as-judge for responses), and sets reasonable thresholds. We didn’t need to read any documentation about how ADK evaluations work.&lt;/p&gt;

&lt;h2 id=&quot;step-7-deploy-to-production&quot;&gt;Step 7: Deploy to Production&lt;/h2&gt;

&lt;p&gt;Once testing looks good, let’s deploy to Agent Engine:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Deploy this to Agent Engine
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The AI uses &lt;strong&gt;&lt;em&gt;adk-deploy-guide&lt;/em&gt;&lt;/strong&gt; to run the deployment:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Export dependencies&lt;/span&gt;
uv &lt;span class=&quot;nb&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--no-hashes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; app/app_utils/.requirements.txt
&lt;span class=&quot;c&quot;&gt;# Deploy to Vertex AI&lt;/span&gt;
uv run &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; app.app_utils.deploy &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--source-packages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;./app &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--entrypoint-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;app.agent_engine_app &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--entrypoint-object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;agent_engine &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--requirements-file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;app/app_utils/.requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This packages our code, uploads it to Google Cloud, and provisions a Reasoning Engine instance. We’ll get back an Engine ID (something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2484736849587732480&lt;/code&gt;). The deployment takes 5-10 minutes while it builds the container and provisions infrastructure.&lt;/p&gt;

&lt;p&gt;Let’s test it:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;vertexai&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vertexai&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;YOUR_PROJECT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;us-central1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;agent_engines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ENGINE_ID&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;async_stream_query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Where is order #12345?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-8-set-up-cicd&quot;&gt;Step 8: Set Up CI/CD&lt;/h2&gt;

&lt;p&gt;For a production system, we need automated testing and deployment:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Set up CI/CD with GitHub Actions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The AI generates three GitHub Actions workflows:&lt;/p&gt;

&lt;h3 id=&quot;1-pr-checks-githubworkflowspr_checksyaml&quot;&gt;1. PR Checks (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/workflows/pr_checks.yaml&lt;/code&gt;)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Runs on every Pull Request&lt;/li&gt;
  &lt;li&gt;Executes unit + integration tests&lt;/li&gt;
  &lt;li&gt;Blocks merge if tests fail&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-staging-deployment-githubworkflowsstagingyaml&quot;&gt;2. Staging Deployment (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/workflows/staging.yaml&lt;/code&gt;)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Triggers on merge to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Deploys to staging environment&lt;/li&gt;
  &lt;li&gt;Runs load tests&lt;/li&gt;
  &lt;li&gt;Uploads results to GCS&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-production-deployment-githubworkflowsdeploy-to-prodyaml&quot;&gt;3. Production Deployment (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/workflows/deploy-to-prod.yaml&lt;/code&gt;)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Requires manual approval&lt;/li&gt;
  &lt;li&gt;Deploys to production environment&lt;/li&gt;
  &lt;li&gt;Same validation as staging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure setup&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;uvx agent-starter-pack setup-cicd &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--staging-project&lt;/span&gt; YOUR_STAGING_PROJECT &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--prod-project&lt;/span&gt; YOUR_PROD_PROJECT &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--repository-name&lt;/span&gt; YOUR_REPO &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--repository-owner&lt;/span&gt; YOUR_GITHUB_USER &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This provisions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Workload Identity Federation (secure, keyless auth)&lt;/li&gt;
  &lt;li&gt;Service accounts with proper IAM roles&lt;/li&gt;
  &lt;li&gt;GitHub secrets configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;step-9-observability&quot;&gt;Step 9: Observability&lt;/h2&gt;

&lt;p&gt;Let’s check on observability:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;How&apos;s observability configured?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The AI (using &lt;strong&gt;&lt;em&gt;adk-observability-guide&lt;/em&gt;&lt;/strong&gt;) explains what’s already set up:&lt;/p&gt;

&lt;h3 id=&quot;built-in-no-configuration-needed&quot;&gt;Built-in (No Configuration Needed)&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cloud Trace&lt;/strong&gt; — Distributed tracing&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Automatic instrumentation via OpenTelemetry&lt;/li&gt;
  &lt;li&gt;Tracks: agent invocation → LLM calls → tool execution&lt;/li&gt;
  &lt;li&gt;View in GCP Console → Trace explorer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prompt-Response Logging&lt;/strong&gt; — Privacy-preserving by default&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Mode: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CONTENT&lt;/code&gt; (metadata only, no PII)&lt;/li&gt;
  &lt;li&gt;Logs: token counts, latency, model names&lt;/li&gt;
  &lt;li&gt;Upload path: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gs://BUCKET_NAME/completions&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;optional-integrations&quot;&gt;Optional Integrations&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;BigQuery Agent Analytics&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Add to app/agent.py
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.plugins&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BigQueryAgentAnalyticsPlugin&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BigQueryAgentAnalyticsPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;agent_analytics&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Third-party platforms&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;AgentOps (session replay)&lt;/li&gt;
  &lt;li&gt;Phoenix/Arize (open-source tracing)&lt;/li&gt;
  &lt;li&gt;Freeplay, Weave, MLflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;adk-observability-guide&lt;/em&gt;&lt;/strong&gt; has instructions for all of these if you want to add them.&lt;/p&gt;

&lt;h2 id=&quot;step-10-write-tests-for-production&quot;&gt;Step 10: Write Tests for Production&lt;/h2&gt;

&lt;p&gt;We need tests that run against the actual deployed agent:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Create integration tests that hit the deployed agent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The AI generates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tests/integration/test_remote_agent.py&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pytest&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;requests&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;subprocess&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_access_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subprocess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gcloud&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;auth&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;print-access-token&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;capture_output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pytest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;integration&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;test_valid_order_status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Test order lookup on deployed agent.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_access_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://us-central1-aiplatform.googleapis.com/v1/projects/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PROJECT_NUM&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/locations/us-central1/reasoningEngines/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ENGINE_ID&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;:streamQuery&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Bearer &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;input&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Where is order #12345?&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;user_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shipped&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;45.99&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Run against production:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pytest tests/integration/test_remote_agent.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;before-and-after&quot;&gt;Before and After&lt;/h2&gt;

&lt;h3 id=&quot;without-skills&quot;&gt;Without Skills&lt;/h3&gt;

&lt;p&gt;The traditional approach:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Read through ADK documentation&lt;/li&gt;
  &lt;li&gt;Look up deployment examples&lt;/li&gt;
  &lt;li&gt;Figure out the Agent Engine APIs&lt;/li&gt;
  &lt;li&gt;Research how to do evaluations properly&lt;/li&gt;
  &lt;li&gt;Set up CI/CD for AI agents (not well documented)&lt;/li&gt;
  &lt;li&gt;Trial and error with observability&lt;/li&gt;
  &lt;li&gt;Write all the boilerplate yourself&lt;/li&gt;
  &lt;li&gt;Debug import errors and API mismatches&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Time investment: probably 2–3 weeks if you’re new to this, 3–5 days if you’re experienced.&lt;/p&gt;

&lt;h3 id=&quot;with-skills&quot;&gt;With Skills&lt;/h3&gt;

&lt;p&gt;What we actually did:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Installed skills once&lt;/li&gt;
  &lt;li&gt;Described what we wanted&lt;/li&gt;
  &lt;li&gt;Let the AI generate it&lt;/li&gt;
  &lt;li&gt;Reviewed and tested the code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Time investment: about an hour.&lt;/p&gt;

&lt;h2 id=&quot;best-practices-and-tips&quot;&gt;Best Practices and Tips&lt;/h2&gt;

&lt;h3 id=&quot;1-install-skills-globally&quot;&gt;1. Install Skills Globally&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npx skills add google/adk-docs/skills &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g&lt;/code&gt; flag so the skills are available in all our projects, not just the current one.&lt;/p&gt;

&lt;h3 id=&quot;2-be-specific-in-prompts&quot;&gt;2. Be Specific in Prompts&lt;/h3&gt;

&lt;p&gt;Vague prompts like “Build an agent” don’t give the AI enough to work with. Better: “Build a customer support agent with order lookup and refund processing, using multi-agent architecture”&lt;/p&gt;

&lt;h3 id=&quot;3-leverage-the-right-skill-for-each-phase&quot;&gt;3. Leverage the Right Skill for Each Phase&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2000/format:webp/1*v1w2yV172duhuQvucF5fyg.png&quot; alt=&quot;Figure 2: Mapping Skills to Example Prompts (Image by Author).&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;h2 id=&quot;iterate-with-evaluations&quot;&gt;Iterate with Evaluations&lt;/h2&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make eval&lt;/code&gt; frequently, not just at the end. After each major change, run the evaluations to catch regressions. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make eval-all&lt;/code&gt; to run all evaluation sets.&lt;/p&gt;

&lt;h3 id=&quot;5-review-generated-code&quot;&gt;5. Review Generated Code&lt;/h3&gt;

&lt;p&gt;The skills make the AI competent at ADK, but we still need to review what it generates:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Check that agent instructions are clear&lt;/li&gt;
  &lt;li&gt;Verify tool validation logic makes sense&lt;/li&gt;
  &lt;li&gt;Make sure the model choices are appropriate&lt;/li&gt;
  &lt;li&gt;Confirm business rules are correctly implemented&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;6-use-version-control&quot;&gt;6. Use Version Control&lt;/h3&gt;

&lt;p&gt;Let’s initialize a git repo early:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git init
git add &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Initial scaffold from ADK Dev Skills&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This way we can see exactly what the AI generated and track our changes over time.&lt;/p&gt;

&lt;h2 id=&quot;common-questions&quot;&gt;Common Questions&lt;/h2&gt;

&lt;h3 id=&quot;do-we-need-to-learn-adk-first&quot;&gt;Do we need to learn ADK first?&lt;/h3&gt;

&lt;p&gt;Basic understanding helps, but the skills reduce the learning curve significantly. We can be productive pretty quickly.&lt;/p&gt;

&lt;h3 id=&quot;can-we-modify-the-generated-code&quot;&gt;Can we modify the generated code?&lt;/h3&gt;

&lt;p&gt;Yes. The code is ours. Treat it as a starting point and modify whatever we need.&lt;/p&gt;

&lt;h3 id=&quot;will-this-work-with-different-ai-assistants&quot;&gt;Will this work with different AI assistants?&lt;/h3&gt;

&lt;p&gt;If it supports the Skills Protocol, yes. Works with Gemini CLI, Claude Code, Cursor, and Antigravity.&lt;/p&gt;

&lt;h3 id=&quot;what-if-we-want-to-deploy-to-cloud-run-instead&quot;&gt;What if we want to deploy to Cloud Run instead?&lt;/h3&gt;

&lt;p&gt;Just ask. The &lt;strong&gt;&lt;em&gt;adk-deploy-guide&lt;/em&gt;&lt;/strong&gt; skill covers multiple deployment targets.&lt;/p&gt;

&lt;h3 id=&quot;can-we-create-our-own-skills&quot;&gt;Can we create our own skills?&lt;/h3&gt;

&lt;p&gt;Yes. Skills are just markdown files with structured information. We can create company-specific ones.&lt;/p&gt;

&lt;h3 id=&quot;how-do-we-update-the-skills&quot;&gt;How do we update the skills?&lt;/h3&gt;

&lt;p&gt;Re-run the install command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npx skills add google/adk-docs/skills &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;what-we-built&quot;&gt;What We Built&lt;/h2&gt;

&lt;p&gt;In about an hour, we created:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Production-ready multi-agent system with intelligent routing&lt;/li&gt;
  &lt;li&gt;Two custom tools with validation logic&lt;/li&gt;
  &lt;li&gt;Unit tests for business logic&lt;/li&gt;
  &lt;li&gt;Integration tests for agent behavior&lt;/li&gt;
  &lt;li&gt;Evaluation datasets with LLM-as-judge scoring&lt;/li&gt;
  &lt;li&gt;Deployed agent on Vertex AI Agent Engine&lt;/li&gt;
  &lt;li&gt;Full CI/CD pipeline with staging and production&lt;/li&gt;
  &lt;li&gt;Cloud observability with tracing and logging&lt;/li&gt;
  &lt;li&gt;Remote integration tests against deployed infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-to-build-next&quot;&gt;What to Build Next&lt;/h2&gt;

&lt;p&gt;Some ideas for what we can build next:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Customer service bot with ticket routing&lt;/li&gt;
  &lt;li&gt;Data analysis agent with BigQuery tools&lt;/li&gt;
  &lt;li&gt;Code review assistant with GitHub integration&lt;/li&gt;
  &lt;li&gt;Documentation generator with web scraping&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The skills work for any domain. Install them once and our AI assistant can build production agents.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;ADK Dev Skills turn AI coding assistants into ADK experts. Instead of the AI guessing at APIs and patterns, it has direct access to the right way to do things. This solves real problems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No more documentation diving&lt;/li&gt;
  &lt;li&gt;No more boilerplate fatigue&lt;/li&gt;
  &lt;li&gt;No API mismatches from outdated examples&lt;/li&gt;
  &lt;li&gt;No deployment guesswork&lt;/li&gt;
  &lt;li&gt;No evaluation uncertainty&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The generated code follows best practices, includes comprehensive testing, and has production-grade infrastructure. Not just faster: actually better.&lt;/p&gt;
</description>
				<pubDate>Sat, 18 Apr 2026 00:00:00 +0000</pubDate>
				<link>https://ppiconsulting.dev//blog/blog98/</link>
				<guid isPermaLink="true">https://ppiconsulting.dev//blog/blog98/</guid>
			</item>
		
			<item>
				<title>Revolutionizing Claims, from Deepfake Detection to Next-Best-Action</title>
				<description>&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:4800/format:webp/1*4RASX9V2BD-7v4G-feujJQ.png&quot; alt=&quot;Revolutionizing Claims, from Deepfake Detection to Next-Best-Action (Image by Author).&quot; /&gt;&lt;br /&gt;Revolutionizing Claims, from Deepfake Detection to Next-Best-Action (Image by Author).&lt;/p&gt;

&lt;!--end_excerpt--&gt;

&lt;h2 id=&quot;revolutionizing-claims-from-deepfake-detection-to-next-best-action&quot;&gt;Revolutionizing Claims: From Deepfake Detection to Next-Best-Action&lt;/h2&gt;

&lt;table&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;td align=&quot;left&quot;&gt;
        :memo:   Please Note
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;

    &lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;
        &lt;ul&gt;
            This is a guest post originally published on &lt;a href=&quot;https://medium.com/google-cloud/revolutionizing-claims-from-deepfake-detection-to-next-best-action-77f5273a7016&quot; target=&quot;_blank&quot;&gt;Google Cloud - Community&lt;/a&gt;.
        &lt;/ul&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;solving-information-overload-and-sophisticated-fraud-with-google-adk&quot;&gt;Solving information overload and sophisticated Fraud with Google ADK&lt;/h2&gt;

&lt;p&gt;The insurance claims process is a critical juncture for both policyholders and carriers. For policyholders, it’s a moment of need, expecting fair and swift resolution. For carriers, it’s a complex dance between empathy, accuracy, and fraud prevention. However, this vital process is currently facing two formidable challenges: an overwhelming &lt;strong&gt;information overload&lt;/strong&gt; from diverse data sources and the insidious rise of &lt;strong&gt;sophisticated fraud&lt;/strong&gt;, particularly with AI-generated or tampered evidence.&lt;/p&gt;

&lt;p&gt;Manually sifting through mountains of unstructured claim documents, cross-referencing policies, and verifying the authenticity of digital evidence is slow, error-prone, and increasingly insufficient against cunning fraudulent tactics. This bottleneck not only delays legitimate claims but also exposes carriers to significant financial losses from successful fraud attempts. The industry desperately needs a solution that can accelerate legitimate payouts while robustly defending against novel forms of deception.&lt;/p&gt;

&lt;p&gt;This article introduces two cutting-edge agent applications, built using the Google Agent Development Kit (ADK) and leveraging advanced GenAI capabilities, designed to revolutionize claims processing:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;An “&lt;strong&gt;Investigator Agent&lt;/strong&gt;” that acts as a digital forensic expert, capable of detecting tampered or AI-generated evidence, particularly in image formats.&lt;/li&gt;
  &lt;li&gt;A “&lt;strong&gt;Reasoning Agent&lt;/strong&gt;” that intelligently analyzes unstructured claim documents against a vast repository of company policies to recommend the optimal “Next-Best-Action” for each unique claim.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Together, these agents form a powerful, intelligent system that augments human claims adjusters, transforming them from overwhelmed processors into strategic decision-makers.&lt;/p&gt;

&lt;h2 id=&quot;the-framework-google-agent-development-kit-adk&quot;&gt;The Framework: Google Agent Development Kit (ADK)&lt;/h2&gt;

&lt;p&gt;To tackle the complexity of claims processing, we need a framework that goes beyond simple LLM API calls. The Google ADK is purpose-built for creating robust, stateful, and auditable agentic workflows. Its key features enable us to construct a sophisticated system:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Agents:&lt;/strong&gt; Specialized, intelligent units for distinct tasks. We’ll use LlmAgent for complex reasoning and SequentialAgent to orchestrate our pipeline deterministically.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;State Management:&lt;/strong&gt; The ADK’s Session object with its shared state dictionary allows agents to communicate and pass crucial claim details — like initial fraud flags or extracted policy clauses — seamlessly through the workflow.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tools:&lt;/strong&gt; Agents are empowered with capabilities beyond text generation. Our agents will use tools to interact with external systems for deepfake detection, vector database lookups, and more.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Structured Output:&lt;/strong&gt; ADK’s integration with Pydantic ensures our agents output clean, validated JSON, providing reliable, actionable data for downstream systems or human review.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-architecture-an-intelligent-claims-processing-pipeline&quot;&gt;The Architecture: An Intelligent Claims Processing Pipeline&lt;/h2&gt;

&lt;p&gt;Our goal is to automate and enhance the critical cognitive steps a human claims adjuster performs. The improved pipeline incorporates the Investigator Agent to preemptively flag fraudulent evidence and the Reasoning Agent to provide intelligent, policy-driven recommendations.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;The Investigator Agent:&lt;/strong&gt; Receives initial claim data, including multimedia evidence. It uses specialized tools to analyze digital evidence (e.g., images) for authenticity and flags potential deepfakes or tampering.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Reasoning Agent:&lt;/strong&gt; Takes the verified claim details (and any fraud flags) and analyzes them against a comprehensive set of company policies and guidelines to recommend the “Next-Best-Action.”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Orchestrator:&lt;/strong&gt; A root agent (SequentialAgent) manages the flow, ensuring the Investigator Agent runs first, followed by the Reasoning Agent, creating a coherent, end-to-end workflow.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2000/format:webp/1*SAvYqKqMXP0Zckzav1iVBw.png&quot; alt=&quot;Figure 1: System Architecture (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 1: System Architecture (Image by Author).&lt;/p&gt;

&lt;h2 id=&quot;step-1-the-investigator-agent--detecting-digital-deception&quot;&gt;Step 1: The Investigator Agent — Detecting Digital Deception&lt;/h2&gt;

&lt;p&gt;The rise of sophisticated AI tools means that digital evidence — especially images — can no longer be trusted at face value. Our Investigator Agent is designed to tackle this challenge head-on. It focuses on verifying the authenticity of submitted images, leveraging advanced techniques to detect tampering or AI generation.&lt;/p&gt;

&lt;p&gt;For this tutorial, we’ll simulate a verify_image_authenticity tool. In a real-world scenario, this tool would integrate with services like Google Cloud’s &lt;a href=&quot;https://deepmind.google/models/synthid/&quot;&gt;SynthID&lt;/a&gt; for detecting AI-generated content or custom Computer Vision models for forensic analysis of image manipulation.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# In agent.py
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AsyncGenerator&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydantic&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BaseModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;asyncio&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.agents&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SequentialAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BaseAgent&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.agents.invocation_context&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InvocationContext&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.events&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.genai&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;types&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# --- Tools ---
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;verify_image_authenticity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Verifies the authenticity of a given image to detect deepfakes or tampering.
    Args:
        image_id: The unique identifier for the image to be verified.
    Returns:
        dict: A dictionary containing the verification status and details.
              - &apos;status&apos;: &quot;authentic&quot;, &quot;tampered&quot;, &quot;ai_generated&quot;, or &quot;unverifiable&quot;.
              - &apos;confidence&apos;: A float representing the confidence score (0.0 to 1.0).
              - &apos;details&apos;: A string with additional findings.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;--- Tool: verify_image_authenticity called for image_id: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; ---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Simulate API call to an image analysis service (e.g., SynthID, custom CV model)
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;claim_123_evidence_fake.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ai_generated&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;confidence&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.95&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;High confidence that the image contains AI-generated elements consistent with deepfake manipulation.&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;claim_456_evidence_tampered.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;tampered&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;confidence&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.88&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Image metadata indicates post-processing and pixel anomalies consistent with tampering.&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;authentic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;confidence&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.99&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;No signs of tampering or AI generation detected.&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# --- Agents ---
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;InvestigatorAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Agent responsible for analyzing digital evidence (e.g., images) for authenticity.
    Uses specialized tools for deepfake detection and tampering analysis.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;image_verification_tool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_verification_tool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_verification_tool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_verification_tool&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_run_async_impl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InvocationContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AsyncGenerator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;claim_evidence&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;claim_evidence&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;claim_evidence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;image_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;evidence_status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;no_image_submitted&quot;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fraud_flags&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;No image evidence submitted.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;verification_result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_verification_tool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;evidence_status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;verification_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fraud_flags&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verification_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;authentic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Image verification complete. Status: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verification_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;status&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, Confidence: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verification_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;confidence&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;. Details: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verification_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;details&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)]))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;investigator_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InvestigatorAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;InvestigatorAgent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;image_verification_tool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verify_image_authenticity&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-2-the-reasoning-agent--policy-driven-next-best-action&quot;&gt;Step 2: The Reasoning Agent — Policy-Driven Next-Best-Action&lt;/h2&gt;

&lt;p&gt;Once the authenticity of the evidence is assessed, the core task of claims processing begins: understanding the claim details in light of company policies to determine the appropriate course of action. Our Reasoning Agent excels here, combining document analysis with intelligent policy retrieval.&lt;/p&gt;

&lt;p&gt;It uses two main tools/capabilities:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A simulated retrieve_policy_documents tool: In a real implementation, this would connect to a &lt;a href=&quot;https://docs.cloud.google.com/vertex-ai/docs/vector-search/overview&quot;&gt;Vector AI Search&lt;/a&gt; database. This tool dynamically fetches relevant policy clauses or guidelines based on the claim type and details.&lt;/li&gt;
  &lt;li&gt;An LlmAgent: Leveraging a powerful LLM, it processes the claim narrative, the retrieved policy documents, and any fraud flags from the Investigator Agent to recommend a precise “Next-Best-Action.”&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Continuing in agent.py...
# --- Pydantic Schemas ---
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ClaimDetails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;claim_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The unique identifier for the claim.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;claim_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;auto&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;medical&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The type of the insurance claim.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;A brief description of the incident.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;policy_number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The policy number associated with the claim.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;reported_damage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Details of the reported damage or loss.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NextBestAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;recommended_action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The recommended next step for claims processing.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;reason&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The reasoning behind the recommended action, citing policy context.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;urgency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;low&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;medium&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;high&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The urgency level of the recommended action.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;flag_for_human_review&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;True if human review is strongly recommended, otherwise False.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# --- Tools ---
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;retrieve_policy_documents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;claim_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;relevant_keywords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Retrieves relevant policy documents or clauses from a Vector AI Search database.
    Args:
        claim_type: The type of claim (e.g., &quot;auto&quot;, &quot;home&quot;, &quot;medical&quot;).
        relevant_keywords: Keywords extracted from the claim description to find matching policies.
    Returns:
        dict: A dictionary containing &apos;status&apos;, &apos;policies_found&apos; (list of relevant policy texts), and &apos;details&apos;.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;--- Tool: retrieve_policy_documents called for claim_type: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;claim_type&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, keywords: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;relevant_keywords&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; ---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Simulate Vector AI Search lookup
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;fraud&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;relevant_keywords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;policies_found&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;                &lt;span class=&quot;s&quot;&gt;&quot;Policy-FRAUD-001: All claims with a &apos;fraud_flag&apos; must undergo secondary review by a senior adjuster.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;Policy-INVESTIGATION-005: Deepfake or AI-generated evidence requires immediate claim suspension and referral to the special investigations unit.&quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Anti-fraud policies retrieved based on keywords.&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;claim_type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;auto&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;accident&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;relevant_keywords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;policies_found&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;                &lt;span class=&quot;s&quot;&gt;&quot;Policy-AUTO-010: Auto accident claims require a police report and damage assessment.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;Policy-PAYOUT-003: Minor damage claims (&amp;lt; $5000) can be fast-tracked for approval.&quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Auto accident policies retrieved.&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;policies_found&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;General Policy-001: Process all claims fairly and promptly.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;General policies retrieved.&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# --- Agents ---
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reasoning_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ReasoningAgent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gemini-2.5-flash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Using a powerful model for complex reasoning
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;retrieve_policy_documents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    You are a highly experienced Claims Adjuster AI. Your task is to analyze claim details
    and policy documents to recommend the &quot;Next-Best-Action&quot; for a claim.
    The session state contains &apos;claim_details&apos;, &apos;evidence_status&apos;, and &apos;fraud_flags&apos;.
    1. Extract relevant keywords from &apos;claim_details.description&apos;.
    2. Use the &apos;retrieve_policy_documents&apos; tool with &apos;claim_details.claim_type&apos; and the extracted keywords.
    3. Carefully review the &apos;claim_details&apos;, &apos;evidence_status&apos;, &apos;fraud_flags&apos;, and the retrieved policies.
    4. Based on this information, determine the single best course of action and provide a clear reasoning.
    5. Your output MUST conform to the &apos;NextBestAction&apos; schema.
    &quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;output_schema&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NextBestAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;output_key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;recommended_action_summary&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-3-orchestrating-the-claims-pipeline&quot;&gt;Step 3: Orchestrating the Claims Pipeline&lt;/h2&gt;

&lt;p&gt;Finally, we integrate both specialized agents into a SequentialAgent. This ensures a deterministic flow where evidence verification always precedes claim analysis and action recommendation.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# The final piece of agent.py
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;claims_processing_pipeline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SequentialAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ClaimsProcessingPipeline&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;A multi-agent pipeline for intelligent insurance claims processing, from deepfake detection to next-best-action recommendations.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sub_agents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;investigator_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reasoning_agent&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;claims_processing_pipeline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;putting-it-all-together-a-runnable-application&quot;&gt;Putting It All Together: A Runnable Application&lt;/h2&gt;

&lt;p&gt;To run this complete claims processing pipeline, follow these steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create the Application Directory:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; claims_processing_app
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Create agent.py:&lt;/strong&gt; Inside the claims_processing_app/ directory, create a file named agent.py and populate it with all the code snippets from the implementation steps above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create a Runner Script (run_pipeline.py):&lt;/strong&gt; In the claims_processing_app/ directory, create a file named run_pipeline.py and populate it with the following code:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;asyncio&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.runners&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.sessions&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemorySessionService&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.genai&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;types&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;agent&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ClaimDetails&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Import root_agent and ClaimDetails from agent.py
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Runs the claims processing pipeline programmatically.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemorySessionService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;claims-session-001&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;claims_demo&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;claims_processing_app&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;agent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Starting Claims Processing Pipeline...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Example 1: Claim with authentic evidence
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--- Running Claim with Authentic Evidence ---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;claim_details_authentic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ClaimDetails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;claim_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;CLAIM-AUTH-789&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;claim_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;auto&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Minor fender bender, damage to front bumper.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;policy_number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;POL-AUTO-987&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reported_damage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Front bumper dented and scratched.&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;claim_evidence_authentic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;image_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;claim_789_evidence_authentic.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;initial_state_authentic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;claim_details&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;claim_details_authentic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model_dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;claim_evidence&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;claim_evidence_authentic&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Send a message to trigger the pipeline with initial state
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;message_authentic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Process this auto claim with authentic evidence.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Create a new session for this example
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;session_id_authentic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;claims-session-authentic&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id_authentic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initial_state_authentic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run_async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id_authentic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;new_message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message_authentic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;]: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;session_authentic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id_authentic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--- State after Authentic Claim ---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_authentic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Example 2: Claim with AI-generated evidence and potential fraud
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--- Running Claim with AI-Generated Evidence (Potential Fraud) ---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;claim_details_fraud&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ClaimDetails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;claim_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;CLAIM-FRAUD-123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;claim_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;home&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Water damage in kitchen, cause unknown. Evidence image attached.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;policy_number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;POL-HOME-123&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reported_damage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Extensive water damage to kitchen cabinets and flooring.&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;claim_evidence_fraud&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;image_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;claim_123_evidence_fake.jpg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;initial_state_fraud&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;claim_details&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;claim_details_fraud&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model_dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;claim_evidence&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;claim_evidence_fraud&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Send a message to trigger the pipeline with initial state
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;message_fraud&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Process this home claim with potentially fraudulent evidence.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Create a new session for this example
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;session_id_fraud&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;claims-session-fraud&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id_fraud&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;initial_state_fraud&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run_async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id_fraud&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;new_message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message_fraud&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;part&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;]: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;session_fraud&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id_fraud&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--- State after Fraudulent Claim ---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_fraud&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--- CLAIMS PROCESSING COMPLETE ---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;asyncio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Install Dependencies:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a requirements.txt file in claims_processing_app/ with the following content:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# claims_processing_app/requirements.txt&lt;/span&gt;
google-adk
pydantic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Install these dependencies from the claims_processing_app/ directory:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Run the Pipeline:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Execute the pipeline from your project root (e.g., cd claims_processing_app/ then python run_pipeline.py):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python claims_processing_app/run_pipeline.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;execution-output&quot;&gt;Execution Output&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Starting Claims Processing Pipeline...
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; Running Claim with Authentic Evidence &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; Tool: verify_image_authenticity called &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;image_id: claim_789_evidence_authentic.jpg &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;InvestigatorAgent]: Image verification complete. Status: AUTHENTIC, Confidence: 0.99. Details: No signs of tampering or AI generation
 detected.
Warning: there are non-text parts &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the response: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;function_call&apos;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, returning concatenated text result from text parts. Check the fu
ll candidates.content.parts accessor to get the full model response.
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; Tool: retrieve_policy_documents called &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;claim_type: auto, keywords: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;fender bender&apos;&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;&apos;damage&apos;&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;&apos;front bumper&apos;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;PolicyRetrievalAgent]: I have retrieved the policy documents based on the claim details. The following policies were found:
- General Policy-001: Process all claims fairly and promptly.
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;RecommendationAgent]: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;recommended_action&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;Initiate damage assessment&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;reason&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;The claim involves reported minor physical damage to a front bumper, and the retrieved policy (General Policy-001) mandat
es processing all claims fairly and promptly. Initiating a damage assessment is the necessary next step to quantify the loss and proce
ed efficiently with the claim.&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;urgency&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;medium&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;flag_for_human_review&quot;&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; State after Authentic Claim &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;claim_details&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;claim_id&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;CLAIM-AUTH-789&quot;&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;claim_type&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;auto&quot;&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;description&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;Minor fender bender, damage to front bumper.&quot;&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;policy_number&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;POL-AUTO-987&quot;&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;reported_damage&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;Front bumper dented and scratched.&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;claim_evidence&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;image_id&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;claim_789_evidence_authentic.jpg&quot;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;retrieved_policies&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;I have retrieved the policy documents based on the claim details. The following policies were found:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;- Gener
al Policy-001: Process all claims fairly and promptly.&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;recommended_action_summary&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;recommended_action&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;Initiate damage assessment&quot;&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;reason&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;The claim involves reported minor physical damage to a front bumper, and the retrieved policy (General Policy-001) mand
ates processing all claims fairly and promptly. Initiating a damage assessment is the necessary next step to quantify the loss and pro
ceed efficiently with the claim.&quot;&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;urgency&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;medium&quot;&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;flag_for_human_review&quot;&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; Running Claim with AI-Generated Evidence &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Potential Fraud&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; Tool: verify_image_authenticity called &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;image_id: claim_123_evidence_fake.jpg &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;InvestigatorAgent]: Image verification complete. Status: AI_GENERATED, Confidence: 0.95. Details: High confidence that the image cont
ains AI-generated elements consistent with deepfake manipulation.
Warning: there are non-text parts &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the response: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;function_call&apos;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, returning concatenated text result from text parts. Check the fu
ll candidates.content.parts accessor to get the full model response.
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; Tool: retrieve_policy_documents called &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;claim_type: home, keywords: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;water damage&apos;&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;&apos;kitchen&apos;&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;&apos;unknown cause&apos;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;PolicyRetrievalAgent]: Policy documents have been retrieved. The retrieved policies include: &lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;General Policy-001: Process all claim
s fairly and promptly.&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;,
  &quot;&lt;/span&gt;recommended_action_summary&lt;span class=&quot;s2&quot;&gt;&quot;: {
    &quot;&lt;/span&gt;recommended_action&lt;span class=&quot;s2&quot;&gt;&quot;: &quot;&lt;/span&gt;Initiate fraud investigation&lt;span class=&quot;s2&quot;&gt;&quot;,
    &quot;&lt;/span&gt;reason&lt;span class=&quot;s2&quot;&gt;&quot;: &quot;&lt;/span&gt;The claim has been explicitly flagged &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;fraud, and the description of &lt;span class=&quot;s1&quot;&gt;&apos;unknown cause&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;water damage further warran
ts a thorough investigation to determine the legitimacy of the claim before proceeding with standard processing. This aligns with the 
principle of fair processing by preventing fraudulent payouts.&lt;span class=&quot;s2&quot;&gt;&quot;,
    &quot;&lt;/span&gt;urgency&lt;span class=&quot;s2&quot;&gt;&quot;: &quot;&lt;/span&gt;high&lt;span class=&quot;s2&quot;&gt;&quot;,
    &quot;&lt;/span&gt;flag_for_human_review&lt;span class=&quot;s2&quot;&gt;&quot;: true
  }
}
--- CLAIMS PROCESSING COMPLETE ---
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusion-augmenting-adjusters-fortifying-defenses&quot;&gt;Conclusion: Augmenting Adjusters, Fortifying Defenses&lt;/h2&gt;

&lt;p&gt;The landscape of insurance claims is evolving rapidly, demanding solutions that are both efficient and resilient against new threats. The intelligent agent pipeline presented here — featuring an Investigator Agent for deepfake detection and a Reasoning Agent for next-best-action recommendations — transforms traditional claims processing.&lt;/p&gt;

&lt;p&gt;By leveraging the Google Agent Development Kit, coupled with advanced capabilities like SynthID, Vector AI Search, and Computer Vision, we move claims adjusters from reactive, manual data processors to proactive, strategic decision-makers. This architecture not only accelerates legitimate payouts and enhances customer satisfaction but also fortifies defenses against increasingly sophisticated fraudulent activities.&lt;/p&gt;

&lt;p&gt;This is more than automation; it is an augmentation of human expertise, empowering adjusters with AI-driven insights to navigate complexity, ensure fairness, and uphold the integrity of the insurance ecosystem. The future of claims processing is intelligent, secure, and decisive.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To explore more multi-agent patterns, check out the&lt;/em&gt; &lt;a href=&quot;https://github.com/google/adk-samples&quot;&gt;&lt;em&gt;Google Agent Development Kit (ADK) samples&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate>
				<link>https://ppiconsulting.dev//blog/blog97/</link>
				<guid isPermaLink="true">https://ppiconsulting.dev//blog/blog97/</guid>
			</item>
		
			<item>
				<title>The Next-Gen Underwriter, Accelerating Quotes with Document Intelligence</title>
				<description>&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2752/format:webp/1*oeyQpCwJyGrdVSeTcFsV8g.jpeg&quot; alt=&quot;Accelerating Quotes with Document Intelligence (Image by Author).&quot; /&gt;&lt;br /&gt;Accelerating Quotes with Document Intelligence (Image by Author).&lt;/p&gt;

&lt;!--end_excerpt--&gt;

&lt;h2 id=&quot;the-next-gen-underwriter-accelerating-quotes-with-document-intelligence&quot;&gt;The Next-Gen Underwriter: Accelerating Quotes with Document Intelligence&lt;/h2&gt;

&lt;table&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;td align=&quot;left&quot;&gt;
        :memo:   Please Note
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;

    &lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;
        &lt;ul&gt;
            This is a guest post originally published on &lt;a href=&quot;https://medium.com/google-cloud/the-next-gen-underwriter-accelerating-quotes-with-document-intelligence-c76f03164b1a&quot; target=&quot;_blank&quot;&gt;Google Cloud - Community&lt;/a&gt;.
        &lt;/ul&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;a-multi-agent-framework-for-instant-data-extraction-and-premium-calculation-with-google-adk&quot;&gt;A Multi-Agent Framework for Instant Data Extraction and Premium Calculation with Google ADK&lt;/h2&gt;

&lt;p&gt;In the hyper-competitive insurance market, speed is the ultimate currency. The carrier that delivers an accurate quote first often wins the business. Yet, for decades, the underwriting process has been anchored by a manual, time-intensive task: extracting data from a mountain of disparate documents. Underwriters, who should be focused on strategic risk assessment, are instead mired in the operational quicksand of data entry, toggling between ACORD forms, prior carrier policies, and vehicle registration PDFs.&lt;/p&gt;

&lt;p&gt;This manual data entry introduces significant latency into the quoting pipeline. In a market where response time directly correlates with conversion rates, this latency translates to lost business. The objective is to re-architect this pipeline, replacing human data-transfer steps with a deterministic, automated system.&lt;/p&gt;

&lt;p&gt;This article details how to build a GenAI-powered agent system that automates the quoting pipeline. Using the Google Agent Development Kit (ADK), Gemini 2.5, and principles of multi-agent design, we will construct a system that can instantly classify complex policy documents, extract key data points, and generate a comparable quote in seconds. This is how we shift the underwriter’s role from data processor to strategic analyst.&lt;/p&gt;

&lt;h2 id=&quot;the-framework-google-agent-development-kit-adk&quot;&gt;The Framework: Google Agent Development Kit (ADK)&lt;/h2&gt;

&lt;p&gt;To build a system this complex, we need more than a simple LLM API call. We require a framework that supports stateful, auditable, and production-ready workflows. The Google ADK is designed for this purpose. It provides the core primitives to build sophisticated agentic systems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Agents:&lt;/strong&gt; Specialized, intelligent units that perform specific tasks. We will use LlmAgent for complex reasoning and SequentialAgent to orchestrate the workflow deterministically.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;State Management:&lt;/strong&gt; The ADK provides a Session object with a shared state dictionary. This allows different agents to communicate and pass data — like a customer’s VIN or their prior coverage limits — seamlessly through the pipeline.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tools:&lt;/strong&gt; Agents can be given capabilities beyond text generation. As we’ll see, agents can use tools — which are simple Python functions — to interact with external data sources or logic, like a pricing engine.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Structured Output:&lt;/strong&gt; ADK’s integration with Pydantic allows us to force an LLM to output clean, validated JSON. This is the key to creating reliable, actionable data for downstream processes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-architecture-a-more-realistic-quoting-pipeline&quot;&gt;The Architecture: A More Realistic Quoting Pipeline&lt;/h2&gt;

&lt;p&gt;Our goal is to automate the cognitive sequence a human underwriter follows. For our improved example, this process now includes reading from a directory of document files and using a dedicated tool to calculate the premium. The agent flow is as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;The Document Ingestion Agent:&lt;/strong&gt; Reads a directory of application documents (e.g., ACORD forms, vehicle registrations) from the file system.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Data Extraction Agent:&lt;/strong&gt; Parses the content of all documents to extract key data points into a structured format.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Premium Calculation Agent:&lt;/strong&gt; Uses a calculate_premium_tool to determine the policy price based on the extracted data.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Quote Formatting Agent:&lt;/strong&gt; Assembles the final quote from all the data gathered in the previous steps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2000/format:webp/1*ZI_jCfHooeC04wC-bhpzsA.png&quot; alt=&quot;Figure 1: System Architecture (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 1: System Architecture (Image by Author).&lt;/p&gt;

&lt;h2 id=&quot;step-1-the-ingestion-agent&quot;&gt;Step 1: The Ingestion Agent&lt;/h2&gt;

&lt;p&gt;First, we create text files to simulate the underwriting documents. Then, our &lt;em&gt;DocumentIngestionAgent&lt;/em&gt; reads all files from a &lt;em&gt;./documents&lt;/em&gt; directory and loads their content into the session state. This is more realistic than hardcoding the text in the agent itself.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# In agent.py
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;asyncio&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydantic&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BaseModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AsyncGenerator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.agents&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SequentialAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BaseAgent&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.agents.invocation_context&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InvocationContext&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.events&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.genai&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;types&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DocumentIngestionAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Reads all documents from the specified directory into the session state.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_run_async_impl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InvocationContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AsyncGenerator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;doc_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__file__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;documents&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;docs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;doc_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;file_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;doc_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;r&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;docs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;doc_type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        
        &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;documents&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;docs&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Ingested and classified &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;docs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; documents.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ingestion_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DocumentIngestionAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DocumentSorter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-2-the-extraction-and-quoting-agents&quot;&gt;Step 2: The Extraction and Quoting Agents&lt;/h2&gt;

&lt;p&gt;With the documents in the session state, the DataExtractor agent can parse them. The key change is in the quoting logic. We now have a dedicated &lt;em&gt;calculate_premium_tool&lt;/em&gt; that acts as a mini rating engine. A &lt;em&gt;QuoteCalculator&lt;/em&gt; agent is responsible for calling this tool, and a final &lt;em&gt;QuoteFormatter&lt;/em&gt; agent assembles all the pieces into the structured output. This separation of concerns (tool use vs. formatting) is a critical ADK pattern.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Continuing in agent.py...
# --- Tool Definition ---
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calculate_premium_tool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vehicle_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prior_bodily_injury_coverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Calculates a monthly premium based on vehicle and prior coverage.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;base_premium&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;150.0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Tesla&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vehicle_model&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Rivian&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vehicle_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;base_premium&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;25.0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;$300k&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prior_bodily_injury_coverage&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;$500k&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prior_bodily_injury_coverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;base_premium&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;10.0&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Discount for higher prior limits
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;monthly_premium&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base_premium&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# --- Pydantic Schemas ---
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ExtractedQuoteData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Data structure for underwriting quote generation.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;applicant_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The full name of the applicant.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The Vehicle Identification Number.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vehicle_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The make and model of the vehicle.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;prior_bodily_injury_coverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Prior policy&apos;s bodily injury coverage, e.g., &apos;$100k/$300k&apos;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;prior_property_damage_coverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Prior policy&apos;s property damage coverage, e.g., &apos;$50k&apos;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Quote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Final quote structure.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;applicant_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;proposed_coverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;monthly_premium&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# --- Agent Definitions ---
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data_extractor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;DataExtractor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gemini-2.5-pro&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;You are a specialized data extraction agent... Your output MUST be a single, raw JSON object that validates against the schema.&quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Instruction omitted for brevity
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;output_schema&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ExtractedQuoteData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;output_key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;extracted_data&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;quote_calculator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;QuoteCalculator&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gemini-2.5-flash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calculate_premium_tool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    You are a premium calculation agent.
    Use the `calculate_premium_tool` to determine the monthly premium based on the vehicle model and prior coverage from the `{extracted_data}`.
    The tool will return a dictionary like {&quot;monthly_premium&quot;: 165.0}. Your output should be ONLY the numeric value, like 165.0.
    &quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;output_key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;monthly_premium&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;quote_formatter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;QuoteFormatter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gemini-2.5-flash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    You are a formatting agent.
    Take the `{extracted_data}` and the calculated `{monthly_premium}` from the session state.
    Format the final output into the `Quote` schema. The proposed coverage should match the prior policy&apos;s coverage levels.
    &quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;output_schema&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Quote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;output_key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;final_quote&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-3-orchestrating-the-pipeline&quot;&gt;Step 3: Orchestrating the Pipeline&lt;/h2&gt;

&lt;p&gt;Finally, we update our &lt;em&gt;SequentialAgent&lt;/em&gt; to include all four agents in the correct order.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# The final piece of agent.py
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;underwriting_pipeline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SequentialAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;UnderwritingPipeline&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;A multi-agent pipeline to automate insurance quoting.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sub_agents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;ingestion_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;data_extractor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;quote_calculator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;quote_formatter&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;underwriting_pipeline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;example-input-documents&quot;&gt;Example Input Documents&lt;/h3&gt;

&lt;p&gt;To make the example runnable, here is the content for the three sample documents that our agent will read. In a real workflow, an underwriter receives a bundle of such documents, each serving a distinct purpose. These files should be placed in the &lt;em&gt;underwriting_app/documents/&lt;/em&gt; directory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;acord_125.json&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This represents a snippet from an ACORD 125 form, the standard commercial insurance application. For an underwriter, this is the foundational document containing the applicant’s basic information and insurance history. Our agent will use it to identify the applicant’s name and prior carrier details.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ACORD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;form_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ACORD 125&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sections&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;section_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;APPLICANT INFORMATION&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;APPLICANT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;John &apos;Johnny&apos; Doe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ADDRESS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;123 Main St, Anytown, USA 12345&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;PHONE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;555-123-4567&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;section_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;PRIOR CARRIER&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fields&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;CARRIER_NAME&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;XYZ Insurance Co.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;POLICY_NO&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ABC987654321&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;EXPIRATION_DATE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2025-12-01&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;vehicle_registration.txt&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a simplified vehicle registration document. It serves as official proof of the vehicle’s identity (make, model, year) and, crucially, its Vehicle Identification Number (VIN). An underwriter relies on this to confirm the exact vehicle being insured.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;VEHICLE IDENTIFICATION REPORT
--------------------------------
VIN: 1A2B3C4D5E6F
MAKE: Tesla
MODEL: Model Y Long Range
YEAR: 2023
REGISTERED_OWNER: John Doe
ADDRESS: 123 Main St, Anytown, USA
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;prior_policy.txt&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This file contains the declarations page from the applicant’s previous insurance policy. For an underwriter, this is a key document for competitive quoting. It reveals the applicant’s existing coverage limits, which our agent will use as a baseline to generate a comparable quote.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;PRIOR POLICY DECLARATIONS - XYZ INSURANCE CO.
POLICY #: ABC987654321
NAMED INSURED: John Doe
COVERAGES:
- Bodily Injury Liability: $100,000 Each Person / $300,000 Each Accident
- Property Damage Liability: $50,000 Each Accident
- Uninsured Motorist: $100,000/$300,000
VEHICLE: 2023 Tesla Model Y - VIN: 1A2B3C4D5E6F
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;putting-it-all-together-a-runnable-application&quot;&gt;Putting It All Together: A Runnable Application&lt;/h2&gt;

&lt;p&gt;To run this full, realistic pipeline, follow these steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create the Application Directory:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; underwriting_app/documents
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Create the Document Files:&lt;/strong&gt; Create the three document files inside &lt;em&gt;underwriting_app/documents/&lt;/em&gt; with the content from the beginning of this section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create the agent.py file&lt;/strong&gt; inside &lt;em&gt;underwriting_app/&lt;/em&gt; with all the code from the implementation steps above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create a Runner Script (run_pipeline.py):&lt;/strong&gt; In the &lt;em&gt;underwriting_app&lt;/em&gt; directory, create this file to execute the agent.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# underwriting_app/run_pipeline.py
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;asyncio&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.runners&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.sessions&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemorySessionService&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.genai&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;types&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;agent&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Import the root_agent from agent.py
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Runs the full underwriting pipeline programmatically.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemorySessionService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;quote-session-001&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;underwriter_demo&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;underwriting_app&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;agent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Starting Underwriting Quote Pipeline...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run_async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;new_message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Start the quote generation process.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;]: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;final_quote&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;final_quote&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--- QUOTE GENERATION COMPLETE ---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;final_quote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final_quote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;asyncio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Run the Pipeline:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Install dependencies
pip install google-adk==1.4.2 pydantic
# Run the pipeline from your project root
python underwriting_app/run_pipeline.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;execution-output&quot;&gt;Execution Output&lt;/h2&gt;

&lt;p&gt;Running the new, more realistic pipeline produces the following output. Note the discount applied by the &lt;em&gt;calculate_premium_tool&lt;/em&gt; for the good prior coverage.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Starting Underwriting Quote Pipeline...
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;DocumentSorter]: Ingested and classified 3 documents.
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;DataExtractor]: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&quot;applicant_name&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;John Doe&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;vin&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;1A2B3C4D5E6F&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;vehicle_model&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;Tesla Model Y Long Range&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;prior_bodily_injury_coverage&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$100&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,000 Each Person / &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$300&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,000 Each Accident&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;prior_property_damage_coverage&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$50&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,000 Each Accident&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
Warning: there are non-text parts &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the response: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;function_call&apos;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, returning concatenated text result from text parts. Check the full candidates.content.parts accessor to get the full model response.
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;QuoteCalculator]: 165.0
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;QuoteFormatter]: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;applicant_name&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;John Doe&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;vin&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;1A2B3C4D5E6F&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;proposed_coverage&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;Bodily Injury: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$100k&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$300k&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, Property Damage: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$50k&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;monthly_premium&quot;&lt;/span&gt;: 165.0
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; QUOTE GENERATION COMPLETE &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;applicant_name&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;John Doe&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;vin&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;1A2B3C4D5E6F&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;proposed_coverage&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;Bodily Injury: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$100k&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$300k&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, Property Damage: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$50k&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&quot;monthly_premium&quot;&lt;/span&gt;: 165.0
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;from-local-test-to-production-service&quot;&gt;From Local Test to Production Service&lt;/h2&gt;

&lt;p&gt;For production, this agent can be deployed as a secure, scalable API on Google Cloud Run. This serverless environment ensures that you only pay for what you use, and combined with Vertex AI’s security guarantees, it ensures that sensitive customer data remains within your cloud environment and is never used for model training.&lt;/p&gt;

&lt;h2 id=&quot;conclusion-augmenting-not-replacing-the-expert&quot;&gt;Conclusion: Augmenting, Not Replacing, the Expert&lt;/h2&gt;

&lt;p&gt;The output of this pipeline is not designed to autonomously bind policies. It is designed to feed a “human-in-the-loop” UI. The underwriter is presented with the source documents and the AI-extracted data side-by-side, along with the generated quote. Their role shifts from data collector to data verifier and strategic decision-maker. They are now empowered to process more quotes, faster, and with greater accuracy.&lt;/p&gt;

&lt;p&gt;By breaking down the complex cognitive workflow of underwriting into a series of specialized tasks for AI agents, we can achieve a profound increase in efficiency. We’ve used Gemini 2.5 Pro for the heavy-lifting of data extraction and the nimble Gemini 2.5 Flash for the final formatting — an “Economy of Intelligence” pattern that optimizes for both performance and cost.&lt;/p&gt;

&lt;p&gt;This architecture moves the underwriter from the back office to the front lines of competitive advantage, armed with the speed and intelligence of GenAI.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To explore more multi-agent patterns, check out the&lt;/em&gt; &lt;a href=&quot;https://github.com/google/adk-samples&quot;&gt;&lt;em&gt;Google Agent Development Kit (ADK) samples&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 31 Jan 2026 00:00:00 +0000</pubDate>
				<link>https://ppiconsulting.dev//blog/blog96/</link>
				<guid isPermaLink="true">https://ppiconsulting.dev//blog/blog96/</guid>
			</item>
		
			<item>
				<title>Automating Regulatory Compliance using AI Agents to Streamline Document Audits</title>
				<description>&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2752/format:webp/1*6iR6k1hT5g1w4Px_gRO24g.jpeg&quot; alt=&quot;How AI Agents Streamline Document Audits (Image by Author).&quot; /&gt;&lt;br /&gt;How AI Agents Streamline Document Audits (Image by Author).&lt;/p&gt;

&lt;!--end_excerpt--&gt;

&lt;h2 id=&quot;automating-regulatory-compliance-how-ai-agents-streamline-document-audits&quot;&gt;Automating Regulatory Compliance: How AI Agents Streamline Document Audits&lt;/h2&gt;

&lt;table&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;td align=&quot;left&quot;&gt;
        :memo:   Please Note
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;

    &lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;
        &lt;ul&gt;
            This is a guest post originally published on &lt;a href=&quot;https://medium.com/google-cloud/automating-regulatory-compliance-how-ai-agents-streamline-document-audits-ab93c0a734c2&quot; target=&quot;_blank&quot;&gt;Google Cloud - Community&lt;/a&gt;.
        &lt;/ul&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;an-end-to-end-blueprint-using-google-agent-development-kit-adk&quot;&gt;An end to end blueprint using Google Agent Development Kit (ADK)&lt;/h2&gt;

&lt;p&gt;In the insurance industry, the distance between a finalized product and its market launch is often measured not in days, but in regulatory hurdles. For underwriters, this reality creates a distinct tension: their expertise lies in assessing risk, yet a significant portion of their bandwidth is consumed by the “red tape” of compliance: checking font sizes on disclosure forms, verifying state-specific clauses, and ensuring terminology alignment across hundred-page documents.&lt;/p&gt;

&lt;p&gt;This manual review process is a bottleneck. It is performant only in its ability to slow down business. Errors here are costly, leading to submission rejections and delays that are measured in months. It is an inefficiency ripe for automation.&lt;/p&gt;

&lt;p&gt;The solution is not to train underwriters to be better proofreaders. It is to architect a system that treats compliance as a computable task. In this article, we explore how we built an AI-powered “Auditor Agent” system using the Google Agent Development Kit (ADK) and Gemini 2.5. By chaining specialized agents together, we can automate the rigorous, repetitive work of regulatory review, freeing human experts to focus on the nuance of risk.&lt;/p&gt;

&lt;h2 id=&quot;the-toolkit-google-agent-development-kit-adk&quot;&gt;The Toolkit: Google Agent Development Kit (ADK)&lt;/h2&gt;

&lt;p&gt;Before diving into the architecture, it is helpful to understand the framework powering this solution. The Google ADK is a Python-first framework designed to bridge the gap between simple LLM prototypes and production-grade systems.&lt;/p&gt;

&lt;p&gt;Unlike basic API wrappers, ADK provides the architectural primitives necessary for complex, stateful workflows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Agents:&lt;/strong&gt; The core decision-makers. In our example, we use LlmAgent for tasks requiring reasoning (like the Auditor) and SequentialAgent for defining deterministic workflows (the Pipeline).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Runners:&lt;/strong&gt; The execution engine that manages the event loop. The Runner handles the flow of messages between the user, the agents, and the tools, ensuring that execution is robust and observable.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Sessions &amp;amp; State:&lt;/strong&gt; A persistent memory layer. The ADK’s Session object maintains a shared state dictionary, allowing different agents in a chain to access the same data (such as the policy text) without needing to pass it manually in every prompt.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Web Interface:&lt;/strong&gt; A built-in local UI (&lt;em&gt;adk web&lt;/em&gt;) for debugging and visual tracing. It allows developers to “open the black box” and watch agents reason, call tools, and update state in real-time — a critical feature for debugging multi-agent chains.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-architecture-a-multi-agent-approach&quot;&gt;The Architecture: A Multi-Agent Approach&lt;/h2&gt;

&lt;p&gt;We cannot simply ask an LLM to “check this document.” Compliance is too complex for a single prompt. It requires reading a draft, understanding specific regulatory rulebooks (which vary by state), identifying violations, and citing them precisely.&lt;/p&gt;

&lt;p&gt;To solve this, we employ a &lt;strong&gt;Multi-Agent System&lt;/strong&gt; orchestrated by the ADK. We break the workflow into three distinct cognitive tasks, each handled by a specialized agent:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;The Ingestion Agent:&lt;/strong&gt; (Simulated) A custom BaseAgent that injects a hardcoded policy document into the session state for demo purposes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Compliance Auditor (The Core):&lt;/strong&gt; Compares the extracted text against a strict set of regulatory guidelines using Gemini 2.5 Pro.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Report Generator:&lt;/strong&gt; Synthesizes the findings into a structured tabular format for the human underwriter.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We use ADK’s SequentialAgent to chain these steps into a deterministic pipeline (Figure 1).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2000/format:webp/1*Y8CSOliA4U_Qh9Lj9TcWtA.png&quot; alt=&quot;Figure 1: Multi-Agent System (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 1: Multi-Agent System (Image by Author).&lt;/p&gt;

&lt;h2 id=&quot;step-1-defining-the-compliance-auditor&quot;&gt;Step 1: Defining the Compliance Auditor&lt;/h2&gt;

&lt;p&gt;The heart of our system is the ComplianceAuditor agent. We use Gemini 2.5 Pro for this task because of its massive context window and ability to reason through complex logical constraints.&lt;/p&gt;

&lt;p&gt;Notice the precision in the instruction below. We do not ask the agent to “read and summarize.” We instruct it to act as a hostile auditor, specifically looking for failures. We also configure it with a low temperature to ensure deterministic, factual outputs.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.agents&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;  
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.genai&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;types&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Define the configuration for deterministic output  
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen_config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GenerateContentConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;  
    &lt;span class=&quot;n&quot;&gt;temperature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Low temperature for strict adherence to rules  
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;top_p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;compliance_auditor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ComplianceAuditor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gemini-2.5-pro&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;generate_content_config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gen_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    You are a Senior Regulatory Compliance Officer for an insurance carrier.
    Your task is to audit the provided &apos;policy_text&apos; against the following guidelines:
    - [NY-204-B] Policy validity period must be at least 60 days.
    - [NY-300-A] Digital claims submission options must be provided.
    - [GEN-001] Cancellation requires 30-day notice.
    **CRITICAL RULES:**
    1.  **Citation is Mandatory:** You must quote the exact text from the policy that violates a rule.
    2.  **Binary Assessment:** For every guideline, the status is either PASS, FAIL, or NOT_FOUND.
    3.  **No Hallucinations:** If a rule is not mentioned in the text, mark it as &apos;NOT FOUND&apos;.
    Input Data:
    - Policy Text: {policy_text}
    Output the audit findings as a structured list of violations.
    &quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;output_key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;audit_findings&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-2-structured-output-for-actionability&quot;&gt;Step 2: Structured Output for Actionability&lt;/h2&gt;

&lt;p&gt;An agent’s insight is useless if it cannot be integrated into a downstream workflow. A free-text paragraph describing errors is hard to process programmatically.&lt;/p&gt;

&lt;p&gt;To solve this, we enforce a strict schema on the output. In ADK, we can define a Pydantic model to force the LLM to return structured JSON. This allows our application to render the results directly into a UI dashboard or a CSV file without complex parsing logic.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydantic&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BaseModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;  
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Violation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;rule_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The ID of the regulation violated (e.g., &apos;NY-204-B&apos;).&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;PASS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FAIL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;NOT_FOUND&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;quoted_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;The exact text from the document triggering the violation.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;remediation_suggestion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Specific instructions on how to fix the text.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AuditReport&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;policy_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;violations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Violation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;overall_risk_score&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;A score from 0-100 indicating compliance health.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Apply this schema to a Reporting Agent  
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;report_generator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;  
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ReportGenerator&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;gemini-2.5-flash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Flash is sufficient for formatting tasks  
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;  
    Format the raw &apos;audit_findings&apos; from the previous agent into a strict JSON object that validates against the &apos;AuditReport&apos; schema.
    Use the &apos;policy_id&apos; from the session state.
    Calculate an &apos;overall_risk_score&apos; based on the number and severity of failures. A higher score means more risk.
    - 0 findings = 0 score.
    - 1 finding = 50 score.
    - 2 findings = 75 score.
    - 3 or more findings = 95 score.
    &quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;n&quot;&gt;output_schema&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AuditReport&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;n&quot;&gt;output_key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;final_json_report&quot;&lt;/span&gt;  
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-3-orchestration-with-sequentialagent&quot;&gt;Step 3: Orchestration with SequentialAgent&lt;/h2&gt;

&lt;p&gt;Finally, we bind these components together. The SequentialAgent primitive in ADK allows us to pass the state (the document text, the guidelines, and the intermediate findings) from one agent to the next.&lt;/p&gt;

&lt;p&gt;The ingestion_agent runs as the first step in the pipeline. It populates session.state[“policy_text”], making the document available to the subsequent agents in the sequence.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.agents&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SequentialAgent&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;auditor_pipeline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SequentialAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;  
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AutomatedAuditPipeline&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Ingests a policy document and produces a structured compliance report.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  
    &lt;span class=&quot;n&quot;&gt;sub_agents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;  
        &lt;span class=&quot;n&quot;&gt;ingestion_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Loads text into state  
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;compliance_auditor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Analyzes text against guidelines  
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;report_generator&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Formats output to JSON  
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-4-execution-with-vertex-ai&quot;&gt;Step 4: Execution with Vertex AI&lt;/h2&gt;

&lt;p&gt;To run this pipeline in a production environment, we use the Runner class. This handles the event loop and state management. Crucially, we configure the environment to use Vertex AI, ensuring enterprise-grade security and scalability.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;asyncio&lt;/span&gt;  
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;  
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.runners&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;  
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.sessions&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemorySessionService&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;Runs the full compliance audit pipeline.&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;use_vertex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GOOGLE_GENAI_USE_VERTEXAI&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;False&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;use_vertex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;INFO: Using Vertex AI for generative models.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GOOGLE_CLOUD_PROJECT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GOOGLE_CLOUD_LOCATION&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERROR: GOOGLE_CLOUD_PROJECT and GOOGLE_CLOUD_LOCATION must be set for Vertex AI.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;INFO: Using Google AI Studio. Set GOOGLE_API_KEY environment variable.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;environ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GOOGLE_API_KEY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERROR: GOOGLE_API_KEY must be set for AI Studio.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InMemorySessionService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;audit-session-001&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;underwriter_demo&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;audit_app&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;agent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auditor_pipeline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Starting Compliance Audit Pipeline...&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;final_event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run_async&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;new_message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Start the audit.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_final_response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;final_event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;]: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;]: (No text content)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;final_report&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;final_json_report&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;--- AUDIT COMPLETE ---&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;final_report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final_report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Overall Risk Score: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final_report&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;overall_risk_score&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERROR: Final JSON report not found in session state.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;final_event&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;final_event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error_message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;REASON: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final_event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error_message&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;__main__&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# To run this script, you must first authenticate and set your project:
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# 1. `pip install google-adk==1.4.2 google-genai pydantic`
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# 2. `gcloud auth application-default login`
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# 3. `export GOOGLE_CLOUD_PROJECT=&quot;your-gcp-project-id&quot;`
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# 4. `export GOOGLE_CLOUD_LOCATION=&quot;us-central1&quot;`
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# 5. `export GOOGLE_GENAI_USE_VERTEXAI=&quot;True&quot;`
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# 6. `python compliance_audit.py`
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;asyncio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;running-the-example&quot;&gt;Running the Example&lt;/h2&gt;

&lt;p&gt;To see this pipeline in action, you can run the code locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt; Ensure you have Python installed, along with the necessary libraries:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install google-adk==1.4.2 google-genai pydantic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Authentication (Vertex AI):&lt;/strong&gt; Authenticate using the Google Cloud CLI and set your project details. This is preferred for production environments over using raw API keys. &lt;strong&gt;Crucially, ensure these environment variables are correctly set and active in your shell before execution to avoid Missing key inputs argument errors.&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Login to Google Cloud  
gcloud auth application-default login
# Set your project ID and location  
export GOOGLE_CLOUD_PROJECT=&quot;your-project-id&quot;  
export GOOGLE_CLOUD_LOCATION=&quot;us-central1&quot;
# Instruct ADK to use Vertex AI  
export GOOGLE_GENAI_USE_VERTEXAI=&quot;True&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Execution:&lt;/strong&gt; Run the script with all the code snippets directly to see the console output.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python compliance_audit.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Visual Debugging (Optional):&lt;/strong&gt; For larger projects structured with the ADK standard layout, you can use the built-in web interface too (Figure 2):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adk web .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2000/format:webp/1*jgkgsidGJgSOHlRX8TSqXg.png&quot; alt=&quot;Figure 2: ADK Web (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 2: ADK Web (Image by Author).&lt;/p&gt;

&lt;h2 id=&quot;execution-output&quot;&gt;Execution Output&lt;/h2&gt;

&lt;p&gt;When you run the compliance_audit.py script, you will see the agent pipeline execute in real-time. The final output will be a structured JSON report detailing the compliance failures:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;INFO: Using Vertex AI for generative models.
Starting Compliance Audit Pipeline...
[IngestionAgent]: Policy document ingested.
[ComplianceAuditor]: Guideline [NY-204-B] FAIL. Citation: &quot;This policy is valid for 30 days from the date of issue.&quot;
Guideline [GEN-001] FAIL. Citation: &quot;We reserve the right to cancel this policy at any time by providing a 15-day written notice to the policyholder.&quot;
[ReportGenerator]: {
  &quot;policy_id&quot;: &quot;POLICY-XYZ&quot;, 
  &quot;violations&quot;: [
    {&quot;rule_id&quot;: &quot;NY-204-B&quot;, &quot;status&quot;: &quot;FAIL&quot;, &quot;quoted_text&quot;: &quot;text...&quot;}, 
    {&quot;rule_id&quot;: &quot;GEN-001&quot;, &quot;status&quot;: &quot;FAIL&quot;, &quot;quoted_text&quot;: &quot;text...&quot;}
  ], 
  &quot;overall_risk_score&quot;: 75
}
--- AUDIT COMPLETE ---
{
  &quot;policy_id&quot;: &quot;POLICY-XYZ&quot;,
  &quot;violations&quot;: [
    {
      &quot;rule_id&quot;: &quot;NY-204-B&quot;,
      &quot;status&quot;: &quot;FAIL&quot;,
      &quot;quoted_text&quot;: &quot;This policy is valid for 30 days from the date of issue.&quot;,
      &quot;remediation_suggestion&quot;: &quot;Review and revise the policy text to comply with the regulation NY-204-B.&quot;
    },
    {
      &quot;rule_id&quot;: &quot;GEN-001&quot;,
      &quot;status&quot;: &quot;FAIL&quot;,
      &quot;quoted_text&quot;: &quot;We reserve the right to cancel this policy at any time by providing a 15-day written notice to the policyholder.&quot;,
      &quot;remediation_suggestion&quot;: &quot;Review and revise the policy text to comply with the regulation GEN-001.&quot;
    }
  ],
  &quot;overall_risk_score&quot;: 75
}
Overall Risk Score: 75
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;adapting-for-the-adk-web-interface&quot;&gt;Adapting for the ADK Web Interface&lt;/h2&gt;

&lt;p&gt;While running the script directly is useful for batch processing, the ADK’s adk web command provides a powerful interactive UI for debugging and demonstrations. To use it, we need to refactor our script into the standard ADK project structure.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Create the Application Directory:&lt;/strong&gt; Create a folder named audit_app.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Create the Agent File:&lt;/strong&gt; Inside audit_app, create a file named agent.py.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Define the root_agent:&lt;/strong&gt; Move all the Python code (imports, agent definitions, and the pipeline definition) from compliance_audit.py into audit_app/agent.py. The main() function is no longer needed. The only addition is to assign your final pipeline to a special variable named root_agent.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your &lt;em&gt;audit_app/agent.py&lt;/em&gt; file would look like this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;asyncio&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydantic&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BaseModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AsyncGenerator&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.agents&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SequentialAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BaseAgent&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.agents.invocation_context&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InvocationContext&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.events&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.genai&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;types&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genai_types&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# --- All Agent Definitions (IngestionAgent, compliance_auditor, etc.) ---
# ... (paste all class and agent definitions from the script here) ...
# The adk web command looks for this specific variable.
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;auditor_pipeline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With this structure, you can run &lt;em&gt;adk web .&lt;/em&gt; from the root of your project. The tool will discover the audit_app, and you can start an audit by simply typing a message like “Start the audit” into the chat interface. The IngestionAgent will automatically load the hardcoded policy, and the pipeline will execute as before, with the added benefit of a visual trace in the UI.&lt;/p&gt;

&lt;h2 id=&quot;trust-but-verify-evaluating-the-auditor&quot;&gt;Trust, But Verify: Evaluating the Auditor&lt;/h2&gt;

&lt;p&gt;In a regulated industry, “it works on my machine” is not a shipping criteria. We need statistical confidence. How do we know the agent isn’t hallucinating a pass on a faulty policy?&lt;/p&gt;

&lt;p&gt;The ADK includes a dedicated evaluation framework (adk eval). This allows us to define a “Golden Dataset” of policies with known violations and run the agent against them. We can then calculate a &lt;strong&gt;Recall Score&lt;/strong&gt; — specifically, what percentage of &lt;em&gt;actual&lt;/em&gt; violations did the agent catch?&lt;/p&gt;

&lt;p&gt;This shifts the deployment conversation from “I think it works” to “It has a 99.8% detection rate on our NY validation set.”&lt;/p&gt;

&lt;h2 id=&quot;from-script-to-service-production-architecture&quot;&gt;From Script to Service: Production Architecture&lt;/h2&gt;

&lt;p&gt;While the script above runs locally, production requires an API. ADK provides patterns to wrap this Runner in a &lt;strong&gt;FastAPI&lt;/strong&gt; server using the adk api_server command.&lt;/p&gt;

&lt;p&gt;This allows us to deploy the agent as a containerized service on &lt;strong&gt;Google Cloud Run&lt;/strong&gt;. The benefits are three-fold:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Serverless Scaling:&lt;/strong&gt; It scales down to zero when no policies are being audited, saving costs.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Security:&lt;/strong&gt; We can run the agent inside a VPC Service Perimeter, ensuring that sensitive insurance documents never traverse the public internet.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Data Privacy &amp;amp; PII:&lt;/strong&gt; In the insurance sector, data sovereignty is non-negotiable. By leveraging Vertex AI, we ensure that sensitive policyholder data remains within our Google Cloud trust boundary. It is never used to train public models, addressing a primary compliance requirement for FinTech and InsurTech deployments.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;the-human-in-the-loop-pattern&quot;&gt;The “Human-in-the-Loop” Pattern&lt;/h2&gt;

&lt;p&gt;Automation does not mean autonomy. The structured JSON output we generate in Step 2 is not meant to be the final decision-maker. Instead, it feeds into a frontend UI — an “Approval Queue.”&lt;/p&gt;

&lt;p&gt;Here, the underwriter sees the document on the left and the AI’s findings on the right. They can click “Approve” or “Reject” on each finding. This feedback loop does two things: it keeps a human liable for the final decision (a regulatory requirement), and it generates a labelled dataset to fine-tune future versions of the model.&lt;/p&gt;

&lt;h2 id=&quot;from-red-tape-to-risk-analysis&quot;&gt;From Red Tape to Risk Analysis&lt;/h2&gt;

&lt;p&gt;By deploying this architecture, we shift the underwriter’s role. Instead of reading a 50-page document to find that a disclaimer is in 10-point font instead of 12-point, they receive a generated table (Figure 3):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2000/format:webp/1*1tjxxLpTIRpSoip7iAoDyg.png&quot; alt=&quot;Figure 3: Output Results (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 3: Output Results (Image by Author).&lt;/p&gt;

&lt;p&gt;This shift allows the human expert to verify the AI’s findings in minutes rather than hours. The “sheer” volume of paperwork no longer dictates the pace of business.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The goal of AI in this context is not to replace the compliance officer, but to equip them with a tool that handles the “brute force” computation of regulatory verification. By using ADK to structure this workflow, we ensure that the process is auditable, consistent, and scalable.&lt;/p&gt;

&lt;p&gt;One final architectural note: you’ll observe we mixed models in this pipeline. We used &lt;strong&gt;Gemini 2.5 Flash&lt;/strong&gt; for ingestion and formatting (high speed, low cost) and reserved &lt;strong&gt;Gemini 2.5 Pro&lt;/strong&gt; solely for the auditing step (high reasoning). This “Economy of Intelligence” ensures the system is not just effective, but cost-efficient at scale.&lt;/p&gt;

&lt;p&gt;If you are building similar systems, start by defining your schemas. The precision of your data structures determines the reliability of your agents.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To get started with these patterns, explore the&lt;/em&gt; &lt;a href=&quot;https://github.com/google/adk-samples&quot;&gt;&lt;em&gt;Google Agent Development Kit (ADK)&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 18 Jan 2026 00:00:00 +0000</pubDate>
				<link>https://ppiconsulting.dev//blog/blog95/</link>
				<guid isPermaLink="true">https://ppiconsulting.dev//blog/blog95/</guid>
			</item>
		
			<item>
				<title>Reusable AI Patterns Transforming Every Industry</title>
				<description>&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*dkQeNau1F61MHWO_cGmhvA.png&quot; alt=&quot;The Continent of Generative AI (Image by Author).&quot; /&gt;&lt;br /&gt;The Continent of Generative AI (Image by Author).&lt;/p&gt;

&lt;!--end_excerpt--&gt;

&lt;h2 id=&quot;reusable-ai-patterns-transforming-every-industry&quot;&gt;Reusable AI Patterns Transforming Every Industry&lt;/h2&gt;

&lt;table&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;td align=&quot;left&quot;&gt;
        :memo:   Please Note
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;

    &lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;
        &lt;ul&gt;
            This is a guest post originally published on &lt;a href=&quot;https://medium.com/google-cloud/reusable-ai-patterns-transforming-every-industry-f60ecc4df531&quot; target=&quot;_blank&quot;&gt;Google Cloud - Community&lt;/a&gt;.
        &lt;/ul&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;a-blueprint-to-navigate-the-understanding-how-genai-is-redefining-every-industry&quot;&gt;A blueprint to navigate the understanding how GenAI is redefining every industry&lt;/h2&gt;

&lt;h3 id=&quot;tldr&quot;&gt;TL;DR&lt;/h3&gt;

&lt;p&gt;This article presents a strategic blueprint for understanding the business impact of Generative AI, arguing that its true power lies not in isolated, industry-specific solutions, but in a set of powerful, reusable patterns that apply across all sectors.&lt;/p&gt;

&lt;p&gt;We need to move beyond a fragmented view of AI use cases (“islands”) to reveal a connected “continent” of capabilities. This analysis is broken into three parts:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Industry Verticals:&lt;/strong&gt; It details specific, high-value GenAI applications across 15 distinct industries, grouped into four major sectors: Business &amp;amp; Finance, Consumer &amp;amp; Services, Tech &amp;amp; Infrastructure, and Public &amp;amp; Social.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Horizontal Functions:&lt;/strong&gt; It identifies evergreen use cases for core business departments present in every company, including HR, Sales &amp;amp; Marketing, IT &amp;amp; Cybersecurity, and Finance.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Reusable Patterns:&lt;/strong&gt; The core thesis is distilled into six foundational AI patterns that connect all the preceding examples: &lt;strong&gt;Synthetic Data Generation, Hyper-Personalization, Complex Information Synthesis, Conversational Interfaces, Simulation &amp;amp; Digital Twins,&lt;/strong&gt; and &lt;strong&gt;Advanced Content Generation.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;The current Generative AI landscape feels like an old, unfinished map of the world — chaotic, exciting, with huge sections marked “Here be dragons.” For the past couple of years, we’ve been exploring it one small island at a time, drawing detailed charts of “Insurance Island” or the “Retail Archipelago,” treating each as a separate world.&lt;/p&gt;

&lt;p&gt;But after traveling this landscape for a while, you start to see the bigger picture. You notice the deep ocean currents — the powerful, underlying patterns — that connect all these separate landmasses. You realize it’s not a scattered collection of islands at all; it’s one vast, interconnected continent.&lt;/p&gt;

&lt;p&gt;This post is my first draft of a new map. It’s a cartographer’s attempt to chart that continent, to trace the currents of core AI capabilities like “Simulation” and “Synthesis” as they flow from one industry to the next. It’s a blueprint meant not as a final, definitive guide, but as a new way to navigate this transformative era — by seeing the whole, connected world at once.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*dkQeNau1F61MHWO_cGmhvA.png&quot; alt=&quot;Figure 1: The Continent of Generative AI (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 1: The Continent of Generative AI (Image by Author).&lt;/p&gt;

&lt;h2 id=&quot;part-1-the-industry-verticals--ai-in-the-wild&quot;&gt;Part 1: The Industry Verticals — AI in the Wild&lt;/h2&gt;

&lt;p&gt;Every industry speaks its own language, but the core business challenges? They’re surprisingly universal. Here’s a detailed look at how GenAI is providing solutions, grouped by their broader economic sector.&lt;/p&gt;

&lt;h2 id=&quot;business--finance&quot;&gt;Business &amp;amp; Finance&lt;/h2&gt;

&lt;p&gt;This sector runs on data, risk, and complex contracts. GenAI isn’t just helping; it’s becoming the new backbone for intelligence and automation.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*zvETZGcgK9w6qOQL_RXYEA.png&quot; alt=&quot;Figure 2: Business &amp;amp; Finance (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 2: Business &amp;amp; Finance (Image by Author).&lt;/p&gt;

&lt;h3 id=&quot;insurance-intelligence-in-risk-claims-and-customer-experience&quot;&gt;Insurance: Intelligence in Risk, Claims, and Customer Experience&lt;/h3&gt;

&lt;p&gt;The entire insurance lifecycle, from underwriting to claims, is a complex dance of data. GenAI is finally turning that complexity into a competitive advantage.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Smarter Underwriting:&lt;/strong&gt; It used to take days. Now, AI models generate dynamic risk assessments by digesting unstructured data like property reports and climate models, creating hyper-personalized policies in minutes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Automated Claims:&lt;/strong&gt; We’re way beyond simple data extraction. GenAI can summarize messy claim narratives, analyze a photo of car damage, and draft empathetic, clear updates to keep policyholders in the loop.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Next-Gen Fraud Detection:&lt;/strong&gt; The real game-changer is generating synthetic data of &lt;em&gt;novel&lt;/em&gt; fraud schemes. This lets us train models to catch sophisticated criminals before they strike.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Proactive Engagement:&lt;/strong&gt; Instead of just sending a bill, AI creates personalized outreach for renewals and safety recommendations (like weather alerts for homeowners), turning insurers into proactive partners.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;finance-securing-transactions-and-personalizing-advice&quot;&gt;Finance: Securing Transactions and Personalizing Advice&lt;/h3&gt;

&lt;p&gt;Financial institutions are walking a tightrope: lock down security on one side, and deliver hyper-personalized services on the other. GenAI is the key to doing both at scale.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The Financial Co-Pilot:&lt;/strong&gt; AI can now act as a personal financial guide for every single customer, analyzing spending habits and life goals to generate tailored investment strategies and debt-reduction plans. It’s a level of service once reserved for the ultra-wealthy.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Automated Compliance (RegTech):&lt;/strong&gt; Compliance has historically been a domain defined by high-volume, repetitive manual tasks. GenAI is systematically automating these workflows. This includes interpreting new regulations, automating KYC and AML checks, and powering the next generation of surveillance. For trading firms, it can analyze billions of communications (chats, emails, calls) to flag market abuse with a deep understanding of nuance and context, far surpassing legacy keyword systems.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Market Intelligence on Demand:&lt;/strong&gt; Imagine summarizing thousands of earnings reports and news articles into a single, actionable paragraph. That’s no longer a dream; it’s a daily reality for investment professionals.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;legal-augmenting-expertise-and-automating-discovery&quot;&gt;Legal: Augmenting Expertise and Automating Discovery&lt;/h3&gt;

&lt;p&gt;Anyone in the legal field knows that a huge chunk of time is lost to a mountain of documents. GenAI is giving lawyers their time back.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;AI-Powered Document Review (e-Discovery):&lt;/strong&gt; Drastically accelerate the review of thousands of documents in litigation, letting AI do the first pass of summarizing and flagging relevant clauses.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Intelligent Legal Research:&lt;/strong&gt; Think of it as a research assistant that understands plain English, summarizing case law and analyzing statutes in seconds.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Automated Contract Drafting &amp;amp; Analysis:&lt;/strong&gt; Generate standardized contracts and, more importantly, analyze incoming third-party contracts to instantly identify risks and non-standard clauses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;real-estate--construction-from-smart-design-to-efficient-management&quot;&gt;Real Estate &amp;amp; Construction: From Smart Design to Efficient Management&lt;/h3&gt;

&lt;p&gt;The building lifecycle, from a sketch to a finished building, is notoriously complex and prone to delays.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Generative Architectural Design:&lt;/strong&gt; This is where it gets fun. Architects can input constraints like plot size, budget, and local codes, and the AI will generate multiple optimized floor plans and 3D models.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Automated Construction Planning:&lt;/strong&gt; AI can analyze project plans and daily site reports to spot potential delays and safety risks before they become costly problems, generating smarter schedules.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Dynamic Property Listings &amp;amp; Virtual Staging:&lt;/strong&gt; Automatically generate compelling property listings and use image models to virtually stage empty rooms, helping buyers see the potential.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;consumer--services&quot;&gt;Consumer &amp;amp; Services&lt;/h2&gt;

&lt;p&gt;This is the world of customer experience, logistics, and content. Here, GenAI is making every interaction more personal, efficient, and engaging.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*yv1r8sdMXOZqM0osEntIXg.png&quot; alt=&quot;Figure 3: Consumer &amp;amp; Services (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 3: Consumer &amp;amp; Services (Image by Author).&lt;/p&gt;

&lt;h3 id=&quot;retail--cpg-the-end-of-one-size-fits-all-shopping&quot;&gt;Retail &amp;amp; CPG: The End of One-Size-Fits-All Shopping&lt;/h3&gt;

&lt;p&gt;Retailers are in a constant battle to create amazing customer experiences while managing fragile global supply chains. GenAI is the force multiplier for both.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The AI Shopping Assistant:&lt;/strong&gt; These aren’t your old, clunky chatbots. Sophisticated AI now acts as an expert personal shopper, guiding customers through product discovery with real-time styling advice.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Resilient Supply Chains:&lt;/strong&gt; What if you could simulate the future? By modeling market scenarios — like competitor promotions or shipping disruptions — GenAI creates stunningly accurate demand forecasts and helps businesses sidestep bottlenecks.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Content That Converts:&lt;/strong&gt; AI generates unique product descriptions, marketing emails, and even “virtual try-on” experiences tailored to an individual’s tastes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Optimized Store Layouts:&lt;/strong&gt; AI can generate optimal product placements based on sales data and customer flow patterns to maximize every square foot of retail space.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;travel--hospitality-crafting-perfect-trips-and-seamless-experiences&quot;&gt;Travel &amp;amp; Hospitality: Crafting Perfect Trips and Seamless Experiences&lt;/h3&gt;

&lt;p&gt;This industry is all about creating memorable experiences. That means managing dynamic pricing, complex logistics, and real-time disruptions without a hitch.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;AI-Powered Trip Planning:&lt;/strong&gt; It’s like having an intelligent travel agent on call 24/7. AI can generate complete, personalized itineraries from vague prompts like “a relaxing beach vacation in Southeast Asia for under $2000.”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Dynamic Pricing and Revenue Management:&lt;/strong&gt; Generate sophisticated pricing models that adjust in real-time based on demand, competitor rates, and local events.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Proactive Disruption Management:&lt;/strong&gt; AI can monitor for flight delays and weather events, then proactively generate and offer solutions to affected travelers before they even think to complain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;media--entertainment-scaling-content-and-personalizing-discovery&quot;&gt;Media &amp;amp; Entertainment: Scaling Content and Personalizing Discovery&lt;/h3&gt;

&lt;p&gt;The pressure is relentless: create a firehose of engaging content while helping consumers find the gems in a sea of choices.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;AI-Assisted Creativity:&lt;/strong&gt; AI is becoming a creative partner, augmenting human talent by generating script ideas, concept art, and background music. It can even create trailers and highlights from long-form video automatically.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Intelligent Archives:&lt;/strong&gt; Imagine making your entire content library instantly searchable. AI automates the transcription, translation, and metadata tagging, readying it for monetization.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Localization at Scale:&lt;/strong&gt; Automatically generate high-quality subtitles and even synthetic voice dubs in dozens of languages, opening up global markets faster than ever before.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;logistics--transportation-optimizing-flow-and-enhancing-visibility&quot;&gt;Logistics &amp;amp; Transportation: Optimizing Flow and Enhancing Visibility&lt;/h3&gt;

&lt;p&gt;This industry operates on razor-thin margins and is vulnerable to the slightest disruption. Optimization isn’t a goal; it’s a survival mechanism.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Dynamic Route &amp;amp; Network Optimization:&lt;/strong&gt; Generate and simulate thousands of potential routing options in real-time, factoring in traffic, weather, and fuel costs to find the absolute best path.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Intelligent Document Processing:&lt;/strong&gt; Automate the tedious and error-prone data extraction from critical documents like Bills of Lading and customs forms.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Predictive Disruption Analysis:&lt;/strong&gt; Generate simulations of potential supply chain shocks (like port closures) and recommend proactive rerouting and contingency plans.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;tech--infrastructure&quot;&gt;Tech &amp;amp; Infrastructure&lt;/h2&gt;

&lt;p&gt;This category covers the physical world — from factories to the energy grid. GenAI is creating more efficient, resilient, and innovative physical products and systems.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*vOADPmV2bUD1GU2b4MDcqg.png&quot; alt=&quot;Figure 4: Tech &amp;amp; Infrastructure (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 4: Tech &amp;amp; Infrastructure (Image by Author).&lt;/p&gt;

&lt;h3 id=&quot;manufacturing-designing-the-future-optimizing-the-present&quot;&gt;Manufacturing: Designing the Future, Optimizing the Present&lt;/h3&gt;

&lt;p&gt;Manufacturers have to constantly innovate while maximizing the efficiency and uptime of their multi-million dollar production lines.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Generative Design:&lt;/strong&gt; This is mind-bending stuff. Engineers define a product’s requirements — weight, materials, cost — and AI generates thousands of optimized designs, creating forms a human would never have imagined.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Predictive Maintenance on Steroids:&lt;/strong&gt; By generating synthetic sensor data that mimics rare machine failures, we can train AI models to predict breakdowns with uncanny accuracy.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Automated Quality Control:&lt;/strong&gt; AI analyzes images from the production line to spot microscopic defects in real-time and generate alerts with probable causes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;telecommunications-optimizing-networks-retaining-customers&quot;&gt;Telecommunications: Optimizing Networks, Retaining Customers&lt;/h3&gt;

&lt;p&gt;In a saturated market, preventing customer churn and providing effective technical support are everything for Telcos.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Proactive Network Operations:&lt;/strong&gt; AI can simulate network traffic to predict congestion and optimize capacity, while predictive models anticipate hardware failures in cell towers before they go down.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;AI-Powered Field Service:&lt;/strong&gt; Give technicians a “co-pilot” that understands technical manuals, helping them troubleshoot complex issues in the field and dramatically improving first-time fix rates.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Smart Contract Analysis:&lt;/strong&gt; Automatically summarize complex B2B service contracts and SLAs. For all customers, AI can analyze bills and resolve discrepancies instantly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;energy--utilities-balancing-the-grid-and-ensuring-safety&quot;&gt;Energy &amp;amp; Utilities: Balancing the Grid and Ensuring Safety&lt;/h3&gt;

&lt;p&gt;Energy providers have to ensure grid stability amidst fluctuating demand and the rise of renewables, all while maintaining vast, critical infrastructure.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Grid Management &amp;amp; Load Forecasting:&lt;/strong&gt; Generate highly accurate simulations of energy demand by factoring in weather and economic indicators, allowing for optimized energy production and preventing outages.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Predictive Maintenance for Infrastructure:&lt;/strong&gt; Analyze data from drones, sensors, and satellite imagery to predict failures in turbines, transformers, and pipelines before they become critical.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Renewable Energy Optimization:&lt;/strong&gt; Generate precise forecasts for wind and solar output to create optimal strategies for battery storage and release, maximizing the value of every electron.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;automotive-redefining-the-in-vehicle-experience-and-service-lifecycle&quot;&gt;Automotive: Redefining the In-Vehicle Experience and Service Lifecycle&lt;/h3&gt;

&lt;p&gt;The industry is transforming towards electric, connected, and autonomous vehicles, with a new focus on the digital experience and post-sales service.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Intelligent In-Vehicle Assistant:&lt;/strong&gt; Create a conversational co-pilot that can control vehicle settings, plan complex routes with charging stops, and provide a truly rich infotainment experience.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;AI-Powered Diagnostics &amp;amp; Service:&lt;/strong&gt; Empower service technicians with a GenAI model that understands vehicle sensor data and service manuals, providing step-by-step repair instructions.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Accelerated Vehicle Design:&lt;/strong&gt; Use generative design to create and test thousands of aerodynamic body shapes and lightweight chassis designs in a fraction of the time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;public--social&quot;&gt;Public &amp;amp; Social&lt;/h2&gt;

&lt;p&gt;These verticals are focused on society’s well-being, from our health to our education. GenAI’s role here is to augment human experts and broaden access to critical services.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*vBkqw_F5at6DqOYQ3TQasw.png&quot; alt=&quot;Figure 5: Public &amp;amp; Social (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 5: Public &amp;amp; Social (Image by Author).&lt;/p&gt;

&lt;h3 id=&quot;healthcare--life-sciences-accelerating-discovery-easing-burnout&quot;&gt;Healthcare &amp;amp; Life Sciences: Accelerating Discovery, Easing Burnout&lt;/h3&gt;

&lt;p&gt;Healthcare is drowning in data, and clinicians are burning out from administrative overload. GenAI is a lifeline, accelerating research and giving doctors more time with patients.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;AI-Powered Drug Discovery:&lt;/strong&gt; Researchers can now generate and test novel molecular structures in a simulation, dramatically shortening the early, expensive phases of drug development.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The End of Clinical Paperwork:&lt;/strong&gt; This is the big one for doctors. AI can now listen to a patient conversation and automatically generate structured clinical notes directly into the EHR, fighting clinician burnout.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;On-Demand Medical History:&lt;/strong&gt; Upon admission, AI can give clinicians a rapid, summarized overview of a patient’s entire medical history, ensuring better, faster care.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Synthetic Data for Research:&lt;/strong&gt; AI can create synthetic medical images and patient data to train diagnostic models without compromising patient privacy — a huge deal for studying rare diseases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;public-sector-enhancing-citizen-services-and-operational-efficiency&quot;&gt;Public Sector: Enhancing Citizen Services and Operational Efficiency&lt;/h3&gt;

&lt;p&gt;Government agencies have to deliver a vast range of services, often with tight budgets and legacy systems.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Intelligent Constituent Services:&lt;/strong&gt; Create conversational AI agents that give citizens 24/7 access to information about services, benefits, and regulations, answering their questions instantly.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Policy Analysis &amp;amp; Simulation:&lt;/strong&gt; Summarize and analyze proposed legislation and public commentary to help policymakers understand potential impacts before a bill becomes law.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Automated Grant and Permit Processing:&lt;/strong&gt; Streamline the application process by having GenAI read and validate documents, checking for compliance and slashing backlogs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;education-personalizing-learning-and-streamlining-administration&quot;&gt;Education: Personalizing Learning and Streamlining Administration&lt;/h3&gt;

&lt;p&gt;Educators want to provide personalized learning for every student but are often swamped by large class sizes and administrative work.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Personalized Learning Assistants:&lt;/strong&gt; Create AI tutors that adapt to each student’s learning pace and style, generating customized practice problems and study guides to help them master any subject.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Curriculum &amp;amp; Content Development:&lt;/strong&gt; Assist educators by generating fresh lesson plans, classroom activities, and assessment questions aligned with curriculum standards.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Administrative Co-pilot:&lt;/strong&gt; Automate the thankless tasks, like generating school newsletters, meeting summaries, and parent-teacher communications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-2-the-horizontals--the-ai-toolkit-for-every-company&quot;&gt;Part 2: The Horizontals — The AI Toolkit for Every Company&lt;/h2&gt;

&lt;p&gt;Beyond specific industries, every single company has core business functions. Building reusable GenAI assets for these “horizontals” is one of the fastest ways to scale value across an organization.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*pQt6iMAF-c1WuADZczoOkA.png&quot; alt=&quot;Figure 6: Horizontal Functions (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 6: Horizontal Functions (Image by Author).&lt;/p&gt;

&lt;h3 id=&quot;human-resources-hr&quot;&gt;Human Resources (HR)&lt;/h3&gt;

&lt;p&gt;AI is giving HR teams superpowers, letting them move from administrative tasks to strategic talent management.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The Talent Co-pilot:&lt;/strong&gt; Generate tailored job descriptions, screen resumes, and create personalized interview questions to find the perfect candidate faster.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Frictionless Onboarding:&lt;/strong&gt; Power a 24/7 HR chatbot to answer new hires’ questions about benefits and policies, freeing up the HR team to focus on the human connection.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Engagement &amp;amp; Development:&lt;/strong&gt; Analyze employee feedback surveys to generate summaries of sentiment and create personalized learning paths for career growth.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;sales--marketing&quot;&gt;Sales &amp;amp; Marketing&lt;/h3&gt;

&lt;p&gt;The days of spray-and-pray marketing are over. GenAI allows for true one-to-one communication, at scale.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Hyper-Personalized Campaigns:&lt;/strong&gt; Generate thousands of variations of ad copy and email campaigns tailored to individual customer segments and their specific needs.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Sales Assistant:&lt;/strong&gt; Prepare sales teams for every meeting by having AI summarize a prospect’s company news, industry trends, and past interactions.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;AI-Driven Content Strategy:&lt;/strong&gt; Analyze market trends and competitor activities to generate sharp ideas for blog posts, white papers, and other marketing content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;it--cybersecurity&quot;&gt;IT &amp;amp; Cybersecurity&lt;/h3&gt;

&lt;p&gt;IT departments are using AI to build faster, manage complexity, and stay one step ahead of threats.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The Developer’s Co-pilot:&lt;/strong&gt; Generate boilerplate code, suggest optimizations, and even translate code between programming languages. It’s a massive productivity boost.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Intelligent Incident Management:&lt;/strong&gt; Analyze system logs to instantly summarize incidents, identify the likely root cause, and suggest remediation steps.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Threat Intelligence &amp;amp; Simulation:&lt;/strong&gt; Summarize the latest threat intelligence reports and generate security recommendations. Even better, simulate phishing attacks to train employees.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;corporate-finance--accounting&quot;&gt;Corporate Finance &amp;amp; Accounting&lt;/h3&gt;

&lt;p&gt;AI is automating the tedious parts of finance, allowing teams to become more strategic advisors to the business.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Automated Financial Storytelling:&lt;/strong&gt; Connect to financial systems and automatically generate narrative summaries for quarterly reports, explaining key trends and variances in plain English.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Intelligent Expense Processing:&lt;/strong&gt; Automate data extraction from invoices and receipts, categorize expenses, and check for policy compliance.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The FP&amp;amp;A Co-pilot:&lt;/strong&gt; Assist analysts by generating financial models and running scenario analyses based on simple, natural language prompts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;part-3-the-blueprint--connecting-the-dots-with-reusable-patterns&quot;&gt;Part 3: The Blueprint — Connecting the Dots with Reusable Patterns&lt;/h2&gt;

&lt;p&gt;This is where it all comes together. When you zoom out from the map, you see that these dozens of use cases are all powered by a handful of foundational AI patterns. Master these, and you can build for any industry. This is the blueprint for a truly reusable AI strategy.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*oKV0Y-GiDuxeOMfBYz1QLQ.png&quot; alt=&quot;Figure 7: The Complete Landscape (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 7: The Complete Landscape (Image by Author).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 1: Synthetic Data Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The key to robust Fraud Detection (Finance), accurate Predictive Maintenance (Manufacturing), and privacy-preserving Medical Training (Healthcare).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 2: Hyper-Personalization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The engine connecting Retail (shopping assistants), Finance (financial co-pilots), Travel (trip planning), and Marketing (campaigns).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 3: Complex Information Synthesis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The ability to distill vast, unstructured data into insights. It powers Market Intelligence (Finance), Clinical Summarization (Healthcare), and Legal Research (Legal).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 4: Conversational Interfaces&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The universal human-AI interaction layer. It powers everything from external Customer Support bots to internal IT Helpdesks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 5: Simulation &amp;amp; Digital Twins&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The power to model reality. This is crucial for Supply Chain (Retail), Network Operations (Telco), and Financial Modeling (Finance).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern 6: Advanced Content Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This spans everything from creating Marketing Copy to highly technical outputs like Generative Design (Manufacturing) and Code Generation (IT).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*KfJB4BgqwrDZqddgWOUdzQ.png&quot; alt=&quot;Figure 8: Interconnected Patterns (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 8: Interconnected Patterns (Image by Author).&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;A blueprint, no matter how detailed, is not a building. It is a plan, a vision, an invitation to build. What I’ve laid out here is my reading of that plan — a schematic of the interconnected, reusable patterns that I believe will form the foundations of the next generation of enterprise.&lt;/p&gt;

&lt;p&gt;But the most exciting part is that the concrete is still wet. The framework is still being built.&lt;/p&gt;

&lt;p&gt;This blueprint is an invitation to stop building isolated tools and start designing scalable intelligence. It’s a challenge to look beyond the immediate problem in your industry and ask: “What core pattern are we &lt;em&gt;really&lt;/em&gt; trying to solve, and how can we build it in a way that it becomes a foundational asset for everything we do next?”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you enjoyed the mindmaps in this article, they were created using&lt;/em&gt; &lt;a href=&quot;https://github.com/pierpaolo28/mind-maps-generator&quot;&gt;&lt;em&gt;Mind Maps Generator&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, an open source tool!&lt;/em&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 26 Oct 2025 00:00:00 +0000</pubDate>
				<link>https://ppiconsulting.dev//blog/blog94/</link>
				<guid isPermaLink="true">https://ppiconsulting.dev//blog/blog94/</guid>
			</item>
		
			<item>
				<title>Google Veo A Technical Deep Dive for the AI Director</title>
				<description>&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:2560/format:webp/1*-26qT7GVnSiP_1RQZL_79A.gif&quot; alt=&quot;Video 1: Submarines and a whale in Zurich Lake (Image by Author).&quot; /&gt;&lt;br /&gt;Video 1: Submarines and a whale in Zurich Lake (Image by Author).&lt;/p&gt;

&lt;!--end_excerpt--&gt;

&lt;h2 id=&quot;google-veo-a-technical-deep-dive-for-the-ai-director&quot;&gt;Google Veo: A Technical Deep Dive for the AI Director&lt;/h2&gt;

&lt;table&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;td align=&quot;left&quot;&gt;
        :memo:   Please Note
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;

    &lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;
        &lt;ul&gt;
            This is a guest post originally published on &lt;a href=&quot;https://medium.com/google-cloud/google-veo-a-technical-deep-dive-for-the-ai-director-a6fdf6438a3f&quot; target=&quot;_blank&quot;&gt;Google Cloud - Community&lt;/a&gt;.
        &lt;/ul&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;an-in-depth-guide-to-the-architecture-prompting-and-workflows-behind-googles-generative-video-model&quot;&gt;An In-Depth Guide to the Architecture, Prompting, and Workflows Behind Google’s Generative Video Model&lt;/h3&gt;

&lt;p&gt;The leap from static images to dynamic, coherent video has long been a formidable benchmark for generative AI. With the introduction of models like Google’s Veo, we’re witnessing a paradigm shift. This isn’t just about creating moving pictures; it’s about enabling a new form of &lt;strong&gt;procedural cinematography&lt;/strong&gt;, where creators can direct complex scenes through language. For developers, creatives, and data scientists, understanding the engine under the hood is crucial to harnessing its full potential and moving from being a mere user to a true AI director.&lt;/p&gt;

&lt;p&gt;This article provides a technical deep dive into Google Veo. We’ll deconstruct its architecture, move on to foundational prompting strategies, and culminate in advanced techniques for achieving the holy grail of AI video: &lt;strong&gt;consistency&lt;/strong&gt; in characters, scenes, and branding. We will also walk through a practical multi-shot workflow and explore the emerging hybrid approach of combining generation with powerful editing tools, a process that is set to define the next generation of digital content creation.&lt;/p&gt;

&lt;h1 id=&quot;deconstructing-veo--the-architecture-of-motion&quot;&gt;Deconstructing Veo — The Architecture of Motion&lt;/h1&gt;

&lt;p&gt;At its core, Veo is a sophisticated generative model capable of producing high-definition video from a variety of inputs, including text, images, or a combination of both. Its ability to generate up to 1080p resolution footage that can extend beyond a minute, complete with an emergent understanding of real-world physics and cinematic techniques, stems from its powerful and efficient architecture: a &lt;strong&gt;Latent Diffusion Transformer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s break down this trifecta of concepts, as understanding each piece is key to understanding Veo’s capabilities and limitations.&lt;/p&gt;

&lt;h2 id=&quot;the-latent-space-a-strategy-of-efficiency&quot;&gt;The Latent Space: A Strategy of Efficiency&lt;/h2&gt;

&lt;p&gt;Processing raw video data — a sequence of high-resolution pixel grids — is computationally astronomical. To solve this, Veo employs a latent diffusion model (LDM). The process begins with a specialized autoencoder, which consists of two parts: an encoder and a decoder.&lt;/p&gt;

&lt;p&gt;The video encoder takes raw video frames and compresses them into a lower-dimensional, information-dense representation known as the &lt;strong&gt;latent space&lt;/strong&gt;. This process intelligently strips out redundant visual information while preserving the essential features of the scene, objects, and their movement over time. Think of it as creating a highly detailed blueprint of the video rather than working with the raw, heavy bricks and mortar. This isn’t just a smaller file; it’s a structured, semantic map of the video’s content.&lt;/p&gt;

&lt;p&gt;By operating within this compressed latent space, the computationally intensive diffusion process becomes drastically more manageable, enabling the generation of high-resolution video without requiring prohibitive amounts of processing power.&lt;/p&gt;

&lt;h2 id=&quot;the-diffusion-process-denoising-to-reality&quot;&gt;The Diffusion Process: Denoising to Reality&lt;/h2&gt;

&lt;p&gt;The generative heart of the model is diffusion. It’s a two-part process that allows the model to learn and then create complex data structures.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Forward Process (Training)&lt;/strong&gt;: During training, the model takes the clean latent representations of video and systematically adds Gaussian noise over a series of steps until nothing but random noise remains. This teaches the model the statistical structure of video data at every level of detail, from broad compositions down to fine textures. It learns what “video-ness” looks like at every stage of clarity.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Reverse Process (Inference)&lt;/strong&gt;: The model then learns to reverse this process. At inference time, it starts with a random noise tensor and, guided by the user’s prompt (which is also converted into a mathematical representation), it iteratively applies a learned denoising function. Step by step, it removes the noise, sculpting the random tensor into a clean latent representation that reflects the prompt’s content. It’s akin to a sculptor who knows precisely where to chisel a block of marble to reveal the statue within.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This denoising process is what “creates” the video. The final clean latent is then passed to the &lt;strong&gt;decoder&lt;/strong&gt; (the other half of the autoencoder), which upscales it back into the full-resolution video we see.&lt;/p&gt;

&lt;h2 id=&quot;the-transformer-modeling-the-language-of-time&quot;&gt;The Transformer: Modeling the Language of Time&lt;/h2&gt;

&lt;p&gt;The critical component executing this reverse-denoising process is a &lt;strong&gt;Transformer-based denoising network&lt;/strong&gt;. Transformers, with their self-attention mechanism, are unparalleled at modeling complex, long-range dependencies within sequential data. Unlike older models that could “forget” what happened early in a sequence, a Transformer can pay attention to all parts of the input at once. This makes them perfectly suited for the temporal nature of video.&lt;/p&gt;

&lt;p&gt;To make the data compatible, Veo “tokenizes” the compressed latent space, turning the spatio-temporal data into a sequence that the Transformer can process. This allows the model to understand not just what’s in a single frame, but how objects should consistently evolve and interact over time. This leads to more coherent and physically plausible results like realistic water ripples, consistent character motion, or fabric movement that reacts to a character’s actions. This unified architecture is what allows Veo to follow complex, multi-scene narrative prompts and understand cinematic language like “timelapse” or “drone shot.”&lt;/p&gt;

&lt;h1 id=&quot;the-art-of-direction--foundational-prompting&quot;&gt;The Art of Direction — Foundational Prompting&lt;/h1&gt;

&lt;p&gt;If Veo is the film crew, your prompt is the screenplay and the director’s shot list rolled into one. Effective prompting moves beyond simple descriptions to a form of procedural direction. A well-structured prompt is built on several core components that, when combined, give the model a clear and unambiguous set of instructions.&lt;/p&gt;

&lt;h2 id=&quot;the-essential-elements&quot;&gt;The Essential Elements&lt;/h2&gt;

&lt;p&gt;Based on official guidance and community best practices, every foundational prompt should contain these four elements:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subject&lt;/strong&gt;: Who or what is the focus? Be specific and descriptive. The more detail you provide, the less the model has to guess.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Instead of:&lt;/em&gt; “a man”&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Try:&lt;/em&gt; “a grizzled, elderly fisherman with a thick white beard and a worn, yellow raincoat.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Action&lt;/strong&gt;: What is the subject doing? Crucially, focus on a single, clear action or “beat.” Trying to chain multiple actions in one prompt (e.g., “a man walks in, sits down, and drinks coffee”) can confuse the model.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Instead of:&lt;/em&gt; “a dog runs and jumps”&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Try:&lt;/em&gt; “a golden retriever leaps gracefully through the air to catch a red frisbee.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Context (Scene)&lt;/strong&gt;: Where and when is this happening? Describe the environment, time of day, and atmosphere to ground your subject in a believable world.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Example:&lt;/em&gt; “A misty, ancient redwood forest at dawn, with golden sunbeams filtering through the dense canopy.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Style&lt;/strong&gt;: The overall aesthetic. This is where you define the look and feel, referencing artistic movements, film techniques, or even specific hardware.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Examples:&lt;/em&gt; “cinematic, shot on 35mm film with anamorphic lenses,” “Studio Ghibli-inspired animation,” “hyperrealistic, Unreal Engine 5 render,” “grainy found footage from a 1990s VHS tape.”&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;adding-cinematic-control-the-modifiers&quot;&gt;Adding Cinematic Control: The Modifiers&lt;/h2&gt;

&lt;p&gt;To elevate your output from a simple clip to a cinematic shot, you must direct the camera and ambiance with specific keywords.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Camera Motion&lt;/strong&gt;: Be explicit. If you want movement, specify it.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pan&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tilt&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dolly-in&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tracking shot&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crane shot&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;handheld micro-shake&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;whip pan&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slow push-in&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Camera Framing&lt;/strong&gt;: How is the subject framed? Use standard filmmaking terminology.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wide shot&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;medium shot&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;close-up&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extreme close-up (ECU)&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;over-the-shoulder (OTS)&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;point-of-view (POV)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Camera Angle&lt;/strong&gt;: What is the camera’s perspective? This has a powerful psychological effect.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;low angle&lt;/code&gt; (makes the subject look powerful)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;high angle&lt;/code&gt; (can make the subject seem small or vulnerable)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eye-level&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bird&apos;s-eye view&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dutch angle&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ambiance &amp;amp; Lighting&lt;/strong&gt;: Control the mood with color and light. Be evocative.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;warm golden hour lighting&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cool blue tones of twilight&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dramatic high-contrast film noir lighting&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;soft, diffused light from an overcast sky&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;caustic reflections from water&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;example-prompt-breakdown&quot;&gt;Example Prompt Breakdown&lt;/h2&gt;

&lt;p&gt;Let’s combine these into a powerful, directorial prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weak Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;A car driving in the city at night.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*lrCZm5DOejSdBbCar2Roaw.gif&quot; alt=&quot;Video 2: Weak Prompt (Image by Author).&quot; /&gt;&lt;br /&gt;Video 2: Weak Prompt (Image by Author).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strong, Directorial Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Cinematic wide shot of a vintage 1980s sports car, gleaming cherry red, speeding through a rain-slicked neon alley at night. The camera tracks smoothly alongside the car. Moody, high-contrast film noir lighting with reflections of pink and blue neon signs on the wet asphalt.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*aZJ4-Esawp6iiC54sASL0w.gif&quot; alt=&quot;Video 3: Directoral Prompt (Image by Author).&quot; /&gt;&lt;br /&gt;Video 3: Directoral Prompt (Image by Author).&lt;/p&gt;

&lt;h1 id=&quot;advanced-techniques-for-cinematic-consistency&quot;&gt;Advanced Techniques for Cinematic Consistency&lt;/h1&gt;

&lt;p&gt;The most significant challenge in multi-shot AI video generation is consistency. A character’s face changing mid-scene or a setting’s style drifting breaks the narrative illusion. Here are systematic strategies to combat this.&lt;/p&gt;

&lt;h2 id=&quot;character-consistency-defeating-identity-drift&quot;&gt;Character Consistency: Defeating “Identity Drift”&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Challenge:&lt;/strong&gt; AI models are generally stateless. They interpret each prompt independently and have no “memory” of the character they generated in the previous shot. This leads to “identity drift,” where features, clothing, or even ethnicity can change from one shot to the next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution 1: The Character Bible&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your most powerful tool is a “character bible” — a highly detailed, reusable block of text that defines your character.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Create a Detailed Description&lt;/strong&gt;: Go beyond the basics. Describe facial structure (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oval face, prominent cheekbones, aquiline nose&lt;/code&gt;), specific features (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a small scar above the left eyebrow&lt;/code&gt;), hair (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wavy, shoulder-length auburn hair&lt;/code&gt;), and wardrobe (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a well-worn, dark brown leather jacket over a grey Henley shirt&lt;/code&gt;). The more unique and specific the details, the stronger the anchor.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Verbatim Rule&lt;/strong&gt;: This is critical. &lt;strong&gt;Copy and paste the exact same character block&lt;/strong&gt; into every single prompt where that character appears. Do not paraphrase or shorten it. The model interprets your prompt as a set of tokens; changing even one word creates a different input and can lead to a different output.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Prioritize the Block&lt;/strong&gt;: Place the character description prominently at the start of your prompt to give it maximum weight in the model’s attention mechanism.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Character Bible Example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CHARACTER: A woman in her late 20s named Elara. She has an oval face with prominent cheekbones, deep blue almond-shaped eyes, and a constellation of light freckles across her nose. Her hair is wavy, shoulder-length, and auburn. She wears a well-worn, dark brown leather jacket over a grey Henley shirt and dark-wash jeans.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You would then append scene-specific descriptions to this block for each shot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution 2: Image-to-Video Anchoring&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For even greater control, use a multi-modal approach by providing visual conditioning.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Generate a Still Image&lt;/strong&gt;: Use a powerful image model (like Google’s Imagen) or even Veo itself to generate a perfect still frame of your character using your detailed “character bible” prompt. This is your “master reference.”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Use as a Reference&lt;/strong&gt;: Feed this generated image into Veo along with your text prompt for the video scene. The image acts as a powerful visual anchor, significantly reducing identity drift and ensuring the model adheres to the established look.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;scene-and-narrative-consistency&quot;&gt;Scene and Narrative Consistency&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Challenge:&lt;/strong&gt; Creating a coherent, multi-shot narrative where the environment, style, and lighting remain consistent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution 1: One Beat Per Prompt&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the cardinal rule of AI storyboarding. Do not try to describe an entire sequence in one prompt. Break your narrative down into individual shots or “beats,” with each prompt generating a single, short clip (e.g., 5–8 seconds). This gives you maximum control over the final edit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution 2: Lexicon and Style Block Consistency&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just like the character bible, create a reusable “Style Block” for your scene.&lt;/p&gt;

&lt;p&gt;Style Block Example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;STYLE: Cinematic, shot on 35mm film with a 2.35:1 aspect ratio. Color graded with a palette of muted earth tones and cool blues. Lighting is soft, natural, and atmospheric, mimicking an overcast winter morning. A light film grain is visible.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Paste this exact block into every prompt within the sequence. Furthermore, reuse the same core nouns and adjectives for the setting (e.g., always call it a “&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minimalist Scandinavian kitchen&lt;/code&gt;,” not just “&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a kitchen&lt;/code&gt;”).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution 3: Motivated Transitions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Direct your transitions to create a seamless flow. End one prompt on an action that begs for a continuation and start the next by fulfilling it.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Prompt 1 (ends with):&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...Elara turns and exits the frame to the left.&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Prompt 2 (begins with):&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Medium shot. Elara enters the frame from the right, now walking down a dimly lit hallway...&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;brand-consistency&quot;&gt;Brand Consistency&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Challenge:&lt;/strong&gt; Ensuring AI-generated content aligns perfectly with a brand’s specific visual identity (VI), color palette, and tone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution: Combine the techniques above to create a “Brand VI Block.”&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Define the Visuals&lt;/strong&gt;: Codify your brand’s style. Include the color palette (you can even reference hex codes, though mileage may vary), lighting style (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bright, clean studio lighting&lt;/code&gt;), camera style (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stable tripod shots, no handheld motion&lt;/code&gt;), and overall tone (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;energetic and upbeat&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;serious and professional&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;In-painting and Editing&lt;/strong&gt;: For product placements, Veo’s editing capabilities will be key. You can generate a scene and then use in-painting or masking to specifically edit or insert a branded product, ensuring it looks seamlessly integrated. This provides a level of granular control that pure text-to-video cannot match.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;practical-workflow--storyboarding-a-multi-shot-scene&quot;&gt;Practical Workflow — Storyboarding a Multi-Shot Scene&lt;/h1&gt;

&lt;p&gt;Theory is one thing, but execution is another. Let’s walk through a concrete example of creating a short, three-shot narrative sequence using the consistency principles we’ve discussed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept:&lt;/strong&gt; A detective, Elara, finds a crucial clue in a rain-soaked alley at night.&lt;/p&gt;

&lt;p&gt;First, we establish our reusable “bibles” for the character and the scene’s style. This “pre-production” step is vital.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Character Bible:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CHARACTER: A woman in her late 20s named Elara. She has an oval face with prominent cheekbones, deep blue almond-shaped eyes, and a constellation of light freckles across her nose. Her hair is wavy, shoulder-length, and auburn. She wears a well-worn, dark brown leather jacket over a grey Henley shirt and dark-wash jeans.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Style Bible:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;STYLE: Cinematic film noir. Moody, high-contrast lighting with deep shadows. The scene is set in a rain-slicked city alley at night, with reflections of pink and blue neon signs on the wet asphalt. Shot on 35mm film with a gritty, textured feel.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, we storyboard our sequence, one beat per prompt.&lt;/p&gt;

&lt;h2 id=&quot;shot-1-the-establishing-shot&quot;&gt;Shot 1: The Establishing Shot&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Introduce the character and setting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_[CHARACTER BIBLE]_&lt;/code&gt; &lt;em&gt;+&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_[STYLE BIBLE]_&lt;/code&gt; &lt;em&gt;+ Wide shot. Elara walks slowly into frame from the left, her face determined as she scans the ground. The camera tracks smoothly with her movement.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;shot-2-the-discovery&quot;&gt;Shot 2: The Discovery&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Show the character finding something. This shot uses a motivated transition from Shot 1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_[CHARACTER BIBLE]_&lt;/code&gt; &lt;em&gt;+&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_[STYLE BIBLE]_&lt;/code&gt; &lt;em&gt;+ Medium shot. Elara stops and her eyes fix on something on the ground. She crouches down slowly, her hand reaching out towards the pavement just out of frame.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;shot-3-the-clue&quot;&gt;Shot 3: The Clue&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; A close-up reveal of the clue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_[CHARACTER BIBLE]_&lt;/code&gt; &lt;em&gt;+&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_[STYLE BIBLE]_&lt;/code&gt; &lt;em&gt;+ Extreme close-up from an over-the-shoulder (OTS) perspective. Elara’s fingers gently pick up a small, tarnished silver locket from a puddle on the asphalt. The reflection of neon signs is visible on the locket’s surface.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By pasting the verbatim bibles into each prompt and breaking the narrative into distinct, connected beats, we create a coherent sequence where the character, location, and aesthetic remain consistent.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*_gfxsxNUVYIxBLz1Dy-FWw.gif&quot; alt=&quot;Video 4: Storyboarding a Multi-Shot Scene (Image by Author).&quot; /&gt;&lt;br /&gt;Video 4: Storyboarding a Multi-Shot Scene (Image by Author).&lt;/p&gt;

&lt;h1 id=&quot;the-hybrid-workflow--generation-meets-editing&quot;&gt;The Hybrid Workflow — Generation Meets Editing&lt;/h1&gt;

&lt;p&gt;While text-to-video generation is incredibly powerful, the future of professional AI filmmaking lies in a hybrid workflow that combines generation with precise editing tools. Veo isn’t just a generator; it’s a component in a larger creative pipeline that will likely integrate with tools like Adobe After Effects or DaVinci Resolve.&lt;/p&gt;

&lt;p&gt;The core idea is to use the generative model for the “heavy lifting” — ideation, animation, and complex textures — and then use editing features for refinement and control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Process:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Generate the Base Layer:&lt;/strong&gt; Use the prompting techniques described above to generate your primary video clip. Focus on getting the motion, composition, and overall feel right. Don’t worry about small imperfections.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Masking for Targeted Edits:&lt;/strong&gt; Once you have your clip, you can use masking to isolate specific regions of the video over time. For example, if a character’s logo on their shirt flickers or a background object looks out of place, you can draw a mask around that area.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;In-painting and Out-painting:&lt;/strong&gt; With a mask applied, you can issue a new prompt to regenerate &lt;em&gt;only&lt;/em&gt; the masked area. This is where the true power lies.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;In-painting (Correction):&lt;/strong&gt; Use this to fix artifacts. If a character’s hand looks unnatural, mask it and prompt for “&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a realistic human hand, fingers slightly curled.&lt;/code&gt;” The model will regenerate the hand while keeping the rest of the scene intact. You can even use it for subtle performance changes, like masking a character’s mouth and prompting for a “slight smile.”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;In-painting (Addition):&lt;/strong&gt; Use this for product placement. Mask a table and prompt for “&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a can of branded &apos;Starlight Soda&apos; sitting on the table.&lt;/code&gt;” This allows for perfect, on-brand object insertion.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Out-painting (Extension):&lt;/strong&gt; This feature allows you to extend the frame of the video, generating new visual information beyond the original boundaries. This is perfect for changing aspect ratios (e.g., converting a 16:9 shot to a 9:16 for social media) or creating a wider, more panoramic shot from an existing clip.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This hybrid approach offers the best of both worlds: the speed and creativity of AI generation with the precision and control of traditional post-production, enabling a much higher standard of final output.&lt;/p&gt;

&lt;h1 id=&quot;the-future-is-direction&quot;&gt;The Future is Direction&lt;/h1&gt;

&lt;p&gt;Google Veo and models of its caliber represent a fundamental shift. The bottleneck is no longer the technical ability to create pixels, but the creative and technical skill to direct the AI. The skillset of a modern creator is evolving from one of pure technical execution (e.g., mastering complex 3D software) to one of detailed creative specification and curation. By understanding the underlying architecture, adopting a systematic, directorial approach to prompting, and embracing a hybrid workflow that combines generation with editing, creators can move from generating novel curiosities to producing deliberate, consistent, and compelling cinematic narratives.&lt;/p&gt;

&lt;p&gt;The age of the AI Director has arrived, and it promises to democratize storytelling in ways we are only beginning to imagine.&lt;/p&gt;
</description>
				<pubDate>Sun, 24 Aug 2025 00:00:00 +0000</pubDate>
				<link>https://ppiconsulting.dev//blog/blog93/</link>
				<guid isPermaLink="true">https://ppiconsulting.dev//blog/blog93/</guid>
			</item>
		
			<item>
				<title>The Startup Fork In The Road</title>
				<description>&lt;p&gt;&lt;img src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXdwloeKORUdwLwGvKjrj-rA5-RogPx5JHGsNIqsRCmu2LIJQ47eIbCdZOkHeL2C-Ag3mN5VlF6n-XGCkzAO_fAO_M545wPhrM8hQ7kW_uX-JeYl0XUXsNdyNwf7fBvGzhpwiIuU8g?key=I6soiPVYY85ogn4IpHGyC7hG&quot; alt=&quot;Linkaout Web Interface (Image by Author).&quot; /&gt;&lt;br /&gt;Linkaout Web Interface (Image by Author).&lt;/p&gt;

&lt;!--end_excerpt--&gt;

&lt;h1 id=&quot;the-startup-fork-in-the-road-vc-funding-vs-the-bootstrappers-journey&quot;&gt;The Startup Fork in the Road: VC Funding vs. The Bootstrapper’s Journey&lt;/h1&gt;

&lt;p&gt;So, you’ve got a killer idea, the spark of entrepreneurial fire in your belly, and you’re ready to build. But before you dive headfirst into the exhilarating world of startups, there’s a fundamental question every founder must answer: How will you fuel your vision? Broadly, two paths diverge: seeking Venture Capital (VC) funding or embracing the often grittier, yet incredibly rewarding, path of bootstrapping. This isn’t just a financial decision; it’s a choice that shapes your company’s culture, your control, and your growth trajectory.&lt;/p&gt;

&lt;p&gt;Let’s break down these two distinct approaches before we explore how one of these philosophies inspired me and &lt;a href=&quot;https://alkedejupi.com/&quot;&gt;Alked&lt;/a&gt; to create Linkaout, a map-based app designed to connect Londoners with local events, with a particular focus on how we approached development and launch as bootstrappers.&lt;/p&gt;

&lt;h2 id=&quot;the-vc-route-rocket-fuel-and-high-stakes&quot;&gt;The VC Route: Rocket Fuel and High Stakes&lt;/h2&gt;

&lt;p&gt;Venture Capital funding is often portrayed as the glamorous path to startup stardom. It involves selling a portion of your company (equity) to investors in exchange for significant capital.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Upsides of VC Funding:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Accelerated Growth:&lt;/strong&gt; Access to substantial funds can mean scaling rapidly – hiring a large team, launching aggressive marketing campaigns, and capturing market share quickly.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Expertise and Network:&lt;/strong&gt; VCs often bring more than just money. They can provide invaluable mentorship, industry connections, and strategic guidance.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Validation and Credibility:&lt;/strong&gt; Securing VC funding can be seen as a stamp of approval, potentially attracting further investment, top talent, and customer trust.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Reduced Personal Financial Risk:&lt;/strong&gt; The financial burden is shared with investors, lessening the direct hit on your personal savings.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Downsides of VC Funding:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Loss of Control and Ownership:&lt;/strong&gt; Giving away equity means giving away a degree of control. Founders may find their decision-making power diluted and be beholden to investor expectations.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Intense Pressure for Rapid Returns:&lt;/strong&gt; VCs are looking for significant returns on their investment, often within a 5-10 year timeframe. This can create immense pressure to prioritize hyper-growth, sometimes at the expense of sustainable profitability or the founder’s original vision.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Focus on Growth over Profitability (Initially):&lt;/strong&gt; The mantra is often “grow big, fast,” with profitability sometimes taking a backseat in the early stages.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Exit Strategy Focus:&lt;/strong&gt; Most VCs invest with an exit in mind, such as an acquisition or an Initial Public Offering (IPO). This might not align with every founder’s long-term goals.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-bootstrappers-creed-building-brick-by-brick&quot;&gt;The Bootstrapper’s Creed: Building Brick by Brick&lt;/h2&gt;

&lt;p&gt;Bootstrapping, on the other hand, is the art of building a company from the ground up with little to no external funding. It relies on personal savings, revenue generated by the business itself, and a relentless focus on lean operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Upsides of Bootstrapping:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Full Ownership and Control:&lt;/strong&gt; You retain 100% ownership of your company and make all the decisions. Your vision remains undiluted.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Focus on Profitability and Sustainability:&lt;/strong&gt; Since you’re relying on your own revenue to grow, profitability becomes a key focus from day one, often leading to more resilient and sustainable business models.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Freedom and Flexibility:&lt;/strong&gt; You have the autonomy to pivot, adapt, and grow at your own pace without external investor pressure.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Customer-Centricity:&lt;/strong&gt; Bootstrappers are often laser-focused on their customers, as paying users are the lifeblood of their growth.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Fosters Creativity and Resourcefulness:&lt;/strong&gt; Limited resources force you to be innovative and find cost-effective solutions.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Downsides of Bootstrapping:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Slower Growth:&lt;/strong&gt; Growth is typically more organic and can be slower compared to VC-backed competitors with deep pockets.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Personal Financial Risk:&lt;/strong&gt; You’re often investing your own money, making the financial stakes very personal.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Limited Resources:&lt;/strong&gt; Scaling can be challenging without significant capital for marketing, hiring, or large-scale development.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Building Credibility Can Take Longer:&lt;/strong&gt; Without the halo effect of VC backing, establishing credibility and attracting talent can require more persistent effort.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-why-and-how-of-linkaout-a-bootstrapping-tale&quot;&gt;The “Why” and “How” of Linkaout: A Bootstrapping Tale&lt;/h2&gt;

&lt;p&gt;This brings us to Linkaout.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The idea was born from the bootstrapping philosophy, popularised by figures like &lt;a href=&quot;https://x.com/levelsio?ref=levels.io&quot;&gt;Pieter Levels&lt;/a&gt;—known for his mantra of building and launching products quickly to get real feedback from users. This “Indie Hacker” or “Maker” ethos champions rapid iteration and a direct line to the customer. Living in London, we often found it difficult to discover local events without switching between multiple platforms. That’s why we created &lt;a href=&quot;https://linkaout.com/&quot;&gt;Linkaout&lt;/a&gt;—a map-based app that helps you easily discover what’s happening around you, in the most intuitive way possible (Figure 1). The core motivation was to solve a personal pain point, a common starting place for many bootstrapped ventures, and to do so by building something people would genuinely use and, ideally, pay for, ensuring sustainability from the outset.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXdwloeKORUdwLwGvKjrj-rA5-RogPx5JHGsNIqsRCmu2LIJQ47eIbCdZOkHeL2C-Ag3mN5VlF6n-XGCkzAO_fAO_M545wPhrM8hQ7kW_uX-JeYl0XUXsNdyNwf7fBvGzhpwiIuU8g?key=I6soiPVYY85ogn4IpHGyC7hG&quot; alt=&quot;Figure 1: Linkaout Web Interface&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Figure 1: Linkaout Web Interface (Image by Author).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How? The Lean Development and Launch Process&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In true bootstrapping fashion, the approach was lean and agile. We built on tools we were familiar with—or had heard good things about—and quickly got to work. There was no lengthy fundraising process or a large, pre-hired team. Our first version included a simple map that let users create events in London, along with a login system, profile pages to view created events, and other basic features to immediately showcase the app’s potential.&lt;/p&gt;

&lt;p&gt;This wasn’t about perfecting every detail before launch. It was about identifying the core problem and building the absolute minimum required to see if the solution resonated with users. This led us to embrace a lean tech stack and strategically leverage free-tier services to keep costs to a minimum while maximizing development speed and flexibility.&lt;/p&gt;

&lt;p&gt;Here’s a closer look at the ‘how’ for a bootstrapped app like Linkaout:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Choosing a Lean and Cost-Effective Tech Stack:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bootstrappers need technology that is powerful, easy to use, and ideally offers a generous free tier to defer costs until revenue is generated. For Linkaout, or similar bootstrapped projects, a stack like the following is highly effective:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Supabase (Backend: Database, Authentication, Storage, Realtime):&lt;/strong&gt; As an open-source Firebase alternative, Supabase provides a powerful PostgreSQL database with built-in features like authentication, file storage, and real-time subscriptions. Its free tier is remarkably generous, offering sufficient database storage (e.g., 500MB), file storage (e.g., 1GB), and bandwidth for initial development and gaining early users. This eliminates the need for a dedicated backend team or managing complex server infrastructure from day one. Setting up user accounts, storing event data, and handling user uploads can all be done within Supabase’s free limits for a considerable time. The unlimited API requests in the free tier are a significant advantage for apps expecting variable usage.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;NextJS (Web Frontend):&lt;/strong&gt; A React framework that enables server-side rendering and static site generation. This is excellent for building fast, SEO-friendly web applications. For a bootstrapped team, NextJS streamlines front-end development, providing a solid structure and performance optimizations out-of-the-box. You can build your web presence, marketing site, or even parts of your application interface efficiently. Its flexibility allows for building everything from a simple landing page to a more complex web application.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Netlify (Web Hosting &amp;amp; Serverless Functions):&lt;/strong&gt; Netlify offers a fantastic platform for hosting static websites and serverless functions directly from your Git repository. Their free tier provides ample bandwidth (e.g., 100GB/month), build minutes (e.g., 300 minutes/month), and serverless function invocations (e.g., 125,000/month). This is more than enough to host a performant web application or landing page for a bootstrapped product and handle initial API calls via functions without incurring hosting costs. The seamless integration with Git makes the deployment process incredibly simple and fast.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;FlutterFlow (Cross-Platform Mobile App Development):&lt;/strong&gt; This is a low-code platform specifically designed for building native mobile applications (iOS and Android) using Google’s Flutter framework, and also supports web app development. FlutterFlow dramatically accelerates the UI build process with drag-and-drop components and integrates easily with backends like Supabase. For bootstrappers, this means building a high-quality, cross-platform mobile app can be done significantly faster and often without deep native mobile development expertise, saving considerable time and money. While FlutterFlow has paid tiers for advanced features and code export, their free tier allows for building and testing, providing a clear path to see if the platform meets your needs before committing financially. The ability to export code later also provides a safety net if more custom development is needed down the line.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By combining tools like these, a bootstrapped team can build a robust, scalable application with authentication, a database, file storage, a web presence, and native mobile apps, all while staying within free-tier limits during the crucial early stages of development and validation. The focus is on speed, functionality, and minimizing burn rate. This lean stack minimizes complexity and allows a small team (or even a solo founder) to manage the entire development process, potentially leveraging AI tools like &lt;strong&gt;Cursor&lt;/strong&gt; for code generation and assistance, or &lt;strong&gt;Lovable&lt;/strong&gt; for user feedback analysis to further streamline the process.&lt;/p&gt;

&lt;p&gt;Linkaout architecture design for the whole application is shown below in Figure 2:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXcopGchonFn9DbRvRfILD-UoXcaLCYdpJlVGvxB6QIl_I6J3NwcUjh-SUinhpDJz9H6Ay2BcKLSLusSSPjW2o3Tup6B95huxQLcNpOx0nxzmx7XPs6VcFdbrq9Byxwvn-LVPWMc-A?key=I6soiPVYY85ogn4IpHGyC7hG&quot; alt=&quot;Figure 2: Linkaout Architecture&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Figure 2: Linkaout Architecture (Image by Author).&lt;/p&gt;

&lt;p&gt;What’s remarkable is just how low the initial financial outlay can be. For Linkaout, the core development and initial launch costs were incredibly modest, primarily consisting of:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://lh7-rt.googleusercontent.com/docsz/AD_4nXecKkAc1n_cJ-bta3m4RFDr_pyHntledvDZbUT0DiskCvIhDnJmGniHjkDQep-0MOFha6N9pVpZqPYTXttDW28u8_XsMlfGtleBcRaV-XcshkXqmV2trJI6bpEMBuqrAqL5vmDMuQ?key=I6soiPVYY85ogn4IpHGyC7hG&quot; alt=&quot;Figure 3: Linkaout Development Costs&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Figure 3: Linkaout Development Costs (Image by Author).&lt;/p&gt;

&lt;p&gt;This demonstrates that the barrier to entry for launching a functional, cross-platform product is significantly lower than many might assume, thanks to the power of modern, developer-friendly tools and generous free tiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The “MVP of an MVP” Approach:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of aiming for a feature-rich application, the goal is to build the absolute minimum required to test the core value proposition. For Linkaout, this meant a map, the ability to create events, and user profiles. This stripped-down approach ensures you don’t waste time building features nobody wants. It forces clarity on what is truly essential for the first version that users will interact with. This initial version should be functional enough to gather genuine user feedback on the core concept.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Rapid Iteration and User Feedback:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With a lean stack and an MVP, the focus shifts to getting the product in front of real users as quickly as possible. As soon as we had a working MVP—an MVP of an MVP, you could say—we launched it across the web, the App Store, and Google Play. This aligns perfectly with the bootstrapping principle of getting your product in front of real users as quickly as possible to gather crucial feedback.&lt;/p&gt;

&lt;h2 id=&quot;launching-to-gain-traction-getting-your-product-seen&quot;&gt;Launching to Gain Traction: Getting Your Product Seen&lt;/h2&gt;

&lt;p&gt;The initial launch isn’t the end; it’s the beginning of a conversation with your market. For bootstrapped apps, gaining initial visibility without a massive marketing budget is key. This involves strategically leveraging platforms and communities where your target users spend time.&lt;/p&gt;

&lt;p&gt;Here are some common approaches for launching a bootstrapped product:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.producthunt.com/products/linkaout&quot;&gt;&lt;strong&gt;Product Hunt&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; A popular platform for discovering new products. A well-executed launch can provide a significant surge of early adopters and valuable feedback from a tech-savvy community. Strategies include building anticipation with a “Coming Soon” page, engaging with the community beforehand, crafting a compelling product page with visuals and a demo, planning for launch day engagement, and following up with supporters.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;App Stores (Apple App Store, Google Play Store):&lt;/strong&gt; For mobile apps, launching on the major app stores is essential. Focus on clear descriptions, compelling screenshots, and optimizing for relevant keywords to improve discoverability. Encourage early users to leave reviews. &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Online Communities and Forums:&lt;/strong&gt; Identify online communities, forums, and social media groups relevant to your product’s niche. Share your product in a non-spammy way, focusing on how it solves a specific problem for that community. Be prepared to engage and answer questions.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Content Marketing:&lt;/strong&gt; Create valuable content (blog posts, tutorials, videos) related to your product’s domain. This can attract organic traffic and establish your expertise, driving users to your product.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Direct Outreach:&lt;/strong&gt; Reach out to potential early adopters directly, whether through personal networks, targeted emails (if you have a relevant list), or introductions.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key for bootstrappers is to choose launch channels that align with their target audience and leverage them effectively with limited resources. The goal is to get the product in front of real users to gather feedback and begin building traction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improving the Product&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After the launch, we began iterating, adding small but meaningful features based on real user feedback gathered from initial usage and various launch efforts. This iterative process, driven by direct user input rather than boardroom directives, is a hallmark of a bootstrapped company that must stay closely attuned to its customers’ needs to survive and thrive. Every feature added, every bug fixed, is a direct response to what the market is telling you, ensuring that limited resources are always focused on delivering maximum value. &lt;/p&gt;

&lt;p&gt;This level of agility gives bootstrapped products a distinct advantage over large corporations and well-known apps, where new ideas often get stuck in endless meetings and approval loops. By staying lean and responsive, you can move faster, adapt quicker, and deliver what users want, before the competition even has time to react.&lt;/p&gt;

&lt;h2 id=&quot;conclusion-choosing-the-path-less-traveled-and-planning-for-the-future&quot;&gt;Conclusion: Choosing the Path Less Traveled and Planning for the Future&lt;/h2&gt;

&lt;p&gt;The choice between VC funding and bootstrapping is a deeply personal one, with significant implications for a startup’s journey. While VC can provide rapid acceleration, bootstrapping offers control, sustainability, and a direct connection with your users. For Linkaout, the bootstrapping path, empowered by a lean tech stack and strategic launch platforms, allowed us to quickly turn an idea into a working product, gather real-world feedback, and begin the process of building a sustainable business, brick by brick. It’s a path that demands resourcefulness and resilience, but offers the profound reward of building something truly yours, guided by the needs of the people you aim to serve. &lt;/p&gt;

&lt;p&gt;For those embarking on the entrepreneurial journey, especially if you’re starting solo, resources like &lt;a href=&quot;https://www.startupschool.org/&quot;&gt;&lt;strong&gt;YC Startup School&lt;/strong&gt;&lt;/a&gt; can be invaluable. Beyond providing foundational knowledge, they offer platforms, such as co-founder matching, that can help connect you with potential partners who share your vision and complementary skills.&lt;/p&gt;

&lt;p&gt;Furthermore, the bootstrapping journey doesn’t mean you’re locked into running the business forever. Unlike the often high-stakes exit demands of VC, bootstrappers have more flexibility in how they eventually move on. Options can include selling the business on platforms specifically designed for smaller, profitable online businesses like &lt;a href=&quot;https://www.buymicrostartups.com/&quot;&gt;&lt;strong&gt;BuyMyMicroStartup&lt;/strong&gt;&lt;/a&gt;, or pursuing &lt;strong&gt;Entrepreneurship Through Acquisition (ETA)&lt;/strong&gt;, where an individual or small group acquires a controlling stake in a mature, profitable small business with the intent of running it. These avenues provide alternative exit opportunities that align with the sustainable, profitable nature of many bootstrapped ventures.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was co-written with&lt;/em&gt; &lt;a href=&quot;https://alkedejupi.com/&quot;&gt;&lt;em&gt;Alked Ejupi&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 07 Jun 2025 00:00:00 +0000</pubDate>
				<link>https://ppiconsulting.dev//blog/blog92/</link>
				<guid isPermaLink="true">https://ppiconsulting.dev//blog/blog92/</guid>
			</item>
		
			<item>
				<title>Building a European Property Investment Agent with Google ADK</title>
				<description>&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4436/1*3dS_wVpwQBM5HTs3lJaMfQ.png&quot; alt=&quot;Agent Development Kit Frontend (Image by Author).&quot; /&gt;&lt;br /&gt;Agent Development Kit Frontend (Image by Author).&lt;/p&gt;

&lt;!--end_excerpt--&gt;

&lt;h2 id=&quot;building-a-european-property-investment-agent-with-google-adk&quot;&gt;Building a European Property Investment Agent with Google ADK&lt;/h2&gt;

&lt;table&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;td align=&quot;left&quot;&gt;
        :memo:   Please Note
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;

    &lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;
        &lt;ul&gt;
            This is a guest post originally published on &lt;a href=&quot;https://medium.com/p/ac2e27a6098b&quot; target=&quot;_blank&quot;&gt;Google Cloud - Community&lt;/a&gt;.
        &lt;/ul&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;end-to-end-demonstration-on-how-to-build-ai-agents-using-google-agent-development-kit&quot;&gt;End to end demonstration on how to build AI Agents using Google Agent Development Kit&lt;/h3&gt;

&lt;p&gt;The world of AI agents is rapidly evolving, offering exciting possibilities for automating tasks and providing specialized assistance. In fields like finance and investment, where analyzing vast amounts of dynamic data is crucial, AI agents can act as powerful assistants, sifting through information, identifying trends, and providing tailored insights. &lt;a href=&quot;https://google.github.io/adk-docs/&quot;&gt;Google’s Agent Development Kit (ADK)&lt;/a&gt; is a powerful framework designed to help developers build, test, and deploy these sophisticated agents with relative ease. In this post, we’ll walk through a practical example: creating a simple, yet illustrative, agent capable of providing insights into European property investment hotspots and economic outlooks. This project demonstrates how to structure an agent using the ADK’s core concepts to handle specific domain-related queries.&lt;/p&gt;

&lt;h2 id=&quot;what-is-google-adk&quot;&gt;What is Google ADK?&lt;/h2&gt;

&lt;p&gt;The Google Agent Development Kit (ADK) is a robust framework that simplifies the process of building AI agents powered by large language models (LLMs). At its heart, the ADK provides a structured way to define an agent’s capabilities. It allows developers to specify the LLM model the agent will use, provide clear instructions on how the agent should behave, and equip it with “tools” — essentially, functions or APIs the agent can call to perform specific actions or retrieve external information.&lt;/p&gt;

&lt;p&gt;One of the key strengths of the ADK is its support for creating hierarchies of agents. This pattern, often referred to as a “coordinator-worker” or “orchestrator” pattern, allows you to build complex agents by breaking down capabilities into smaller, more manageable specialized agents. A high-level “coordinator” agent receives the initial user query, understands the user’s intent, and then delegates the task to the most appropriate “worker” agent. This modular approach makes agents easier to develop, debug, and scale, as each worker agent can be focused on a specific domain or task, equipped with only the tools it needs. This contrasts with building a single, monolithic agent that tries to handle everything, which can quickly become unwieldy.&lt;/p&gt;

&lt;h2 id=&quot;setting-up-your-environment&quot;&gt;Setting Up Your Environment&lt;/h2&gt;

&lt;p&gt;Before we dive into the code that defines our European property investment agent, you need to set up your development environment. For this demonstration, I utilized a &lt;a href=&quot;https://cloud.google.com/workstations/docs&quot;&gt;Google Cloud Workstation&lt;/a&gt;, which offers a convenient, pre-configured cloud-based environment, saving the hassle of local setup complexities. However, you can also set this up on a local machine with Python installed.&lt;/p&gt;

&lt;h3 id=&quot;install-the-google-adk&quot;&gt;Install the Google ADK&lt;/h3&gt;

&lt;p&gt;Open your terminal or Cloud Workstation command line and run the following command to install the necessary Python library from PyPI:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install google-adk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command fetches and installs the core ADK library and its dependencies, giving you access to the classes and functions needed to define your agents and tools.&lt;/p&gt;

&lt;h3 id=&quot;authenticate-with-google-cloud&quot;&gt;Authenticate with Google Cloud&lt;/h3&gt;

&lt;p&gt;If you plan to use Google Cloud services, such as Vertex AI for accessing powerful LLMs like Gemini, you’ll need to authenticate your development environment. This command sets up your application default credentials, allowing your code running in the environment to access Google Cloud resources securely:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcloud auth application-default login
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Follow the prompts to log in with your Google account. This step is crucial if GOOGLE_GENAI_USE_VERTEXAI is set to “TRUE” in your environment configuration.&lt;/p&gt;

&lt;h2 id=&quot;project-structure&quot;&gt;Project Structure&lt;/h2&gt;

&lt;p&gt;Our project is organized within a standard Python package structure. The main code resides in a folder named europe_property_investor. Inside this folder, we have a few key files that define our agent and its configuration:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;europe_property_investor/
├── .env
├── __init__.py
└── agent.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This structure is clean and follows Python best practices for creating reusable modules.&lt;/p&gt;

&lt;p&gt;Let’s look at the purpose of each file:&lt;/p&gt;

&lt;h3 id=&quot;env&quot;&gt;.env&lt;/h3&gt;

&lt;p&gt;This file is used to store environment variables that configure our agent’s runtime behavior, particularly its connection to Google Cloud services. Using a .env file is a common practice for managing configuration settings separately from your code, making it easy to change settings without modifying the core logic.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GOOGLE_CLOUD_PROJECT=&quot;TODO&quot; # Replace TODO with your Google Cloud Project ID
GOOGLE_CLOUD_LOCATION=&quot;us-central1&quot; # e.g., us-central1 or europe-west1
GOOGLE_GENAI_USE_VERTEXAI=&quot;TRUE&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You &lt;strong&gt;must&lt;/strong&gt; replace “TODO” with your actual Google Cloud Project ID. The GOOGLE_CLOUD_LOCATION specifies the region for Vertex AI, and GOOGLE_GENAI_USE_VERTEXAI=”TRUE” tells the ADK to use Vertex AI for accessing the Gemini model, rather than the public GenAI API.&lt;/p&gt;

&lt;h3 id=&quot;initpy&quot;&gt;&lt;strong&gt;init&lt;/strong&gt;.py&lt;/h3&gt;

&lt;p&gt;This file is essential for Python to recognize the europe_property_investor directory as a package. It can also be used to control which objects are exposed when the package is imported. In our simple case, it primarily serves to make the main root_agent directly accessible from the package level.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;agent&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;.agent&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By importing root_agent here, we can easily refer to our main agent when running the ADK web interface command later.&lt;/p&gt;

&lt;h3 id=&quot;agentpy&quot;&gt;agent.py&lt;/h3&gt;

&lt;p&gt;This is the core of our agent application. It contains all the definitions for the tools our agent can use, the specialized “worker” agents that handle specific tasks, and the main “coordinator” agent that acts as the entry point for user interactions and orchestrates the flow by delegating tasks to the appropriate workers.&lt;/p&gt;

&lt;p&gt;Let’s break down the key components within agent.py:&lt;/p&gt;

&lt;h3 id=&quot;imports-and-configuration&quot;&gt;Imports and Configuration&lt;/h3&gt;

&lt;p&gt;We begin by importing the necessary classes from the google.adk library, as well as standard Python typing utilities. We also define the specific LLM model we intend to use.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.agents&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt; 
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.tools.agent_tool&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AgentTool&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;google.adk.tools.google_search_tool&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;google_search&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TypedDict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;MODEL_NAME&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gemini-2.0-flash&quot;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using gemini-2.0-flash provides a good balance of performance and cost-effectiveness for many agent tasks. You could experiment with other models depending on your specific needs and budget.&lt;/p&gt;

&lt;h3 id=&quot;typeddict-definitions&quot;&gt;TypedDict Definitions&lt;/h3&gt;

&lt;p&gt;TypedDict from the typing module is a powerful feature that allows us to define dictionaries with specific keys and value types. While not strictly required by the ADK, using TypedDict for the output of our tools is highly recommended. It serves as clear documentation for the structure of the data the tool returns, which is invaluable for maintainability. Crucially, this type information is also provided to the LLM, helping it better understand the data it receives from tool calls and improving its ability to process and respond based on that data.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# --- TypedDict Definitions (Shared by relevant agents/tools) ---
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PropertyHotspot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TypedDict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;property_types_favored&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;reasoning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;potential_appreciation_outlook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;average_rental_yield_pa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;market_sentiment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;risk_level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;key_drivers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;potential_headwinds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;investment_horizon_suitability_years&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data_source_year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EconomicOutlook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TypedDict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gdp_growth_forecast_pa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inflation_rate_pa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stability_assessment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;key_economic_notes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data_source_year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These definitions clearly outline the expected data fields for property hotspots and economic outlooks, making the code more readable and helping the LLM interpret the tool results accurately.&lt;/p&gt;

&lt;h3 id=&quot;tool-function-definitions&quot;&gt;Tool Function Definitions&lt;/h3&gt;

&lt;p&gt;These are standard Python functions that encapsulate specific capabilities our agent needs. The ADK allows the LLM to call these functions dynamically based on the user’s request and the agent’s instructions. In a real-world application, these functions would typically interact with external services, databases, or APIs to fetch real-time data or perform actions. For this demonstration, we use simple mock data stored directly within the functions to simulate the tool’s behavior.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;get_european_property_hotspots: This function simulates fetching information about promising European real estate investment locations. It accepts parameters that allow filtering by countries, investment horizon, risk appetite, and property type focus, demonstrating how the LLM can pass arguments to tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_european_property_hotspots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;countries_of_interest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;investment_horizon_years&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;risk_appetite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;property_type_focus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Fetches detailed information on promising European real estate investment locations.
    This tool can be filtered by countries, investment horizon, risk appetite, and property type focus.
    Returns a list of dictionaries, each representing a property hotspot with detailed attributes.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Tool (get_european_property_hotspots) called with countries: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;countries_of_interest&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, &quot;&lt;/span&gt;
        &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;horizon: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;investment_horizon_years&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; years, risk: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;risk_appetite&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, types: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;property_type_focus&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;all_hotspots_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PropertyHotspot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Lisbon (Principe Real, Alfama)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Portugal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;property_types_favored&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Renovated Apartments&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Luxury Residences&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Residential&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;reasoning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Sustained international demand, strong tourism, tech hub growth. Prime areas continue to appreciate.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_appreciation_outlook&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;High (6-9% annually in prime zones)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;average_rental_yield_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;3-4.5%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;market_sentiment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Positive&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;risk_level&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;key_drivers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Golden Visa (historic impact)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Tech sector&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Tourism&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Lifestyle appeal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_headwinds&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Rising prices affecting affordability&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Regulatory changes for short-term rentals&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;investment_horizon_suitability_years&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;5-10&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 Q1&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Porto (Cedofeita, Bonfim)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Portugal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;property_types_favored&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Residential Apartments&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Guesthouses&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Residential&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;reasoning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;More affordable than Lisbon with significant growth, vibrant culture, and increasing tourism.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_appreciation_outlook&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;High (7-10% annually)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;average_rental_yield_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;4-6%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;market_sentiment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Very Positive&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;risk_level&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;key_drivers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Tourism growth&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Urban regeneration&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Lower entry point than Lisbon&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_headwinds&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Infrastructure strain with growth&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Increased competition&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;investment_horizon_suitability_years&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;5-7&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 Q1&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Valencia (Ruzafa, El Cabanyal)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Spain&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;property_types_favored&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Beachfront properties (El Cabanyal)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Modern Apartments (Ruzafa)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Residential&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Vacation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;reasoning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Excellent quality of life, growing tech scene, more affordable than Barcelona/Madrid. Coastal regeneration.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_appreciation_outlook&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium-High (5-8% annually)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;average_rental_yield_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;4-5.5%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;market_sentiment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Positive&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;risk_level&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;key_drivers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Lifestyle&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Tech investment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Tourism&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;University city&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_headwinds&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Some areas saturated&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Local rental regulations&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;investment_horizon_suitability_years&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;3-7&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 Q1&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Malaga City&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Spain&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;property_types_favored&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;City center apartments&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Properties near tech park&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Residential&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Vacation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;reasoning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Significant urban renewal, cultural hub, growing tech presence beyond just Costa del Sol tourism.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_appreciation_outlook&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium-High (5-7% annually)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;average_rental_yield_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;4-5%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;market_sentiment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Positive&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;risk_level&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium-Low&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;key_drivers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Tech hub development&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cultural tourism&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Infrastructure investment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_headwinds&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Seasonal tourism dependency in wider region&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Price increases in prime spots&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;investment_horizon_suitability_years&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;5-10&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 Q1&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Athens (Koukaki, Pangrati)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Greece&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;property_types_favored&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Renovated apartments for short/long term let&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Golden Visa eligible properties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Residential&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;reasoning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Economic recovery, tourism boom, and government incentives. Focus on central, well-connected areas.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_appreciation_outlook&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium (4-7% annually)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;average_rental_yield_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;4-6%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;market_sentiment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cautiously Optimistic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;risk_level&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium-High&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;key_drivers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Tourism&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Golden Visa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Infrastructure upgrades&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Low starting base&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_headwinds&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Bureaucracy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Geopolitical factors in region&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Taxation uncertainties&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;investment_horizon_suitability_years&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;5-7&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 Q1&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Warsaw (Mokotów, Srodmiescie)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Poland&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;property_types_favored&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;New build apartments&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Buy-to-let residential&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Residential&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;reasoning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Strong domestic economy, increasing foreign investment, major business services hub. Relatively stable.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_appreciation_outlook&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium (4-6% annually)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;average_rental_yield_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;5-6.5%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;market_sentiment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Positive&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;risk_level&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium-Low&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;key_drivers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Economic growth (pre-war regional stability)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Business outsourcing&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Young population&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_headwinds&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Regional geopolitical tensions (Ukraine impact)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Inflationary pressures&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;investment_horizon_suitability_years&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;5-10&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 Q1&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Budapest (District VII, IX)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hungary&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;property_types_favored&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Renovation projects&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Short-term rental units&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Residential&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Vacation&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;reasoning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Major tourist destination, relatively low prices for a European capital, vibrant culture.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_appreciation_outlook&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium (3-6% annually)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;average_rental_yield_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;4.5-6%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;market_sentiment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Neutral to Cautiously Optimistic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;risk_level&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Medium-High&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;key_drivers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Tourism&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;University city&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Foreign investment in specific sectors&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;potential_headwinds&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Government policies&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Currency fluctuations (HUF)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Oversupply in certain rental segments&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;investment_horizon_suitability_years&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;3-7&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 Q1&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;filtered_hotspots_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_hotspots_data&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countries_of_interest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;filtered_hotspots_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;spot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spot&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filtered_hotspots_data&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;country&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countries_of_interest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;risk_appetite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;normalized_risk_appetite&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;risk_appetite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;low&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalized_risk_appetite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;risk_levels_to_match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;low&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;medium-low&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;high&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalized_risk_appetite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;risk_levels_to_match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;high&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;medium-high&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;medium&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalized_risk_appetite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;risk_levels_to_match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;medium&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;medium-low&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;medium-high&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;risk_levels_to_match&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;normalized_risk_appetite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;filtered_hotspots_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spot&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filtered_hotspots_data&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;risk_level&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;risk_levels_to_match&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;property_type_focus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;temp_filtered&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;normalized_property_type_focus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptf&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;property_type_focus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spot&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filtered_hotspots_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;spot_favored_types_lower&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fav_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fav_type&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;property_types_favored&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;focused_type&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spot_favored_types_lower&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;focused_type&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normalized_property_type_focus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;temp_filtered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;filtered_hotspots_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;temp_filtered&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filtered_hotspots_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;criteria_summary&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countries_of_interest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;criteria_summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;countries: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;, &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;countries_of_interest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;investment_horizon_years&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;criteria_summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;horizon: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;investment_horizon_years&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; years&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;risk_appetite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;criteria_summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;risk: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;risk_appetite&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;property_type_focus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;criteria_summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;types: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;, &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;property_type_focus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reasoning_message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;No specific hotspots found matching all criteria: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;criteria_summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;. Current data from &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all_hotspots_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;data_source_year&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all_hotspots_data&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;N/A&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.&quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;location&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;property_types_favored&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;reasoning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasoning_message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;potential_appreciation_outlook&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;average_rental_yield_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;market_sentiment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;risk_level&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;key_drivers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;potential_headwinds&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;investment_horizon_suitability_years&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filtered_hotspots_data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The print statement inside the function is a simple way to see when the tool is called and what arguments the LLM provides, which is helpful for debugging. The filtering logic demonstrates how a real tool might process parameters to refine its results.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;get_country_economic_outlook: This function simulates retrieving economic data for a given European country.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_country_economic_outlook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Provides a brief economic outlook (GDP growth, inflation, stability)
    for a specified European country. Returns a dictionary containing economic details.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Tool (get_country_economic_outlook) called for &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;outlooks_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EconomicOutlook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;portugal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Portugal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gdp_growth_forecast_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1.8%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;inflation_rate_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.5%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;stability_assessment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Moderately Stable&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;key_economic_notes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Tourism dependent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;EU recovery funds boosting investment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Focus on tech growth&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 H1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;spain&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Spain&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gdp_growth_forecast_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.1%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;inflation_rate_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.8%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;stability_assessment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Moderately Stable&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;key_economic_notes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Strong tourism rebound&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Renewable energy investment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Regional disparities&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 H1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;greece&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Greece&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gdp_growth_forecast_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.5%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;inflation_rate_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;3.2%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;stability_assessment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Improving&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;key_economic_notes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Post-bailout recovery&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Investment in infrastructure&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;High national debt remains a concern&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 H1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;poland&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Poland&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gdp_growth_forecast_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;3.0%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;inflation_rate_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;4.5%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;stability_assessment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Stable but watchful (geopolitics)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;key_economic_notes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Strong manufacturing base&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Proximity to Ukraine war poses some risk/impact&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;EU funding utilization key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 H1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;hungary&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Hungary&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gdp_growth_forecast_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.2%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;inflation_rate_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;5.0%&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;stability_assessment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Moderately Stable with political variables&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;key_economic_notes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Dependent on foreign manufacturing (automotive)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;EU funds disputes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Forint volatility&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2025 H1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outlooks_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_data&lt;/span&gt; 
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;gdp_growth_forecast_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;inflation_rate_pa&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
            &lt;span class=&quot;s&quot;&gt;&quot;stability_assessment&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Data not available in mock set&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
            &lt;span class=&quot;s&quot;&gt;&quot;key_economic_notes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;No specific data for this country in the current simulated dataset.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; 
            &lt;span class=&quot;s&quot;&gt;&quot;data_source_year&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;N/A&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Again, this uses mock data but illustrates how a tool would take a specific input (a country name) and return structured information.&lt;/p&gt;

&lt;h3 id=&quot;worker-agent-definitions&quot;&gt;Worker Agent Definitions&lt;/h3&gt;

&lt;p&gt;Worker agents are specialized agents designed to handle specific types of queries by utilizing a limited set of relevant tools. This specialization makes their instructions simpler and their behavior more predictable for their specific domain.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;property_hotspots_agent: This agent is solely focused on providing information about property investment locations. It is equipped with only the get_european_property_hotspots tool. Its instruction guides it to use this tool based on the criteria provided by the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;property_hotspots_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;PropertyHotspotsAgent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MODEL_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You are a specialist in European property hotspots. You have one tool to find detailed property investment locations. Use it based on the user&apos;s criteria (countries, investment horizon, risk appetite, property type focus).&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Provides detailed information on promising European real estate investment locations.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_european_property_hotspots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Its instruction is concise and directly relates to the capability of its single tool.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;economic_outlook_agent: This agent specializes in providing economic summaries for countries. It is equipped with only the get_country_economic_outlook tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;economic_outlook_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EconomicOutlookAgent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MODEL_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You are a specialist in European country economic outlooks. You have one tool to fetch economic data (GDP, inflation, stability) for a given country.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Provides a brief economic outlook for a specified European country.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_country_economic_outlook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Similarly, its instruction is tailored to the economic outlook domain.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;google_search_agent: This agent serves as a general-purpose fallback for queries that cannot be handled by the more specialized agents. It wraps the standard google_search tool provided by the ADK.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;google_search&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GoogleSearch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MODEL_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;You are a web search assistant. You have one tool for performing Google searches. Use it to find specific, recent information or anything not covered by other specialized agents.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Performs Google searches for general information or recent news.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;google_search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;google_search_grounding&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AgentTool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;agent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;google_search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;google_search_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GoogleSearchAgent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MODEL_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Given a query that its not possible to ask using PropertyHotspotsAgent and EconomicOutlookAgent use Google Search to find an answer. If no answer is found, inform the user you don&apos;t know the answer. Inform the user, you are using Google Search to reply. If the user asks anything not related to European Property Investment, decline to answer.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Uses Google search to attempt to answer questions that are not possible to answer using PropertyHotspotsAgent and EconomicOutlookAgent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;google_search_grounding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This agent’s instruction is crucial — it tells it to &lt;em&gt;only&lt;/em&gt; use search if the other agents can’t answer and to stay within the domain of European Property Investment.&lt;/p&gt;

&lt;h3 id=&quot;coordinator-agent-definition&quot;&gt;Coordinator Agent Definition&lt;/h3&gt;

&lt;p&gt;The root_agent is the top-level agent and the one directly invoked by the ADK web interface. Its primary role is not to answer queries itself, but to understand the user’s intent and delegate the task to the most appropriate specialized worker agent. This is where the orchestration happens.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# --- Coordinator Agent Definition ---
# This is the agent that will be invoked by &apos;adk web&apos;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root_agent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EuropePropertyInvestmentCoordinator&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MODEL_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;instruction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;You are a coordinator agent for European property investment analysis. &quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;Your role is to understand the user&apos;s query and delegate the task to the most appropriate specialized agent. &quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;You have access to the following specialized agents:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;- **PropertyHotspotsAgent**: Use this agent to find detailed information about specific property investment locations, including filtering by criteria like country, risk, and property type.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;- **EconomicOutlookAgent**: Use this agent to get the general economic outlook for a specific country (e.g., GDP growth, inflation).&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;- **GoogleSearchAgent**: Use this agent for very recent news, highly specific details not covered by other agents, or broader web searches.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;Follow these steps:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;1. Analyze the user&apos;s query to determine the type of information needed.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;2. If the query is broad or unclear for a specific task (e.g., &apos;best investments&apos; without criteria for PropertyHotspotsAgent), ask clarifying questions to get necessary details (like preferred countries, risk appetite, investment horizon, property types).&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;3. Choose the single best specialized agent for the core task. For example, if the user asks for &apos;property hotspots in Spain with medium risk&apos;, delegate to PropertyHotspotsAgent. If they ask &apos;economic outlook for Portugal&apos;, delegate to EconomicOutlookAgent. If they ask &apos;recent property news in Berlin&apos;, delegate to GoogleSearchAgent.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;4. Clearly state which agent you are delegating to and what you are asking it to do.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;5. Relay the information from the specialized agent back to the user in a clear and helpful manner.&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;6. If a query requires information from multiple domains (e.g., property hotspots AND economic outlook for those countries), you might need to break it down and call relevant agents sequentially, presenting a synthesized answer. However, for a single user turn, focus on the primary intent and choose one agent if possible, or explain the need for multiple steps.&quot;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;Do not try to use tools directly yourself; your function is to coordinate your sub-agents.&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Coordinates property investment queries by delegating to specialized agents for property hotspots, economic outlooks, and web searches.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sub_agents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;property_hotspots_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;economic_outlook_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;google_search_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The instruction for the root_agent is the most detailed, as it defines the agent’s overall strategy for handling user requests. It explicitly lists the available sub-agents and provides a step-by-step process for analyzing the query, asking clarifying questions when needed, selecting the appropriate sub-agent, and relaying the final response. This clear instruction is critical for guiding the LLM’s reasoning and delegation process.&lt;/p&gt;

&lt;h2 id=&quot;running-the-agent&quot;&gt;Running the Agent&lt;/h2&gt;

&lt;p&gt;With the .env, &lt;strong&gt;init&lt;/strong&gt;.py, and agent.py files correctly set up in your europe_property_investor directory, you can now run your agent using the ADK command-line interface. Navigate in your terminal to the directory &lt;em&gt;containing&lt;/em&gt; your europe_property_investor folder and execute the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adk web
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command does several things: it finds the root_agent defined in your package (thanks to the &lt;strong&gt;init&lt;/strong&gt;.py file), initializes it, and starts a local web server. This server provides a simple chat interface in your web browser, allowing you to interact directly with your root_agent.&lt;/p&gt;

&lt;p&gt;Once the server is running (usually accessible at &lt;a href=&quot;http://localhost:8000&quot;&gt;http://localhost:8000&lt;/a&gt;), open your web browser and navigate to the provided address. You’ll see a chat window where you can type your queries related to European property investment (Figure 1).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/3840/1*3hqyXS7WD__KoVla-OkpFA.gif&quot; alt=&quot;Figure 1: Live Demonstration of Agent Frontend (Video by Author).&quot; /&gt;&lt;br /&gt;Figure 1: Live Demonstration of Agent Frontend (Video by Author).&lt;/p&gt;

&lt;p&gt;Try typing queries such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;“Tell me about property hotspots in Portugal.” (This should trigger the PropertyHotspotsAgent)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;“What is the economic outlook for Spain?” (This should trigger the EconomicOutlookAgent)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;“Find recent news about property market changes in Berlin.” (This should trigger the GoogleSearchAgent)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;“What are the best investment opportunities?” (This should likely prompt the root_agent to ask for clarification, as per its instruction).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Observe how the root_agent processes your request, identifies the relevant information needed, and then delegates the task to the appropriate specialized worker agent. The worker agent will then use its assigned tool (either fetching mock data or performing a simulated search), and the root_agent will present the result back to you in a conversational manner. This interaction loop demonstrates the power of the coordinator-worker pattern in action.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This practical demonstration using the Google Agent Development Kit illustrates how you can build intelligent agents with structured behavior. By defining specialized tools and organizing agents in a hierarchical coordinator-worker pattern, you can create applications that are modular, maintainable, and capable of handling complex, domain-specific queries.&lt;/p&gt;

&lt;p&gt;While this “Europe Property Investor” agent currently uses mock data, it provides a solid foundation. The next steps could involve integrating real-time data sources — such as financial market APIs, real estate listing services, or economic data providers — into the tool functions. You could also expand the capabilities by adding more specialized worker agents and tools, perhaps for analyzing specific property types (commercial, industrial), assessing legal or tax implications, or even performing rudimentary financial modeling. The modularity offered by the ADK makes such expansions significantly more manageable. Experiment with different queries and observe how the root_agent delegates to the worker agents; understanding this flow is key to building more sophisticated agents with the Google ADK!&lt;/p&gt;
</description>
				<pubDate>Mon, 26 May 2025 00:00:00 +0000</pubDate>
				<link>https://ppiconsulting.dev//blog/blog91/</link>
				<guid isPermaLink="true">https://ppiconsulting.dev//blog/blog91/</guid>
			</item>
		
			<item>
				<title>LLMs Evaluation on GCP</title>
				<description>&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/2048/1*Y4lleX5fvkEjk0eVzqXTIw.jpeg&quot; alt=&quot;AI Generated (Image by Author).&quot; /&gt;&lt;br /&gt;AI Generated (Image by Author).&lt;/p&gt;

&lt;!--end_excerpt--&gt;

&lt;h2 id=&quot;llms-evaluation-on-gcp&quot;&gt;LLMs Evaluation on GCP&lt;/h2&gt;

&lt;table&gt;
    &lt;thead&gt;
    &lt;tr&gt;
        &lt;td align=&quot;left&quot;&gt;
        :memo:   Please Note
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/thead&gt;

    &lt;tbody&gt;
    &lt;tr&gt;
        &lt;td&gt;
        &lt;ul&gt;
            This is a guest post originally published on &lt;a href=&quot;https://medium.com/p/9186fad73f22&quot; target=&quot;_blank&quot;&gt;Google Cloud - Community&lt;/a&gt;.
        &lt;/ul&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;an-introduction-to-some-of-the-most-common-evaluation-approaches-for-llm-applications-and-how-gcp-can-support-you-across-the-journey&quot;&gt;An introduction to some of the most common evaluation approaches for LLM applications and how GCP can support you across the journey.&lt;/h3&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Widespread availability and fast-tracked progresses in LLM performance have made it really easy for practitioners to develop fully fledged AI backed applications in a matter of days. Regardless, even if the road to production may be paved with good intentions, it’s too often littered with the wrecks of projects that skipped rigorous pre-production evaluation. Thorough testing and validation are the essential guardrails that keep a system on track and prevent costly, late-stage failures.&lt;/p&gt;

&lt;p&gt;The foundational model of choice is merely the source of an LLM’s backed application potential (Figure 1). True evaluation is charting the full course of the river: the data that forms its currents, the infrastructure that shapes its banks, and the applications that are its ultimate destination. Only by understanding this entire flow can we predict whether the LLM will reach its potential or run dry before it meets the sea.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/2000/0*OD5fGaXoj76cC_XY&quot; alt=&quot;Figure 1: LLM Evaluation Overview (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 1: LLM Evaluation Overview (Image by Author).&lt;/p&gt;

&lt;p&gt;Defining a standardized way to evaluate an LLM can not only make it possible to quantify the model accuracy but also:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Tracking progress over different development iterations.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Streamline comparison between different models.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Optimizing for fair use (e.g. creating transparent and reproducible processes for bias mitigation).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Meeting regulatory and Service Level Agreements (SLAs) requirements.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;metrics&quot;&gt;Metrics&lt;/h2&gt;

&lt;p&gt;Metrics to evaluate LLMs can be further divided into 2 categories: quantitative and qualitative.&lt;/p&gt;

&lt;p&gt;Quantitative metrics can be easily calculated using numeric formulas, some examples include (Figure 2):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Perplexity&quot;&gt;&lt;strong&gt;Perplexity&lt;/strong&gt;&lt;/a&gt;: how well the model can predict the next word in a sentence (the lower, the better).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/ROUGE_(metric)&quot;&gt;&lt;strong&gt;ROUGE (Recall-Oriented Understudy for Gisting Evaluation)&lt;/strong&gt;&lt;/a&gt;: is used for text summarization tasks and checks the overlap between human summaries and LLM generated summaries. ROUGE focuses mainly on recall.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/BLEU&quot;&gt;&lt;strong&gt;BLEU (Bilingual Evaluation Understudy)&lt;/strong&gt;&lt;/a&gt;: is used for translation tasks and assesses the LLM output against a reference translation. BLEU focuses instead primarily on precision.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Accuracy_and_precision&quot;&gt;&lt;strong&gt;Accuracy&lt;/strong&gt;&lt;/a&gt;: for traditional classification tasks (e.g. spam/not spam).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/2000/0*3y6aBH3Pcn-5E-iF&quot; alt=&quot;Figure 2: LLMs Tasks vs Metrics (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 2: LLMs Tasks vs Metrics (Image by Author).&lt;/p&gt;

&lt;p&gt;Qualitative metrics focus more on capturing overall language/content quality and usually involve humans or &lt;a href=&quot;https://hamel.dev/blog/posts/llm-judge/&quot;&gt;LLMs as a Judge&lt;/a&gt; in order to be estimated, some examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Factuality&lt;/strong&gt;: does the LLM hallucinate? (provides false/misleading information) Is the information provided grounded?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Relevance&lt;/strong&gt;: how relevant is the LLM response compared to the prompt request?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Fluency&lt;/strong&gt;: does the response flow sound natural and realistic?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Coherence&lt;/strong&gt;: are the different phrases/sentences logically consistent?&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/3200/0*Bp03SN3CxtUsyzkf&quot; alt=&quot;Figure 3: Metrics Choice Decision Tree (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 3: Metrics Choice Decision Tree (Image by Author).&lt;/p&gt;

&lt;p&gt;Similar approaches can then be applied when evaluating not only LLM text outputs but also other forms of content such as images. Particularly, for Image synthesis metrics such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Inception_score&quot;&gt;&lt;strong&gt;Inception score&lt;/strong&gt;&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Fr%C3%A9chet_inception_distance&quot;&gt;&lt;strong&gt;Frechet inception distance&lt;/strong&gt;&lt;/a&gt; can be used, and to assess image quality &lt;strong&gt;Structural similarity index&lt;/strong&gt; and &lt;strong&gt;peak signal-to-noise ratio&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Finally, another aspect to keep track of is mitigation of any form of &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_cognitive_biases&quot;&gt;bias&lt;/a&gt; and ensuring &lt;a href=&quot;https://cloud.google.com/vertex-ai/docs/evaluation/intro-evaluation-fairness&quot;&gt;fairness&lt;/a&gt;. Some key metrics can help us ensuring this include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Demographic parity&lt;/strong&gt;: Are loan approvals granted at similar rates for all races? (the model predictions should not be skewed towards any particular group).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Equal opportunity&lt;/strong&gt;: Are equally qualified candidates from all demographics being wrongly rejected at the same rate? (the model should not disproportionately disadvantage certain groups by making more mistakes for them).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Counterfactual Fairness&lt;/strong&gt;: Would a person’s job application be evaluated differently if their gender was changed in the application? (to idea is to identify and eliminate biases directly linked to sensitive attributes).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When evaluating a model it can also be helpful to look for possible intrinsic training biases. For example, usually models tend to prefer verbose answers over short ones or prefer one option over another based on its positional order.&lt;/p&gt;

&lt;h2 id=&quot;llm-evaluation-approachessteps&quot;&gt;LLM Evaluation Approaches/Steps&lt;/h2&gt;

&lt;p&gt;There are currently 4 key LLM Evaluation Approaches/Steps:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Benchmark/Golden Dataset&lt;/strong&gt;: collecting/creating samples of examples reference answers we can evaluate an LLM against. In this case, it is vital to tailor the golden dataset to match future users expectations and needs. Depending on size and structure, these could then be stored in GCP services such as Cloud Storage, BigQuery, Spanner, etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Business Metrics&lt;/strong&gt;: estimating the overall impact of our LLM system on business performance, return on investment, revenue, etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;LLM as a Judge&lt;/strong&gt;: using another LLM to evaluate our LLM system for a set of tasks against some predetermined criterias. Some frequent issues with the “LLM as a Judge” approach are: self-bias, inconsistent scoring, and poor correlation with human evaluations.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;User Provided Feedback&lt;/strong&gt;: using human feedback to direct the model towards more useful responses.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These evaluation approaches can then come to action at different stages in the pre/post deployment process (Figure 4).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4076/1*AfwxY9arDr5Hzdf4yzu2iQ.png&quot; alt=&quot;Figure 4: LLM Evaluation Stages (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 4: LLM Evaluation Stages (Image by Author).&lt;/p&gt;

&lt;h2 id=&quot;benchmarkgolden-dataset&quot;&gt;Benchmark/Golden Dataset&lt;/h2&gt;

&lt;h3 id=&quot;getting-benchmark-datasets&quot;&gt;Getting Benchmark Datasets&lt;/h3&gt;

&lt;p&gt;When working with company specific use cases it would then be advisable to create your own internal golden/benchmark dataset to evaluate your model based on company specific internal jargon (e.g. financial, medical terms), etc. This approach can in fact provide much more relevant evaluations tailored to your use case compared to using out of the box industry benchmarks. In case no data is available, generating synthetic data could be used as a last resort.&lt;/p&gt;

&lt;p&gt;Additionally, there are a large number of existing Evaluation Benchmark datasets commonly used in the industry in order to evaluate LLMs, some include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;GLUE (General Language Understanding Evaluation):&lt;/strong&gt; Assesses overall language understanding through nine diverse tasks, including sentiment analysis, question answering, and textual entailment. Provides a single aggregate score for simplified model comparison.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;SuperGLUE:&lt;/strong&gt; A more challenging successor to GLUE, designed after models surpassed human performance on the original benchmark. Features complex tasks requiring advanced language understanding and reasoning.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;HellaSwag:&lt;/strong&gt; Evaluates commonsense reasoning by requiring models to predict the most logical continuation of a given scenario from multiple choices.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;TruthfulQA:&lt;/strong&gt; Focuses on the model’s ability to provide truthful and non-misleading answers, crucial for building reliable AI systems.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;MMLU (Massive Multitask Language Understanding):&lt;/strong&gt; A comprehensive benchmark with over 15,000 questions across 57 subjects, spanning STEM, humanities, and more. Measures a model’s breadth of knowledge and its ability to perform complex reasoning across diverse domains.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;ARC (AI2 Reasoning Challenge):&lt;/strong&gt; Concentrates on scientific reasoning abilities.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;LAMBADA:&lt;/strong&gt; Tests a model’s proficiency in predicting the final word of a text passage, assessing long-range dependencies.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;SQuAD (Stanford Question Answering Dataset):&lt;/strong&gt; Evaluates reading comprehension and the ability to extract answers from a given text.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;labeled-vs-unlabeled-datasets&quot;&gt;Labeled vs Unlabeled Datasets&lt;/h3&gt;

&lt;p&gt;To aid with the labeling process, different enterprise solutions have been created such as &lt;a href=&quot;https://console.cloud.google.com/marketplace/product/labelbox-tackle-public/labelbox-product-gcp&quot;&gt;Labelbox&lt;/a&gt;, to provide an easy to use interface where to label data and outsource human evaluators (if internal workforce is not possible and data not too sensitive).&lt;/p&gt;

&lt;p&gt;Evaluation can also be possible without labeled data (using for example NannyML open source approach with the &lt;a href=&quot;https://ppiconsulting.dev/blog/blog71/&quot;&gt;Confidence-Based Performance Estimation algorithm&lt;/a&gt; or LLM Autoraters) but often less precise and error prone.&lt;/p&gt;

&lt;h2 id=&quot;user-provided-feedback&quot;&gt;User Provided Feedback&lt;/h2&gt;

&lt;p&gt;Human evaluators, front-facing users and LLM Judges can support the evaluation process in 2 main possible ways: direct or comparative assessment.&lt;/p&gt;

&lt;p&gt;With direct assessment, a user might be asked to rate an answer or complete some sort of survey following a conversation with an LLM (using pointwise metrics). In comparative assessments, users can instead be provided with different variations of the same answer and asked to pick which one they prefer (through pairwise comparison). This approach can be particularly useful when trying to fine tune a model or perform some form of A/B testing to decide which model is best to use.&lt;/p&gt;

&lt;h2 id=&quot;task-specific-approaches&quot;&gt;Task specific approaches&lt;/h2&gt;

&lt;p&gt;So far, we have considered how to evaluate general LLM predictions, although LLMs are usually part of wider systems to solve actual applications. Some common examples include, AI Powered Search, RAG (​​Retrieval Augmented Generation) and Agents. In these cases, additional applications related metrics are needed.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;AI Search:&lt;/strong&gt; Evaluation of search quality using Vertex AI Search can be performed by providing examples of typical user queries paired with best matching results, more information about the process can be found &lt;a href=&quot;https://cloud.google.com/generative-ai-app-builder/docs/evaluate-search-quality#unstructured-data&quot;&gt;here&lt;/a&gt;. To further improve performance, Vertex AI Agent Builder Search is also able to provide an out of the box solution for &lt;a href=&quot;https://cloud.google.com/generative-ai-app-builder/docs/tune-search&quot;&gt;fine-tuning your search model&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;RAG:&lt;/strong&gt; Design of a RAG system needs to usually go through &lt;a href=&quot;https://cloud.google.com/blog/products/ai-machine-learning/optimizing-rag-retrieval?e=48754805&quot;&gt;multiple optimization iterations&lt;/a&gt; and open source libraries such as &lt;a href=&quot;https://github.com/explodinggradients/ragas&quot;&gt;Ragas&lt;/a&gt; can be of great help to streamline the process. With the latest launch of &lt;a href=&quot;https://cloud.google.com/blog/products/ai-machine-learning/introducing-vertex-ai-rag-engine&quot;&gt;Vertex AI RAG Engine&lt;/a&gt; on GCP, it can then be easier than ever to &lt;a href=&quot;https://github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/rag-engine/rag_engine_evaluation.ipynb&quot;&gt;optimize RAG hyperparameters&lt;/a&gt; such as Chunk Size/Overlap, Vector Distance threshold, etc.. to improve search quality. Some examples of metrics used to measure RAG contextual relevance include: NDCG (Normalized Discounted Cumulative Gain), MRR (Mean Reciprocal Rank), MAP (Mean Average Precision), Precision@K. Once optimized the retrieval metrics, it can then be possible to understand its impact on response quality using the &lt;a href=&quot;https://github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/evaluation/evaluate_rag_gen_ai_evaluation_service_sdk.ipynb&quot;&gt;Evaluation Service API&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Agents:&lt;/strong&gt; As agentic solutions are becoming more and more common in the industry, more complex forms of agent evaluations have been emerging. Overall, the success of an agentic workflow can be measured by its final response (if the agent achieved or not its objectives) or trajectory (sequence of tools the agent invoked to achieve its goals). When evaluating trajectory, metrics such as: exact match, in order match, any-order match, precision, recall, etc. are typically used. Additional information about these types of metrics and data setup for evaluation is available in the &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/models/evaluation-agents&quot;&gt;Vertex AI Gen AI evaluation service documentation&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, when metrics optimization might not be enough, LLM fine-tuning might be the best approach to take in order to tailor off the shelf LLMs for your use case specifics (either through Full fine-tuning or Parameter efficient tuning). Vertex AI provides &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/models/tune-models&quot;&gt;Supervised fine-tuning&lt;/a&gt; support out of the box for different data types such as text, image, audio, and document. Moreover, LLM fine-tuning and evaluation can also be performed directly in &lt;a href=&quot;https://cloud.google.com/blog/products/data-analytics/bigquery-can-now-fine-tune-models-hosted-in-vertex-ai/?e=48754805&quot;&gt;BigQuery&lt;/a&gt; depending on use case needs.&lt;/p&gt;

&lt;h2 id=&quot;evaluation-frameworks&quot;&gt;Evaluation Frameworks&lt;/h2&gt;

&lt;p&gt;Here at Google Cloud, we developed the &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/models/evaluation-overview&quot;&gt;Gen AI evaluation service&lt;/a&gt;. This library is designed to work seamlessly with Vertex AI and support not only the Gemini family but also open 3rd party models. Using the GenAI evaluation service you are able to get out of the box support for a whole collection of metrics maintained by the Google ecosystem while still having the flexibility to bring and define your own custom metrics. This service is additionally designed to help perform specialized tasks such as prompt engineering, RAG and AI Agents optimization.&lt;/p&gt;

&lt;p&gt;On top of this, Vertex AI also supports pairwise model-based evaluation through &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/models/side-by-side-eval&quot;&gt;AutoSxS&lt;/a&gt; (with an LLM autorater).&lt;/p&gt;

&lt;p&gt;Finally, if you looking to kickstart your GenAI project on GCP, another great resource to look into is the “&lt;a href=&quot;https://github.com/GoogleCloudPlatform/agent-starter-pack&quot;&gt;Agent Starter Pack&lt;/a&gt;”, an open source repository providing templates for common GenAI tasks on GCP, including how to evaluate Generative AI applications using tools like &lt;a href=&quot;https://cloud.google.com/vertex-ai/generative-ai/docs/models/evaluation-overview&quot;&gt;Gen AI evaluation service&lt;/a&gt; and &lt;a href=&quot;https://cloud.google.com/vertex-ai/docs/experiments/intro-vertex-ai-experiments&quot;&gt;Vertex AI Experiments&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;open-source-alternatives&quot;&gt;Open Source Alternatives&lt;/h3&gt;

&lt;p&gt;With the widespread adoption of LLMs, a wealth of libraries have been developed over the last few years in order to bridge the evaluation gap. Some notable examples include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/confident-ai/deepeval&quot;&gt;DeepEval&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/truera/trulens&quot;&gt;TruLens&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/comet-ml/opik&quot;&gt;Opik&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/guardrails-ai/guardrails&quot;&gt;Guardrails AI&lt;/a&gt; (additional information about guardrails for LLMs and other caveats can be found &lt;a href=&quot;https://towardsdatascience.com/llms-pitfalls-7a33de009638&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, other libraries focused also on traditional Machine Learning evaluation tasks have been expanded to include also LLM capabilities:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://mlflow.org/&quot;&gt;MLFlow&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://huggingface.co/docs/evaluate/en/index&quot;&gt;Hugging Face Evaluate&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/deepchecks/deepchecks&quot;&gt;Deepchecks&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given the open source nature of these frameworks, they can all be used as part of your development process on GCP with any of the models available on Model Garden.&lt;/p&gt;

&lt;h2 id=&quot;best-practices&quot;&gt;Best Practices&lt;/h2&gt;

&lt;p&gt;To summarize, some common best practices to follow in an evaluation system include (Figure 5):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Match metrics to real world needs and make them as straightforward and consistent as possible.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Routinely monitor and create alert systems on key metrics to prevent model performance to degrade for too long unnoticed.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Regularly benchmark performance against other models and perform unit testing on outputs.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Whenever using humans in evaluation, make sure to only work with domain experts that can help steer the model in the right direction.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Perform adversarial attack tests to try to break your own model and discover edge case failures (e.g. Perturbation Testing).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Ensure LLMs predictions are as repeatable as possible (e.g. use low temperature and fixed seeds).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/3200/0*Y0thojPSAvJf8HK7&quot; alt=&quot;Figure 5: Evaluation Pipeline Example (Image by Author).&quot; /&gt;&lt;br /&gt;Figure 5: Evaluation Pipeline Example (Image by Author).&lt;/p&gt;

&lt;p&gt;For an in-depth guide on evaluation, feel free to refer to the &lt;a href=&quot;https://github.com/huggingface/evaluation-guidebook/tree/main&quot;&gt;Hugging Face Evaluation Handbook&lt;/a&gt;.&lt;/p&gt;
</description>
				<pubDate>Sun, 13 Apr 2025 00:00:00 +0000</pubDate>
				<link>https://ppiconsulting.dev//blog/blog90/</link>
				<guid isPermaLink="true">https://ppiconsulting.dev//blog/blog90/</guid>
			</item>
		
	</channel>
</rss>