Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

☁️ Google Cloud CES Example Terraform Module

Provisions a single CES few-shot example conversation (google_ces_example) — targeting hashicorp/google ~> 7.0 on Terraform >= 1.12.0.

Terraform Provider Module Version Module Type Resource Count Posture


🧩 Overview

  • 💬 Manages one CES example (google_ces_example) — a sample user/agent conversation used as a few-shot example to steer agent behavior.
  • 🧩 Each message chunk is one of 6 mutually exclusive types (text, updated_variables, agent_transfer, image, tool_call, tool_response), enforced at plan time.
  • ⚠️ Examples can silently become invalid if a referenced agent/tool/toolset is later deleted — monitor the invalid output.

💡 Why it matters: Few-shot examples directly shape how an agent responds in ambiguous situations. Enforcing the chunk one-of at plan time, and surfacing the invalid output, catches both structural mistakes and silent drift from deleted dependencies.


❤️ Support this project

If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:

Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!


🗺️ Where this fits

flowchart LR
 APP["terraform-google-ces-app\n(google_ces_app)"]:::keystone
 AGENT["terraform-google-ces-agent\n(google_ces_agent)"]:::neutral
 TOOL["terraform-google-ces-tool\n(google_ces_tool)"]:::neutral
 TOOLSET["terraform-google-ces-toolset\n(google_ces_toolset)"]:::neutral
 EXAMPLE["terraform-google-ces-example\n(google_ces_example)"]:::this

 APP -->|"id to app (required, full name)"| EXAMPLE
 AGENT -.->|"id to entry_agent / agent_transfer.target_agent (optional)"| EXAMPLE
 TOOL -.->|"id to tool_call.tool / tool_response.tool (optional)"| EXAMPLE
 TOOLSET -.->|"id to toolset_tool.toolset (optional)"| EXAMPLE

 classDef this fill:#4285F4,color:#ffffff,stroke:#333333
 classDef keystone fill:#174EA6,color:#ffffff,stroke:#333333
 classDef neutral fill:#E8EAED,color:#202124,stroke:#999999
Loading

Validated via the Mermaid Chart MCP before embedding.


🧬 What this builds

flowchart LR
 subgraph Inputs["Inputs"]
 I1["app, location,\nexample_id, display_name"]
 I2["entry_agent,\nmessages (6-way chunk union)"]
 I3["deletion_policy, timeouts"]
 end

 THIS["google_ces_example.this"]:::this

 subgraph Outputs["Outputs"]
 O1["id, name, example_id"]
 O2["create_time, update_time,\netag, invalid"]
 end

 I1 --> THIS
 I2 --> THIS
 I3 --> THIS
 THIS --> O1
 THIS --> O2

 classDef this fill:#4285F4,color:#ffffff,stroke:#333333
Loading

Resource inventory: one keystone resource, google_ces_example.this. No for_each-managed children — messages/chunks are dynamic-rendered nested blocks, not separate resources (see SCOPE.md).


✅ Provider / Versions

Terraform >= 1.12.0
hashicorp/google ~> 7.0
Provider block None — the caller configures google (ADC, WIF, or a service account key per our authentication model)

Schema notes that bite:

  • app consumes the FULL resource name, CONFIRMED — but the same live doc's own embedded sibling resources use the bare app_id for their own app argument, a genuine contradiction even within one doc file (see SCOPE.md).
  • Each chunks entry is a 6-way union, enforced via validation.
  • Examples can silently become invalid if a referenced resource is deleted.
  • No labels, no self_link.

🔑 Required IAM Roles

  • roles/ces.admin (or a narrower example-administration role) on the target project.

☁️ GCP Prerequisites

  • ces.googleapis.com enabled.
  • The target terraform-google-ces-app must already exist.

📁 Module Structure

terraform-google-ces-example/
├── providers.tf # required_providers + required_version — no provider {} block
├── variables.tf # google_ces_example.this schema — messages/chunks 6-way one-of
├── main.tf # google_ces_example.this — the sole keystone resource
├── outputs.tf # id, name, example_id — no self_link (none exists)
├── README.md # this file
├── SCOPE.md # lightweight standalone scope
└── examples/
 └── basic/ # smallest real call

⚙️ Quick Start

module "example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "greeting-example"
  display_name = "Greeting Example"

  messages = [
    { role = "user", chunks = [{ text = "Hi, can you help me with my account?" }] },
    { role = "agent", chunks = [{ text = "Of course! What would you like help with today?" }] },
  ]
}

🔌 Cross-Module Contract

Consumes

Input Type Source module
app string terraform-google-ces-app (required, CONFIRMED full name .id)
entry_agent string, optional terraform-google-ces-agent (CONFIRMED-by-format .id)
messages[].chunks[].agent_transfer.target_agent string, optional terraform-google-ces-agent
messages[].chunks[].tool_call.tool / .tool_response.tool string, optional terraform-google-ces-tool
messages[].chunks[].*.toolset_tool.toolset string, optional terraform-google-ces-toolset

Emits

Output Description
id Terraform-internal id
name Computed resource name
example_id Bare example ID segment
create_time / update_time Timestamps
etag Read-modify-write etag
invalid Whether the example has become invalid (a referenced resource was deleted)

📚 Example Library

1 · Minimal text conversation
module "greeting_example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "greeting-example"
  display_name = "Greeting Example"

  messages = [
    { role = "user", chunks = [{ text = "Hi, can you help me with my account?" }] },
    { role = "agent", chunks = [{ text = "Of course! What would you like help with today?" }] },
  ]
}
2 · Example with an explicit entry_agent
module "loan_entry_example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "loan-entry-example"
  display_name = "Loan Entry Example"
  entry_agent  = module.loan_agent.id

  messages = [
    { role = "user", chunks = [{ text = "I want to check my loan status." }] },
  ]
}
3 · Tool call and tool response chunks
module "tool_call_example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "account-lookup-example"
  display_name = "Account Lookup Example"

  messages = [
    { role = "user", chunks = [{ text = "What's my account balance?" }] },
    {
      role = "agent"
      chunks = [
        {
          tool_call = {
            id   = "call-1"
            tool = module.account_lookup_tool.id
            args = jsonencode({ account_id = "12345" })
          }
        },
      ]
    },
    {
      role = "agent"
      chunks = [
        {
          tool_response = {
            id       = "call-1"
            tool     = module.account_lookup_tool.id
            response = jsonencode({ output = { balance = "1000.00" } })
          }
        },
      ]
    },
    { role = "agent", chunks = [{ text = "Your account balance is $1,000.00." }] },
  ]
}
4 · Toolset-derived tool call
module "toolset_tool_example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "crm-lookup-example"
  display_name = "CRM Lookup Example"

  messages = [
    {
      role = "agent"
      chunks = [
        {
          tool_call = {
            id = "call-1"
            toolset_tool = {
              toolset = module.crm_toolset.id
              tool_id = "get_ticket"
            }
          }
        },
      ]
    },
  ]
}
5 · Agent transfer chunk
module "transfer_example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "transfer-example"
  display_name = "Transfer Example"

  messages = [
    { role = "user", chunks = [{ text = "I need to talk to someone about a mortgage." }] },
    {
      role = "agent"
      chunks = [
        { agent_transfer = { target_agent = module.mortgage_agent.id } },
      ]
    },
  ]
}
6 · Image chunk
module "image_example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "document-upload-example"
  display_name = "Document Upload Example"

  messages = [
    {
      role = "user"
      chunks = [
        { image = { data = filebase64("${path.module}/sample-check.png"), mime_type = "image/png" } },
      ]
    },
  ]
}
7 · Updated variables chunk
module "variable_update_example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "variable-update-example"
  display_name = "Variable Update Example"

  messages = [
    {
      role = "agent"
      chunks = [
        { updated_variables = jsonencode({ member_tier = "PREMIER" }) },
      ]
    },
  ]
}
8 · Multi-turn conversation with mixed roles
module "multi_turn_example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "multi-turn-example"
  display_name = "Multi-Turn Example"

  messages = [
    { role = "user", chunks = [{ text = "Hi" }] },
    { role = "agent", chunks = [{ text = "Hello! How can I help?" }] },
    { role = "user", chunks = [{ text = "I want to pay off my loan early." }] },
    { role = "agent", chunks = [{ text = "I can help with that. Let me look up your loan." }] },
  ]
}
9 · Description for documentation purposes
module "documented_example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "documented-example"
  display_name = "Documented Example"
  description  = "Demonstrates the escalation flow for frustrated members."

  messages = [
    { role = "user", chunks = [{ text = "This is ridiculous, let me talk to a person." }] },
  ]
}
10 · Custom timeouts
module "example_custom_timeouts" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "large-example"
  display_name = "Large Example"

  messages = [
    { role = "user", chunks = [{ text = "Hello" }] },
  ]

  timeouts = {
    create = "10m"
  }
}
11 · Relaxed deletion_policy for a scratch/dev example
module "dev_example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app             = module.app.id
  location        = "us"
  example_id      = "dev-example"
  display_name    = "Dev Example"
  deletion_policy = "DELETE"

  messages = [
    { role = "user", chunks = [{ text = "test" }] },
  ]
}
12 · 🏗️ End-to-end composition
module "app" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-app.git?ref=v1.0.0"

  app_id       = "member-support"
  location     = "us"
  display_name = "Member Support Assistant"
}

module "account_lookup_tool" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-tool.git?ref=v1.0.0"

  app      = module.app.id
  location = "us"
  tool_id  = "account-lookup-tool"

  python_function = {
    name        = "lookup_account"
    python_code = "def lookup_account(account_id: str) -> dict: return {}"
  }
}

module "example" {
  source = "git::https://github.com/microsoftexpert/terraform-google-ces-example.git?ref=v1.0.0"

  app          = module.app.id
  location     = "us"
  example_id   = "account-lookup-example"
  display_name = "Account Lookup Example"

  messages = [
    { role = "user", chunks = [{ text = "What's my account balance?" }] },
    {
      role = "agent"
      chunks = [
        {
          tool_call = {
            id   = "call-1"
            tool = module.account_lookup_tool.id
            args = jsonencode({ account_id = "12345" })
          }
        },
      ]
    },
  ]
}

output "example_invalid" {
  value = module.example.invalid
}

📥 Inputs

Required: app, location, example_id, display_name.

Grouped summary: identity (app, location, example_id, display_name, description, entry_agent), content (messages), operations (deletion_policy, timeouts — no labels on this resource).

Full object schemas

See variables.tf for the complete, verbatim schema.


🧾 Outputs

Output Description Notes
id Terraform-internal id No self_link exists
name Computed resource name Always populated
example_id Bare example ID segment Always populated
create_time / update_time Timestamps Always populated
etag Read-modify-write etag Always populated
invalid Whether the example has become invalid Monitor after deleting any referenced agent/tool/toolset

🧠 Architecture Notes

  • app/location/example_id are force-new.
  • app consumes the FULL resource name here — but note the confirmed within-doc contradiction for embedded sibling resources (see SCOPE.md).
  • Each chunk is a 6-way union, enforced at plan time.
  • Examples silently invalidate when a referenced resource is deleted — apply succeeds, but the example stops being used as a few-shot example. Monitor the invalid output.

🧱 Design Principles

Concern Secure default Opt-out (explicit)
Deletion guard deletion_policy = "PREVENT" (house extension) Caller sets "DELETE" or "ABANDON" explicitly
Chunk correctness Each chunk's 6-way union enforced at plan time N/A — enforced by terraform validate/plan

🚀 Runbook

cd terraform-google-ces-example
terraform init -backend=false
terraform validate
terraform fmt -check

Pin ?ref=v1.0.0 — never a branch. This library is plan-only; a human applies from CI with valid ADC/WIF credentials.


🧪 Testing

terraform validate/fmt -check confirm internal type/reference consistency, formatting, and the per-chunk one-of — they cannot catch GCP API-level rejections or a referenced resource silently invalidating the example after apply. A real terraform plan/apply against a live project, plus periodic monitoring of the invalid output, is the only way to confirm this module's behavior end-to-end over time.


💬 Example Output

$ terraform output

id = "projects/casey-prod/locations/us/apps/member-support/examples/greeting-example"
name = "projects/casey-prod/locations/us/apps/member-support/examples/greeting-example"
example_id = "greeting-example"
invalid = false

🔍 Troubleshooting

Symptom Cause Fix
plan fails: "each chunk must set exactly one of..." A chunk entry set zero or more than one of the 6 selectors Set exactly one selector per chunk
invalid output becomes true after a previously-successful apply A referenced agent/tool/toolset was deleted Update the example to reference a valid resource, or delete the now-invalid example
destroy fails with a deletion-policy error deletion_policy = "PREVENT" (this module's default) Apply once with deletion_policy = "DELETE" or "ABANDON", then run the destroy

🔗 Related Docs

About

Terraform module: terraform-google-ces-example

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages