@intentsolutionsio/jeremy-adk-orchestrator 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,776 @@
1
+ # Jeremy ADK Orchestrator
2
+
3
+ **🎯 VERTEX AI AGENT ENGINE + ADK DEPLOYMENT ONLY**
4
+
5
+ Expert Agent-to-Agent (A2A) protocol manager for communicating with **Vertex AI Agent Development Kit (ADK)** agents deployed on **Agent Engine**.
6
+
7
+ ## ⚠️ Important: What This Plugin Is For
8
+
9
+ **✅ THIS PLUGIN IS FOR:**
10
+ - **ADK agents** deployed to **Vertex AI Agent Engine** (fully-managed runtime)
11
+ - **A2A Protocol** communication between Claude Code and ADK agents
12
+ - **Multi-agent orchestration** with ADK supervisory agents
13
+ - **Python, Java, and Go ADK agents** on Agent Engine
14
+ - Agent Engine features: Code Execution Sandbox, Memory Bank, Sessions
15
+
16
+ **❌ THIS PLUGIN IS NOT FOR:**
17
+ - LangChain agents (use LangSmith)
18
+ - LlamaIndex agents (not ADK compatible)
19
+ - Cloud Run deployments (use `jeremy-genkit-terraform` with `--cloud-run`)
20
+ - Self-hosted agent infrastructure
21
+ - Non-ADK agent frameworks
22
+
23
+ ## Overview
24
+
25
+ This plugin enables Claude Code to communicate with ADK agents deployed on Vertex AI Agent Engine using the standardized A2A (Agent-to-Agent) Protocol. It handles task submission, status checking, session management, and AgentCard discovery for building multi-agent systems.
26
+
27
+ **Key Capabilities:**
28
+ - AgentCard discovery and capability inspection
29
+ - Task submission with structured inputs
30
+ - Session management for Memory Bank persistence
31
+ - Status polling and result retrieval
32
+ - Streaming responses for long-running tasks
33
+ - Multi-agent orchestration with supervisory patterns
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ /plugin install jeremy-adk-orchestrator@claude-code-plugins-plus
39
+ ```
40
+
41
+ ## Prerequisites & Dependencies
42
+
43
+ ### Required Google Cloud Setup
44
+
45
+ **1. Google Cloud Project with APIs Enabled:**
46
+ ```bash
47
+ # Enable required APIs
48
+ gcloud services enable aiplatform.googleapis.com \
49
+ discoveryengine.googleapis.com \
50
+ logging.googleapis.com \
51
+ monitoring.googleapis.com \
52
+ cloudtrace.googleapis.com \
53
+ --project=YOUR_PROJECT_ID
54
+ ```
55
+
56
+ **2. Authentication:**
57
+ ```bash
58
+ # Application Default Credentials
59
+ gcloud auth application-default login
60
+
61
+ # Or use service account
62
+ export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"
63
+ ```
64
+
65
+ **3. Required IAM Permissions:**
66
+ ```yaml
67
+ # Minimum required roles:
68
+ - roles/aiplatform.user # Query Agent Engine resources
69
+ - roles/discoveryengine.admin # Manage agents and sessions
70
+ - roles/logging.viewer # Read agent logs
71
+ - roles/monitoring.viewer # Access metrics
72
+ ```
73
+
74
+ ### Required Python Packages
75
+
76
+ **Install via pip:**
77
+ ```bash
78
+ # Core ADK SDK (required for agent development)
79
+ pip install google-adk>=1.15.1
80
+
81
+ # Vertex AI SDK with Agent Engine support
82
+ pip install google-cloud-aiplatform[agent_engines]>=1.120.0
83
+
84
+ # A2A Protocol SDK (for protocol-level communication)
85
+ pip install a2a-sdk>=0.3.4
86
+
87
+ # HTTP client for REST API calls
88
+ pip install requests>=2.31.0
89
+
90
+ # Observability & Monitoring
91
+ pip install google-cloud-logging>=3.10.0
92
+ pip install google-cloud-monitoring>=2.21.0
93
+ pip install google-cloud-trace>=1.13.0
94
+ ```
95
+
96
+ **All dependencies at once:**
97
+ ```bash
98
+ pip install --upgrade \
99
+ 'google-adk>=1.15.1' \
100
+ 'google-cloud-aiplatform[agent_engines]>=1.120.0' \
101
+ 'a2a-sdk>=0.3.4' \
102
+ 'requests>=2.31.0' \
103
+ 'google-cloud-logging>=3.10.0' \
104
+ 'google-cloud-monitoring>=2.21.0' \
105
+ 'google-cloud-trace>=1.13.0'
106
+ ```
107
+
108
+ ### Agent Engine Management (Python SDK Only)
109
+
110
+ **There is no `gcloud` CLI for Agent Engine.** All management is done via the Python SDK:
111
+
112
+ ```python
113
+ import vertexai
114
+
115
+ client = vertexai.Client(project="YOUR_PROJECT_ID", location="us-central1")
116
+
117
+ # List all deployed agents (reasoning engines)
118
+ for agent in client.agent_engines.list():
119
+ print(f"{agent.display_name}: {agent.resource_name}")
120
+
121
+ # Get a specific agent
122
+ agent = client.agent_engines.get(
123
+ name="projects/YOUR_PROJECT/locations/us-central1/reasoningEngines/12345"
124
+ )
125
+
126
+ # Delete an agent
127
+ # client.agent_engines.delete(name=agent.resource_name)
128
+ ```
129
+
130
+ **Verify SDK Installation:**
131
+ ```bash
132
+ python3 -c "import vertexai; print('Vertex AI SDK ready')"
133
+ python3 -c "import google.adk; print(f'ADK SDK version: {google.adk.__version__}')"
134
+ ```
135
+
136
+ ### ADK Agent Deployment Methods
137
+
138
+ **This plugin works with ADK agents deployed via:**
139
+
140
+ 1. **ADK CLI Deployment:**
141
+ ```bash
142
+ # Install ADK CLI
143
+ pip install google-adk
144
+
145
+ # Deploy agent to Agent Engine (interactive — prompts for project/location)
146
+ adk deploy cloud_run # Deploy to Cloud Run
147
+ # Or deploy via the Python SDK (see method 2 below) for Agent Engine
148
+ ```
149
+
150
+ 2. **Python SDK Deployment:**
151
+ ```python
152
+ from google.adk.agents import Agent
153
+ import vertexai
154
+
155
+ # Define ADK agent
156
+ agent = Agent(
157
+ name="my-adk-agent",
158
+ model="gemini-2.5-flash",
159
+ instruction="Production ADK agent for deployment tasks.",
160
+ tools=[my_tool_function],
161
+ )
162
+
163
+ # Deploy to Agent Engine
164
+ client = vertexai.Client(project=PROJECT_ID, location=LOCATION)
165
+ remote_agent = client.agent_engines.create(
166
+ agent_engine=agent,
167
+ requirements=["google-adk>=1.15.1"],
168
+ display_name="my-adk-agent",
169
+ )
170
+
171
+ print(f"Agent deployed: {remote_agent.resource_name}")
172
+ ```
173
+
174
+ 3. **Terraform Deployment:**
175
+ ```hcl
176
+ resource "google_vertex_ai_reasoning_engine" "adk_agent" {
177
+ display_name = "my-adk-agent"
178
+ region = "us-central1"
179
+
180
+ spec {
181
+ agent_framework = "google-adk" # ← Must specify ADK
182
+
183
+ package_spec {
184
+ pickle_object_gcs_uri = "gs://bucket/agent.pkl"
185
+ python_version = "3.12"
186
+ requirements_gcs_uri = "gs://bucket/requirements.txt"
187
+ }
188
+
189
+ # Agent Engine features
190
+ runtime_config {
191
+ code_execution_config {
192
+ enabled = true
193
+ }
194
+ memory_bank_config {
195
+ enabled = true
196
+ }
197
+ }
198
+ }
199
+ }
200
+ ```
201
+
202
+ ### ❌ NOT Compatible With
203
+
204
+ - **LangChain agents** (different framework, not ADK)
205
+ - **LlamaIndex agents** (not ADK compatible)
206
+ - **Cloud Run deployments** (use `jeremy-genkit-terraform`)
207
+ - **Cloud Functions** (not Agent Engine)
208
+ - **Self-hosted agent infrastructure** (requires Agent Engine runtime)
209
+ - **Non-Google agent frameworks** (Autogen, CrewAI, etc.)
210
+
211
+ ## Features
212
+
213
+ ✅ **AgentCard Discovery**: Automatic capability detection for ADK agents
214
+ ✅ **A2A Protocol Communication**: Standardized task submission and retrieval
215
+ ✅ **Session Management**: Persistent sessions with Memory Bank
216
+ ✅ **Status Polling**: Real-time task status monitoring
217
+ ✅ **Streaming Responses**: Handle long-running agent tasks
218
+ ✅ **Multi-Agent Orchestration**: Supervisory agent patterns
219
+ ✅ **Error Handling**: Retry logic and graceful degradation
220
+ ✅ **Observability**: Integrated logging and tracing
221
+
222
+ ## Components
223
+
224
+ ### Agent
225
+ - **a2a-protocol-manager**: A2A protocol expert with task orchestration capabilities
226
+
227
+ ### Skills (Auto-Activating)
228
+ - **a2a-protocol-manager**: Triggers on "communicate with ADK agent", "orchestrate agents", "send task to agent"
229
+ - **Tool Permissions**: Read, Bash, Write, Grep (for agent communication)
230
+ - **Version**: 1.0.0 (2026 schema compliant)
231
+
232
+ ## Quick Start
233
+
234
+ ### Natural Language Activation
235
+
236
+ Simply mention what you need:
237
+
238
+ ```
239
+ "Communicate with the ADK agent at [endpoint]"
240
+ "Send a task to the sentiment-analysis agent"
241
+ "Orchestrate multiple ADK agents for this workflow"
242
+ "Check status of task ID abc-123"
243
+ "Discover capabilities of the agent at [endpoint]"
244
+ ```
245
+
246
+ The skill auto-activates and handles A2A protocol communication.
247
+
248
+ ## A2A Protocol Architecture
249
+
250
+ ### Communication Flow
251
+
252
+ ```
253
+ Claude Code Plugin
254
+
255
+ AgentCard Discovery
256
+ ↓ GET /.well-known/agent-card
257
+ Agent Metadata (capabilities, skills, schemas)
258
+
259
+ Task Submission (A2A JSON-RPC 2.0)
260
+ ↓ POST / (method: "tasks/send")
261
+ Task Created (task id, status)
262
+
263
+ Task Status
264
+ ↓ POST / (method: "tasks/get")
265
+ Task State (submitted, working, completed, failed)
266
+
267
+ Result in task artifacts
268
+ ↓ parts[].text / parts[].data
269
+ Agent Output
270
+ ```
271
+
272
+ ### AgentCard Discovery
273
+
274
+ **Discover agent capabilities before invocation:**
275
+
276
+ ```python
277
+ import requests
278
+
279
+ def discover_agent_capabilities(agent_endpoint):
280
+ """
281
+ Fetch AgentCard to understand agent's tools and capabilities.
282
+
283
+ AgentCard contains:
284
+ - name: Agent identifier
285
+ - description: What the agent does
286
+ - tools: Available tools the agent can use
287
+ - input_schema: Expected input format
288
+ - output_schema: Expected output format
289
+ """
290
+ response = requests.get(f"{agent_endpoint}/.well-known/agent-card")
291
+ agent_card = response.json()
292
+
293
+ print(f"Agent: {agent_card['name']}")
294
+ print(f"Description: {agent_card['description']}")
295
+ print(f"Available tools: {[tool['name'] for tool in agent_card['tools']]}")
296
+
297
+ return agent_card
298
+
299
+ # Example
300
+ agent_card = discover_agent_capabilities(
301
+ "https://us-central1-aiplatform.googleapis.com/v1/projects/my-project/locations/us-central1/reasoningEngines/my-agent"
302
+ )
303
+ ```
304
+
305
+ ### Task Submission
306
+
307
+ **Submit a task to an ADK agent via A2A JSON-RPC:**
308
+
309
+ ```python
310
+ import requests
311
+ import json
312
+
313
+ def submit_task(agent_endpoint, message_text, task_id=None):
314
+ """
315
+ Submit a task to an ADK agent via A2A protocol (JSON-RPC 2.0).
316
+
317
+ Args:
318
+ agent_endpoint: A2A-compliant agent URL
319
+ message_text: Natural language instruction
320
+ task_id: Optional task ID (generated if not provided)
321
+
322
+ Returns:
323
+ task_id: Unique identifier for tracking task status
324
+ """
325
+ import uuid
326
+ task_id = task_id or str(uuid.uuid4())
327
+
328
+ payload = {
329
+ "jsonrpc": "2.0",
330
+ "method": "tasks/send",
331
+ "params": {
332
+ "id": task_id,
333
+ "message": {
334
+ "role": "user",
335
+ "parts": [{"text": message_text}],
336
+ },
337
+ },
338
+ "id": f"req-{task_id}",
339
+ }
340
+
341
+ response = requests.post(
342
+ agent_endpoint,
343
+ json=payload,
344
+ headers={
345
+ "Content-Type": "application/json",
346
+ "Authorization": f"Bearer {get_access_token()}",
347
+ }
348
+ )
349
+
350
+ result = response.json()
351
+ task_status = result.get("result", {}).get("status", {}).get("state")
352
+
353
+ print(f"Task submitted: {task_id}")
354
+ print(f"Status: {task_status}")
355
+
356
+ return task_id
357
+
358
+ # Example
359
+ task_id = submit_task(
360
+ agent_endpoint="https://my-agent.example.com",
361
+ message_text="Analyze sentiment of customer reviews",
362
+ )
363
+ ```
364
+
365
+ ### Status Polling
366
+
367
+ **Monitor task execution via A2A JSON-RPC:**
368
+
369
+ ```python
370
+ import time
371
+
372
+ def poll_task_status(agent_endpoint, task_id, timeout=300):
373
+ """
374
+ Poll task status until completion or timeout.
375
+
376
+ A2A task states:
377
+ - submitted: Task queued
378
+ - working: Agent is processing
379
+ - input-required: Agent needs more info
380
+ - completed: Task finished successfully
381
+ - failed: Task encountered error
382
+ - canceled: Task was canceled
383
+ """
384
+ start_time = time.time()
385
+
386
+ while time.time() - start_time < timeout:
387
+ payload = {
388
+ "jsonrpc": "2.0",
389
+ "method": "tasks/get",
390
+ "params": {"id": task_id},
391
+ "id": f"poll-{int(time.time())}",
392
+ }
393
+
394
+ response = requests.post(
395
+ agent_endpoint,
396
+ json=payload,
397
+ headers={
398
+ "Content-Type": "application/json",
399
+ "Authorization": f"Bearer {get_access_token()}",
400
+ }
401
+ )
402
+
403
+ result = response.json().get("result", {})
404
+ state = result.get("status", {}).get("state", "unknown")
405
+ print(f"Status: {state}")
406
+
407
+ if state == "completed":
408
+ return result
409
+ elif state == "failed":
410
+ return result
411
+
412
+ time.sleep(5) # Poll every 5 seconds
413
+
414
+ raise TimeoutError(f"Task {task_id} did not complete within {timeout}s")
415
+
416
+ # Example
417
+ result = poll_task_status(agent_endpoint, task_id)
418
+
419
+ state = result.get("status", {}).get("state")
420
+ if state == "completed":
421
+ print("Task completed successfully!")
422
+ artifacts = result.get("artifacts", [])
423
+ for artifact in artifacts:
424
+ for part in artifact.get("parts", []):
425
+ print(f"Output: {part.get('text', '')}")
426
+ else:
427
+ print(f"Task failed: {result.get('status', {}).get('message')}")
428
+ ```
429
+
430
+ ### Result Retrieval
431
+
432
+ **Get agent output (included in tasks/get response):**
433
+
434
+ In A2A, results are returned as `artifacts` in the `tasks/get` response -- there is no separate result endpoint. Each artifact contains `parts` (text, data, or file).
435
+
436
+ ```python
437
+ def get_task_result(agent_endpoint, task_id):
438
+ """
439
+ Retrieve completed task output via tasks/get.
440
+
441
+ Results are in the 'artifacts' field of the task response.
442
+ Each artifact has 'parts' with text or structured data.
443
+ """
444
+ payload = {
445
+ "jsonrpc": "2.0",
446
+ "method": "tasks/get",
447
+ "params": {"id": task_id},
448
+ "id": f"result-{task_id}",
449
+ }
450
+
451
+ response = requests.post(
452
+ agent_endpoint,
453
+ json=payload,
454
+ headers={
455
+ "Content-Type": "application/json",
456
+ "Authorization": f"Bearer {get_access_token()}",
457
+ }
458
+ )
459
+
460
+ task = response.json().get("result", {})
461
+ artifacts = task.get("artifacts", [])
462
+
463
+ print("Agent Output:")
464
+ for artifact in artifacts:
465
+ for part in artifact.get("parts", []):
466
+ if "text" in part:
467
+ print(part["text"])
468
+ elif "data" in part:
469
+ print(json.dumps(part["data"], indent=2))
470
+
471
+ return artifacts
472
+
473
+ # Example
474
+ artifacts = get_task_result(agent_endpoint, task_id)
475
+ ```
476
+
477
+ ## Multi-Agent Orchestration
478
+
479
+ ### Supervisory Agent Pattern
480
+
481
+ **Orchestrate multiple ADK agents:**
482
+
483
+ ```python
484
+ class SupervisoryOrchestrator:
485
+ """
486
+ Coordinate multiple ADK agents for complex workflows.
487
+
488
+ Pattern: Supervisor delegates tasks to specialized agents.
489
+ """
490
+
491
+ def __init__(self, agents_config):
492
+ self.agents = {
493
+ name: agent_config
494
+ for name, agent_config in agents_config.items()
495
+ }
496
+
497
+ def orchestrate(self, workflow_input):
498
+ """
499
+ Execute multi-step workflow across agents.
500
+ """
501
+ results = {}
502
+ session_id = None # Shared session for Memory Bank
503
+
504
+ # Step 1: Data extraction agent
505
+ task_id, session_id = submit_task(
506
+ self.agents['extractor']['endpoint'],
507
+ {"input": workflow_input},
508
+ session_id=session_id
509
+ )
510
+ status = poll_task_status(self.agents['extractor']['endpoint'], task_id)
511
+ results['extracted_data'] = get_task_result(
512
+ self.agents['extractor']['endpoint'],
513
+ task_id
514
+ )
515
+
516
+ # Step 2: Analysis agent (uses extracted data)
517
+ task_id, session_id = submit_task(
518
+ self.agents['analyzer']['endpoint'],
519
+ {"data": results['extracted_data']},
520
+ session_id=session_id # Continue same session
521
+ )
522
+ status = poll_task_status(self.agents['analyzer']['endpoint'], task_id)
523
+ results['analysis'] = get_task_result(
524
+ self.agents['analyzer']['endpoint'],
525
+ task_id
526
+ )
527
+
528
+ # Step 3: Synthesis agent (combines results)
529
+ task_id, session_id = submit_task(
530
+ self.agents['synthesizer']['endpoint'],
531
+ {
532
+ "extracted": results['extracted_data'],
533
+ "analyzed": results['analysis']
534
+ },
535
+ session_id=session_id
536
+ )
537
+ status = poll_task_status(self.agents['synthesizer']['endpoint'], task_id)
538
+ results['final_output'] = get_task_result(
539
+ self.agents['synthesizer']['endpoint'],
540
+ task_id
541
+ )
542
+
543
+ return results
544
+
545
+ # Usage
546
+ orchestrator = SupervisoryOrchestrator({
547
+ 'extractor': {'endpoint': 'https://...'},
548
+ 'analyzer': {'endpoint': 'https://...'},
549
+ 'synthesizer': {'endpoint': 'https://...'}
550
+ })
551
+
552
+ workflow_results = orchestrator.orchestrate({
553
+ "document": "Customer feedback report...",
554
+ "analysis_type": "sentiment_and_topics"
555
+ })
556
+ ```
557
+
558
+ ## Observability & Monitoring
559
+
560
+ ### Cloud Trace Integration
561
+
562
+ **Enable distributed tracing for A2A calls:**
563
+
564
+ ```python
565
+ from opentelemetry import trace
566
+ from opentelemetry.sdk.trace import TracerProvider
567
+ from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
568
+
569
+ # Configure Cloud Trace
570
+ trace.set_tracer_provider(TracerProvider())
571
+ cloud_trace_exporter = CloudTraceSpanExporter()
572
+ tracer = trace.get_tracer(__name__)
573
+
574
+ # Instrument A2A protocol calls
575
+ with tracer.start_as_current_span("a2a_task_submission") as span:
576
+ span.set_attribute("agent.endpoint", agent_endpoint)
577
+ span.set_attribute("task.type", "sentiment_analysis")
578
+
579
+ task_id, session_id = submit_task(agent_endpoint, task_input)
580
+
581
+ span.set_attribute("task.id", task_id)
582
+ span.set_attribute("session.id", session_id)
583
+
584
+ with tracer.start_as_current_span("a2a_task_polling") as span:
585
+ status = poll_task_status(agent_endpoint, task_id)
586
+
587
+ span.set_attribute("task.status", status['state'])
588
+ span.set_attribute("task.latency_ms", status.get('latency'))
589
+ ```
590
+
591
+ ### Cloud Logging
592
+
593
+ **Query orchestration logs:**
594
+
595
+ ```bash
596
+ # View all A2A protocol calls
597
+ gcloud logging read "jsonPayload.component=a2a_protocol AND resource.type=aiplatform.googleapis.com/Agent" \
598
+ --project=YOUR_PROJECT_ID \
599
+ --limit=100 \
600
+ --format=json
601
+
602
+ # Filter by agent endpoint
603
+ gcloud logging read "jsonPayload.agent_endpoint=~'my-agent' AND severity>=WARNING" \
604
+ --project=YOUR_PROJECT_ID \
605
+ --limit=50
606
+ ```
607
+
608
+ ### Custom Metrics
609
+
610
+ **Track orchestration performance:**
611
+
612
+ ```python
613
+ from google.cloud import monitoring_v3
614
+
615
+ def record_orchestration_metrics(
616
+ task_id: str,
617
+ latency_ms: float,
618
+ success: bool
619
+ ):
620
+ """Record custom metrics for A2A orchestration."""
621
+ client = monitoring_v3.MetricServiceClient()
622
+ project_name = f"projects/{PROJECT_ID}"
623
+
624
+ # Record task latency
625
+ series = monitoring_v3.TimeSeries()
626
+ series.metric.type = "custom.googleapis.com/adk/orchestration/latency"
627
+ series.metric.labels['task_id'] = task_id
628
+
629
+ point = monitoring_v3.Point()
630
+ point.value.double_value = latency_ms
631
+ point.interval.end_time.seconds = int(time.time())
632
+ series.points = [point]
633
+
634
+ client.create_time_series(name=project_name, time_series=[series])
635
+
636
+ # Record success/failure
637
+ series = monitoring_v3.TimeSeries()
638
+ series.metric.type = "custom.googleapis.com/adk/orchestration/success_rate"
639
+
640
+ point = monitoring_v3.Point()
641
+ point.value.int64_value = 1 if success else 0
642
+ point.interval.end_time.seconds = int(time.time())
643
+ series.points = [point]
644
+
645
+ client.create_time_series(name=project_name, time_series=[series])
646
+ ```
647
+
648
+ ## Storage Integration
649
+
650
+ ### BigQuery Export
651
+
652
+ **Export orchestration logs to BigQuery:**
653
+
654
+ ```python
655
+ from google.cloud import bigquery
656
+
657
+ def export_orchestration_history():
658
+ """Export A2A protocol calls to BigQuery for analysis."""
659
+ client = bigquery.Client(project=PROJECT_ID)
660
+
661
+ # Create table for orchestration logs
662
+ schema = [
663
+ bigquery.SchemaField("timestamp", "TIMESTAMP"),
664
+ bigquery.SchemaField("task_id", "STRING"),
665
+ bigquery.SchemaField("session_id", "STRING"),
666
+ bigquery.SchemaField("agent_endpoint", "STRING"),
667
+ bigquery.SchemaField("status", "STRING"),
668
+ bigquery.SchemaField("latency_ms", "FLOAT"),
669
+ bigquery.SchemaField("input_tokens", "INTEGER"),
670
+ bigquery.SchemaField("output_tokens", "INTEGER"),
671
+ bigquery.SchemaField("error_message", "STRING"),
672
+ ]
673
+
674
+ table_ref = client.dataset("agent_analytics").table("orchestration_logs")
675
+ table = bigquery.Table(table_ref, schema=schema)
676
+ table = client.create_table(table, exists_ok=True)
677
+
678
+ print(f"Created table: {table.project}.{table.dataset_id}.{table.table_id}")
679
+ ```
680
+
681
+ **Query orchestration patterns:**
682
+
683
+ ```sql
684
+ -- Most commonly orchestrated agents
685
+ SELECT
686
+ agent_endpoint,
687
+ COUNT(*) as total_calls,
688
+ AVG(latency_ms) as avg_latency,
689
+ SUM(CASE WHEN status = 'COMPLETED' THEN 1 ELSE 0 END) / COUNT(*) as success_rate
690
+ FROM `project.agent_analytics.orchestration_logs`
691
+ WHERE timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
692
+ GROUP BY agent_endpoint
693
+ ORDER BY total_calls DESC;
694
+
695
+ -- Multi-agent workflow analysis
696
+ SELECT
697
+ session_id,
698
+ COUNT(DISTINCT agent_endpoint) as num_agents,
699
+ SUM(latency_ms) as total_latency,
700
+ ARRAY_AGG(agent_endpoint ORDER BY timestamp) as agent_sequence
701
+ FROM `project.agent_analytics.orchestration_logs`
702
+ WHERE session_id IS NOT NULL
703
+ AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 DAY)
704
+ GROUP BY session_id
705
+ HAVING num_agents > 1
706
+ ORDER BY total_latency DESC;
707
+ ```
708
+
709
+ ## Use Cases
710
+
711
+ ### Single Agent Communication
712
+ ```
713
+ "Communicate with the sentiment-analysis ADK agent at [endpoint]"
714
+ "Send customer reviews to the analysis agent"
715
+ ```
716
+
717
+ ### Multi-Agent Workflows
718
+ ```
719
+ "Orchestrate data extraction, analysis, and synthesis agents"
720
+ "Run a multi-step workflow across these ADK agents: [list]"
721
+ ```
722
+
723
+ ### Session Management
724
+ ```
725
+ "Continue the conversation with session ID abc-123"
726
+ "Create a new session with Memory Bank persistence"
727
+ ```
728
+
729
+ ### Status Monitoring
730
+ ```
731
+ "Check status of task ID xyz-456"
732
+ "Monitor the long-running analysis task"
733
+ ```
734
+
735
+ ### Capability Discovery
736
+ ```
737
+ "Discover capabilities of the agent at [endpoint]"
738
+ "What tools does this ADK agent support?"
739
+ ```
740
+
741
+ ## Integration with Other Plugins
742
+
743
+ ### jeremy-vertex-engine
744
+ - Orchestrator invokes agents → Inspector validates health
745
+ - A2A protocol calls → Performance monitoring
746
+
747
+ ### jeremy-vertex-validator
748
+ - Validator checks agent code → Orchestrator deploys and tests
749
+ - Pre-deployment validation → Runtime orchestration
750
+
751
+ ### jeremy-adk-terraform
752
+ - Terraform provisions agents → Orchestrator manages communication
753
+ - Infrastructure deployment → Runtime coordination
754
+
755
+ ## Requirements
756
+
757
+ - Google Cloud Project with Vertex AI enabled
758
+ - ADK agents deployed on Agent Engine (NOT Cloud Run)
759
+ - Appropriate IAM permissions for A2A protocol
760
+ - Python 3.10+ (for ADK SDK compatibility)
761
+ - Cloud Logging enabled (for observability features)
762
+ - Cloud Monitoring enabled (for custom metrics)
763
+ - BigQuery dataset (for analytics integration - optional)
764
+
765
+ ## License
766
+
767
+ MIT
768
+
769
+ ## Support
770
+
771
+ - Issues: https://github.com/jeremylongshore/claude-code-plugins/issues
772
+ - Discussions: https://github.com/jeremylongshore/claude-code-plugins/discussions
773
+
774
+ ## Version
775
+
776
+ 2.1.0 (2026) - SDK accuracy fixes, expanded error/example references, corrected imports